add: session management check to get session_state from OP response, generate a externalSessionID if none supported.

This commit is contained in:
ybelMekk
2022-01-22 16:23:16 +01:00
parent f5e5d842e6
commit 7f6d323dde
3 changed files with 35 additions and 10 deletions

View File

@@ -33,6 +33,7 @@ type Configuration struct {
RequestParameterSupported bool `json:"request_parameter_supported"`
RequestURIParameterSupported bool `json:"request_uri_parameter_supported"`
RequestObjectSigningAlgValuesSupported []string `json:"request_object_signing_alg_values_supported"`
CheckSessionIframe string `json:"check_session_iframe,omitempty"`
}
type Supported []string
@@ -71,3 +72,11 @@ func (c *Configuration) FetchJwkSet(ctx context.Context) (*jwk.Set, error) {
return &jwkSet, nil
}
func (c *Configuration) FetchCheckSessionIframe() bool {
if c.CheckSessionIframe == "" {
return false
}
return true
}

View File

@@ -22,18 +22,18 @@ func (in *IDToken) Validate(opts ...jwt.ValidateOption) error {
return nil
}
func (in *IDToken) GetSID() (string, error) {
sid, ok := in.Token.Get("sid")
func (in *IDToken) GetStringClaim(claim string) (string, error) {
gotClaim, ok := in.Token.Get(claim)
if !ok {
return "", fmt.Errorf("missing required 'sid' claim in id_token")
return "", fmt.Errorf("missing required '%s' claim in id_token", claim)
}
sidString, ok := sid.(string)
claimString, ok := gotClaim.(string)
if !ok {
return "", fmt.Errorf("'sid' claim is not a string")
return "", fmt.Errorf("'%s' claim is not a string", claim)
}
return sidString, nil
return claimString, nil
}
func ParseIDToken(jwks jwk.Set, token *oauth2.Token) (*IDToken, error) {

View File

@@ -3,6 +3,7 @@ package router
import (
"context"
"fmt"
"github.com/google/uuid"
"net/http"
"time"
@@ -82,6 +83,11 @@ func (h *Handler) codeExchangeForToken(ctx context.Context, loginCookie *openid.
return tokens, nil
}
func (h *Handler) sidClaimRequired() bool {
config := h.Provider.GetOpenIDConfiguration()
return config.FrontchannelLogoutSupported && config.FrontchannelLogoutSessionSupported
}
func (h *Handler) validateIDToken(idToken *openid.IDToken, loginCookie *openid.LoginCookie) (string, error) {
validateOpts := []jwt.ValidateOption{
jwt.WithAudience(h.Provider.GetClientConfiguration().GetClientID()),
@@ -103,7 +109,18 @@ func (h *Handler) validateIDToken(idToken *openid.IDToken, loginCookie *openid.L
return "", err
}
externalSessionID, err := idToken.GetSID()
var externalSessionID string
switch true {
case h.sidClaimRequired():
externalSessionID, err = idToken.GetStringClaim("sid")
case h.Provider.GetOpenIDConfiguration().FetchCheckSessionIframe():
externalSessionID, err = idToken.GetStringClaim("session_state")
default:
// generate external sid
externalSessionID = h.GenerateExternalSessionID()
}
if err != nil {
return "", fmt.Errorf("getting external session ID from id_token: %w", err)
}
@@ -111,7 +128,6 @@ func (h *Handler) validateIDToken(idToken *openid.IDToken, loginCookie *openid.L
return externalSessionID, nil
}
func (h *Handler) sidClaimRequired() bool {
config := h.Provider.GetOpenIDConfiguration()
return config.FrontchannelLogoutSupported && config.FrontchannelLogoutSessionSupported
func (h *Handler) GenerateExternalSessionID() string {
return fmt.Sprintf("%s:%s:%s", h.Config.OpenID.Provider, h.Provider.GetClientConfiguration().GetClientID(), uuid.New().String())
}