Skip to content

Commit

Permalink
feat: add CanTerminateSessionFromRequest interface (#418)
Browse files Browse the repository at this point in the history
To support access to all claims in the id_token_hint (like a sessionID), this PR adds a new (optional) add-on interface to the Storage.
  • Loading branch information
livio-a committed Jul 18, 2023
1 parent 4c844da commit be89c3b
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
12 changes: 9 additions & 3 deletions pkg/op/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,17 @@ func EndSession(w http.ResponseWriter, r *http.Request, ender SessionEnder) {
RequestError(w, r, err)
return
}
err = ender.Storage().TerminateSession(r.Context(), session.UserID, session.ClientID)
redirect := session.RedirectURI
if fromRequest, ok := ender.Storage().(CanTerminateSessionFromRequest); ok {
redirect, err = fromRequest.TerminateSessionFromRequest(r.Context(), session)
} else {
err = ender.Storage().TerminateSession(r.Context(), session.UserID, session.ClientID)
}
if err != nil {
RequestError(w, r, oidc.DefaultToServerError(err, "error terminating session"))
return
}
http.Redirect(w, r, session.RedirectURI, http.StatusFound)
http.Redirect(w, r, redirect, http.StatusFound)
}

func ParseEndSessionRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.EndSessionRequest, error) {
Expand All @@ -60,11 +65,12 @@ func ValidateEndSessionRequest(ctx context.Context, req *oidc.EndSessionRequest,
RedirectURI: ender.DefaultLogoutRedirectURI(),
}
if req.IdTokenHint != "" {
claims, err := VerifyIDTokenHint[*oidc.TokenClaims](ctx, req.IdTokenHint, ender.IDTokenHintVerifier(ctx))
claims, err := VerifyIDTokenHint[*oidc.IDTokenClaims](ctx, req.IdTokenHint, ender.IDTokenHintVerifier(ctx))
if err != nil {
return nil, oidc.ErrInvalidRequest().WithDescription("id_token_hint invalid").WithParent(err)
}
session.UserID = claims.GetSubject()
session.IDTokenHintClaims = claims
if req.ClientID != "" && req.ClientID != claims.GetAuthorizedParty() {
return nil, oidc.ErrInvalidRequest().WithDescription("client_id does not match azp of id_token_hint")
}
Expand Down
15 changes: 12 additions & 3 deletions pkg/op/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ type AuthStorage interface {
KeySet(context.Context) ([]Key, error)
}

// CanTerminateSessionFromRequest is an optional additional interface that may be implemented by
// implementors of Storage as an alternative to TerminateSession of the AuthStorage.
// It passes the complete parsed EndSessionRequest to the implementation, which allows access to additional data.
// It also allows to modify the uri, which will be used for redirection, (e.g. a UI where the user can consent to the logout)
type CanTerminateSessionFromRequest interface {
TerminateSessionFromRequest(ctx context.Context, endSessionRequest *EndSessionRequest) (string, error)
}

type ClientCredentialsStorage interface {
ClientCredentials(ctx context.Context, clientID, clientSecret string) (Client, error)
ClientCredentialsTokenRequest(ctx context.Context, clientID string, scopes []string) (TokenRequest, error)
Expand Down Expand Up @@ -152,9 +160,10 @@ type StorageNotFoundError interface {
}

type EndSessionRequest struct {
UserID string
ClientID string
RedirectURI string
UserID string
ClientID string
IDTokenHintClaims *oidc.IDTokenClaims
RedirectURI string
}

var ErrDuplicateUserCode = errors.New("user code already exists")
Expand Down

0 comments on commit be89c3b

Please sign in to comment.