Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: end session #35

Merged
merged 5 commits into from Jul 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 10 additions & 3 deletions example/server/default/default.go
Expand Up @@ -15,20 +15,27 @@ import (

func main() {
ctx := context.Background()
port := "9998"
config := &op.Config{
Issuer: "http://localhost:9998/",
CryptoKey: sha256.Sum256([]byte("test")),
Port: "9998",
}
storage := mock.NewAuthStorage()
handler, err := op.NewDefaultOP(ctx, config, storage, op.WithCustomTokenEndpoint(op.NewEndpoint("test")))
if err != nil {
log.Fatal(err)
}
router := handler.HttpHandler().Handler.(*mux.Router)
router := handler.HttpHandler().(*mux.Router)
router.Methods("GET").Path("/login").HandlerFunc(HandleLogin)
router.Methods("POST").Path("/login").HandlerFunc(HandleCallback)
op.Start(ctx, handler)
server := &http.Server{
Addr: ":" + port,
Handler: router,
}
err = server.ListenAndServe()
if err != nil {
log.Fatal(err)
}
<-ctx.Done()
}

Expand Down
2 changes: 0 additions & 2 deletions pkg/op/config.go
Expand Up @@ -16,8 +16,6 @@ type Configuration interface {
KeysEndpoint() Endpoint

AuthMethodPostSupported() bool

Port() string
}

func ValidateIssuer(issuer string) error {
Expand Down
19 changes: 6 additions & 13 deletions pkg/op/default_op.go
Expand Up @@ -10,6 +10,7 @@ import (
"gopkg.in/square/go-jose.v2"

"github.com/caos/logging"

"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/pkg/rp"
)
Expand Down Expand Up @@ -45,7 +46,7 @@ type DefaultOP struct {
signer Signer
verifier rp.Verifier
crypto Crypto
http *http.Server
http http.Handler
decoder *schema.Decoder
encoder *schema.Encoder
interceptor HttpInterceptor
Expand All @@ -64,7 +65,6 @@ type Config struct {
// IdTokenSigningAlgValuesSupported: []string{keys.SigningAlgorithm},
// SubjectTypesSupported: []string{"public"},
// TokenEndpointAuthMethodsSupported:
Port string
}

type endpoints struct {
Expand Down Expand Up @@ -180,13 +180,10 @@ func NewDefaultOP(ctx context.Context, config *Config, storage Storage, opOpts .
p.signer = NewDefaultSigner(ctx, storage, keyCh)
go p.ensureKey(ctx, storage, keyCh, p.timer)

p.verifier = rp.NewDefaultVerifier(config.Issuer, "", p, rp.WithIgnoreAudience())
p.verifier = rp.NewDefaultVerifier(config.Issuer, "", p, rp.WithIgnoreAudience(), rp.WithIgnoreExpiration())

p.http = CreateRouter(p, p.interceptor)

router := CreateRouter(p, p.interceptor)
p.http = &http.Server{
Addr: ":" + config.Port,
Handler: router,
}
p.decoder = schema.NewDecoder()
p.decoder.IgnoreUnknownKeys(true)

Expand Down Expand Up @@ -225,11 +222,7 @@ func (p *DefaultOP) AuthMethodPostSupported() bool {
return true //TODO: config
}

func (p *DefaultOP) Port() string {
return p.config.Port
}

func (p *DefaultOP) HttpHandler() *http.Server {
func (p *DefaultOP) HttpHandler() http.Handler {
return p.http
}

Expand Down
22 changes: 1 addition & 21 deletions pkg/op/op.go
@@ -1,12 +1,10 @@
package op

import (
"context"
"net/http"

"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"

"github.com/caos/oidc/pkg/oidc"
)
Expand All @@ -26,7 +24,7 @@ type OpenIDProvider interface {
HandleUserinfo(w http.ResponseWriter, r *http.Request)
HandleEndSession(w http.ResponseWriter, r *http.Request)
HandleKeys(w http.ResponseWriter, r *http.Request)
HttpHandler() *http.Server
HttpHandler() http.Handler
}

type HttpInterceptor func(http.HandlerFunc) http.HandlerFunc
Expand Down Expand Up @@ -54,21 +52,3 @@ func CreateRouter(o OpenIDProvider, h HttpInterceptor) *mux.Router {
router.HandleFunc(o.KeysEndpoint().Relative(), o.HandleKeys)
return router
}

func Start(ctx context.Context, o OpenIDProvider) {
go func() {
<-ctx.Done()
err := o.HttpHandler().Shutdown(ctx)
if err != nil {
logrus.Error("graceful shutdown of oidc server failed")
}
}()

go func() {
err := o.HttpHandler().ListenAndServe()
if err != nil {
logrus.Panicf("oidc server serve failed: %v", err)
}
}()
logrus.Infof("oidc server is listening on %s", o.Port())
}
9 changes: 8 additions & 1 deletion pkg/op/session.go
Expand Up @@ -27,7 +27,11 @@ func EndSession(w http.ResponseWriter, r *http.Request, ender SessionEnder) {
RequestError(w, r, err)
return
}
err = ender.Storage().TerminateSession(r.Context(), session.UserID, session.Client.GetID())
var clientID string
if session.Client != nil {
clientID = session.Client.GetID()
}
err = ender.Storage().TerminateSession(r.Context(), session.UserID, clientID)
if err != nil {
RequestError(w, r, ErrServerError("error terminating session"))
return
Expand All @@ -50,6 +54,9 @@ func ParseEndSessionRequest(r *http.Request, decoder *schema.Decoder) (*oidc.End

func ValidateEndSessionRequest(ctx context.Context, req *oidc.EndSessionRequest, ender SessionEnder) (*EndSessionRequest, error) {
session := new(EndSessionRequest)
if req.IdTokenHint == "" {
return session, nil
}
claims, err := ender.IDTokenVerifier().Verify(ctx, "", req.IdTokenHint)
if err != nil {
return nil, ErrInvalidRequest("id_token_hint invalid")
Expand Down
26 changes: 18 additions & 8 deletions pkg/rp/default_verifier.go
Expand Up @@ -46,13 +46,20 @@ func NewDefaultVerifier(issuer, clientID string, keySet oidc.KeySet, confOpts ..
return &DefaultVerifier{config: conf, keySet: keySet}
}

//WithIgnoreAudience will turn off audience claim (should only be used for id_token_hints)
//WithIgnoreAudience will turn off validation for audience claim (should only be used for id_token_hints)
func WithIgnoreAudience() func(*verifierConfig) {
return func(conf *verifierConfig) {
conf.ignoreAudience = true
}
}

//WithIgnoreExpiration will turn off validation for expiration claim (should only be used for id_token_hints)
func WithIgnoreExpiration() func(*verifierConfig) {
return func(conf *verifierConfig) {
conf.ignoreExpiration = true
}
}

//WithIgnoreIssuedAt will turn off iat claim verification
func WithIgnoreIssuedAt() func(*verifierConfig) {
return func(conf *verifierConfig) {
Expand Down Expand Up @@ -108,6 +115,7 @@ type verifierConfig struct {
clientID string
nonce string
ignoreAudience bool
ignoreExpiration bool
iat *iatConfig
acr ACRVerifier
maxAge time.Duration
Expand Down Expand Up @@ -275,10 +283,10 @@ func (v *DefaultVerifier) checkSignature(ctx context.Context, idTokenString stri
return "", err
}
if len(jws.Signatures) == 0 {
return "", nil //TODO: error
return "", ErrSignatureMissing()
}
if len(jws.Signatures) > 1 {
return "", nil //TODO: error
return "", ErrSignatureMultiple()
}
sig := jws.Signatures[0]
supportedSigAlgs := v.config.supportedSignAlgs
Expand All @@ -292,16 +300,18 @@ func (v *DefaultVerifier) checkSignature(ctx context.Context, idTokenString stri
signedPayload, err := v.keySet.VerifySignature(ctx, jws)
if err != nil {
return "", err
//TODO:
}

if !bytes.Equal(signedPayload, payload) {
return "", ErrSignatureInvalidPayload() //TODO: err
return "", ErrSignatureInvalidPayload()
}
return jose.SignatureAlgorithm(sig.Header.Algorithm), nil
}

func (v *DefaultVerifier) checkExpiration(expiration time.Time) error {
if v.config.ignoreExpiration {
return nil
}
expiration = expiration.Round(time.Second)
if !v.now().Before(expiration) {
return ErrExpInvalid(expiration)
Expand Down Expand Up @@ -362,16 +372,16 @@ func (v *DefaultVerifier) decryptToken(tokenString string) (string, error) {
}

func (v *DefaultVerifier) verifyAccessToken(accessToken, atHash string, sigAlgorithm jose.SignatureAlgorithm) error {
if atHash == "" {
return nil //TODO: return error
if accessToken == "" {
return nil
}

actual, err := oidc.ClaimHash(accessToken, sigAlgorithm)
if err != nil {
return err
}
if actual != atHash {
return nil //TODO: error
return ErrAtHash()
}
return nil
}
9 changes: 9 additions & 0 deletions pkg/rp/error.go
Expand Up @@ -40,9 +40,18 @@ var (
ErrAuthTimeToOld = func(maxAge, authTime time.Time) *validationError {
return ValidationError("Auth Time of token must not be older than %v, but was %v (%v to old)", maxAge, authTime, maxAge.Sub(authTime))
}
ErrSignatureMissing = func() *validationError {
return ValidationError("id_token does not contain a signature")
}
ErrSignatureMultiple = func() *validationError {
return ValidationError("id_token contains multiple signatures")
}
ErrSignatureInvalidPayload = func() *validationError {
return ValidationError("Signature does not match Payload")
}
ErrAtHash = func() *validationError {
return ValidationError("at_hash does not correspond to access token")
}
)

func ValidationError(message string, args ...interface{}) *validationError {
Expand Down