handle request object
This commit is contained in:
parent
72a9829117
commit
f067d723f2
7 changed files with 196 additions and 36 deletions
|
@ -2,7 +2,6 @@ package op
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -41,6 +40,7 @@ type Authorizer interface {
|
|||
IDTokenHintVerifier() IDTokenHintVerifier
|
||||
Crypto() Crypto
|
||||
Issuer() string
|
||||
RequestObjectSupported() bool
|
||||
}
|
||||
|
||||
//AuthorizeValidator is an extension of Authorizer interface
|
||||
|
@ -70,6 +70,13 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
|
|||
AuthRequestError(w, r, authReq, err, authorizer.Encoder())
|
||||
return
|
||||
}
|
||||
if authReq.RequestParam != "" && authorizer.RequestObjectSupported() {
|
||||
authReq, err = ParseRequestObject(r.Context(), authReq, authorizer.Storage(), authorizer.Issuer())
|
||||
if err != nil {
|
||||
AuthRequestError(w, r, authReq, err, authorizer.Encoder())
|
||||
return
|
||||
}
|
||||
}
|
||||
validation := ValidateAuthRequest
|
||||
if validater, ok := authorizer.(AuthorizeValidator); ok {
|
||||
validation = validater.ValidateAuthRequest
|
||||
|
@ -79,6 +86,10 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
|
|||
AuthRequestError(w, r, authReq, err, authorizer.Encoder())
|
||||
return
|
||||
}
|
||||
if authReq.RequestParam != "" {
|
||||
AuthRequestError(w, r, authReq, oidc.ErrRequestNotSupported(), authorizer.Encoder())
|
||||
return
|
||||
}
|
||||
req, err := authorizer.Storage().CreateAuthRequest(r.Context(), authReq, userID)
|
||||
if err != nil {
|
||||
AuthRequestError(w, r, authReq, oidc.DefaultToServerError(err, "unable to save auth request"), authorizer.Encoder())
|
||||
|
@ -92,7 +103,7 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) {
|
|||
RedirectToLogin(req.GetID(), client, w, r)
|
||||
}
|
||||
|
||||
//ParseAuthorizeRequest parsed the http request into a oidc.AuthRequest
|
||||
//ParseAuthorizeRequest parsed the http request into an oidc.AuthRequest
|
||||
func ParseAuthorizeRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.AuthRequest, error) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
|
@ -106,6 +117,83 @@ func ParseAuthorizeRequest(r *http.Request, decoder httphelper.Decoder) (*oidc.A
|
|||
return authReq, nil
|
||||
}
|
||||
|
||||
//ParseRequestObject parse the `request` parameter, validates the token including the signature
|
||||
//and copies the token claims into the auth request
|
||||
func ParseRequestObject(ctx context.Context, authReq *oidc.AuthRequest, storage Storage, issuer string) (*oidc.AuthRequest, error) {
|
||||
requestObject := new(oidc.RequestObject)
|
||||
payload, err := oidc.ParseToken(authReq.RequestParam, requestObject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if requestObject.ClientID != "" && requestObject.ClientID != authReq.ClientID {
|
||||
return authReq, oidc.ErrInvalidRequest()
|
||||
}
|
||||
if requestObject.ResponseType != "" && requestObject.ResponseType != authReq.ResponseType {
|
||||
return authReq, oidc.ErrInvalidRequest()
|
||||
}
|
||||
if requestObject.Issuer != requestObject.ClientID {
|
||||
return authReq, oidc.ErrInvalidRequest()
|
||||
}
|
||||
if !str.Contains(requestObject.Audience, issuer) {
|
||||
return authReq, oidc.ErrInvalidRequest()
|
||||
}
|
||||
keySet := &jwtProfileKeySet{storage, requestObject.Issuer}
|
||||
if err = oidc.CheckSignature(ctx, authReq.RequestParam, payload, requestObject, nil, keySet); err != nil {
|
||||
return authReq, err
|
||||
}
|
||||
CopyRequestObjectToAuthRequest(authReq, requestObject)
|
||||
return authReq, nil
|
||||
}
|
||||
|
||||
//CopyRequestObjectToAuthRequest overwrites present values from the Request Object into the auth request
|
||||
//and clears the `RequestParam` of the auth request
|
||||
func CopyRequestObjectToAuthRequest(authReq *oidc.AuthRequest, requestObject *oidc.RequestObject) {
|
||||
if str.Contains(authReq.Scopes, oidc.ScopeOpenID) && len(requestObject.Scopes) > 0 {
|
||||
authReq.Scopes = requestObject.Scopes
|
||||
}
|
||||
if requestObject.RedirectURI != "" {
|
||||
authReq.RedirectURI = requestObject.RedirectURI
|
||||
}
|
||||
if requestObject.State != "" {
|
||||
authReq.State = requestObject.State
|
||||
}
|
||||
if requestObject.ResponseMode != "" {
|
||||
authReq.ResponseMode = requestObject.ResponseMode
|
||||
}
|
||||
if requestObject.Nonce != "" {
|
||||
authReq.Nonce = requestObject.Nonce
|
||||
}
|
||||
if requestObject.Display != "" {
|
||||
authReq.Display = requestObject.Display
|
||||
}
|
||||
if len(requestObject.Prompt) > 0 {
|
||||
authReq.Prompt = requestObject.Prompt
|
||||
}
|
||||
if requestObject.MaxAge != nil {
|
||||
authReq.MaxAge = requestObject.MaxAge
|
||||
}
|
||||
if len(requestObject.UILocales) > 0 {
|
||||
authReq.UILocales = requestObject.UILocales
|
||||
}
|
||||
if requestObject.IDTokenHint != "" {
|
||||
authReq.IDTokenHint = requestObject.IDTokenHint
|
||||
}
|
||||
if requestObject.LoginHint != "" {
|
||||
authReq.LoginHint = requestObject.LoginHint
|
||||
}
|
||||
if len(requestObject.ACRValues) > 0 {
|
||||
authReq.ACRValues = requestObject.ACRValues
|
||||
}
|
||||
if requestObject.CodeChallenge != "" {
|
||||
authReq.CodeChallenge = requestObject.CodeChallenge
|
||||
}
|
||||
if requestObject.CodeChallengeMethod != "" {
|
||||
authReq.CodeChallengeMethod = requestObject.CodeChallengeMethod
|
||||
}
|
||||
authReq.RequestParam = ""
|
||||
}
|
||||
|
||||
//ValidateAuthRequest validates the authorize parameters and returns the userID of the id_token_hint if passed
|
||||
func ValidateAuthRequest(ctx context.Context, authReq *oidc.AuthRequest, storage Storage, verifier IDTokenHintVerifier) (sub string, err error) {
|
||||
authReq.MaxAge, err = ValidateAuthReqPrompt(authReq.Prompt, authReq.MaxAge)
|
||||
|
|
|
@ -22,9 +22,14 @@ type Configuration interface {
|
|||
AuthMethodPostSupported() bool
|
||||
CodeMethodS256Supported() bool
|
||||
AuthMethodPrivateKeyJWTSupported() bool
|
||||
TokenEndpointSigningAlgorithmsSupported() []string
|
||||
GrantTypeRefreshTokenSupported() bool
|
||||
GrantTypeTokenExchangeSupported() bool
|
||||
GrantTypeJWTAuthorizationSupported() bool
|
||||
IntrospectionAuthMethodPrivateKeyJWTSupported() bool
|
||||
IntrospectionEndpointSigningAlgorithmsSupported() []string
|
||||
RequestObjectSupported() bool
|
||||
RequestObjectSigningAlgorithmsSupported() []string
|
||||
|
||||
SupportedUILocales() []language.Tag
|
||||
}
|
||||
|
|
|
@ -19,23 +19,27 @@ func Discover(w http.ResponseWriter, config *oidc.DiscoveryConfiguration) {
|
|||
|
||||
func CreateDiscoveryConfig(c Configuration, s Signer) *oidc.DiscoveryConfiguration {
|
||||
return &oidc.DiscoveryConfiguration{
|
||||
Issuer: c.Issuer(),
|
||||
AuthorizationEndpoint: c.AuthorizationEndpoint().Absolute(c.Issuer()),
|
||||
TokenEndpoint: c.TokenEndpoint().Absolute(c.Issuer()),
|
||||
IntrospectionEndpoint: c.IntrospectionEndpoint().Absolute(c.Issuer()),
|
||||
UserinfoEndpoint: c.UserinfoEndpoint().Absolute(c.Issuer()),
|
||||
EndSessionEndpoint: c.EndSessionEndpoint().Absolute(c.Issuer()),
|
||||
JwksURI: c.KeysEndpoint().Absolute(c.Issuer()),
|
||||
ScopesSupported: Scopes(c),
|
||||
ResponseTypesSupported: ResponseTypes(c),
|
||||
GrantTypesSupported: GrantTypes(c),
|
||||
SubjectTypesSupported: SubjectTypes(c),
|
||||
IDTokenSigningAlgValuesSupported: SigAlgorithms(s),
|
||||
TokenEndpointAuthMethodsSupported: AuthMethodsTokenEndpoint(c),
|
||||
IntrospectionEndpointAuthMethodsSupported: AuthMethodsIntrospectionEndpoint(c),
|
||||
ClaimsSupported: SupportedClaims(c),
|
||||
CodeChallengeMethodsSupported: CodeChallengeMethods(c),
|
||||
UILocalesSupported: c.SupportedUILocales(),
|
||||
Issuer: c.Issuer(),
|
||||
AuthorizationEndpoint: c.AuthorizationEndpoint().Absolute(c.Issuer()),
|
||||
TokenEndpoint: c.TokenEndpoint().Absolute(c.Issuer()),
|
||||
IntrospectionEndpoint: c.IntrospectionEndpoint().Absolute(c.Issuer()),
|
||||
UserinfoEndpoint: c.UserinfoEndpoint().Absolute(c.Issuer()),
|
||||
EndSessionEndpoint: c.EndSessionEndpoint().Absolute(c.Issuer()),
|
||||
JwksURI: c.KeysEndpoint().Absolute(c.Issuer()),
|
||||
ScopesSupported: Scopes(c),
|
||||
ResponseTypesSupported: ResponseTypes(c),
|
||||
GrantTypesSupported: GrantTypes(c),
|
||||
SubjectTypesSupported: SubjectTypes(c),
|
||||
IDTokenSigningAlgValuesSupported: SigAlgorithms(s),
|
||||
RequestObjectSigningAlgValuesSupported: RequestObjectSigAlgorithms(c),
|
||||
TokenEndpointAuthMethodsSupported: AuthMethodsTokenEndpoint(c),
|
||||
TokenEndpointAuthSigningAlgValuesSupported: TokenSigAlgorithms(c),
|
||||
IntrospectionEndpointAuthSigningAlgValuesSupported: IntrospectionSigAlgorithms(c),
|
||||
IntrospectionEndpointAuthMethodsSupported: AuthMethodsIntrospectionEndpoint(c),
|
||||
ClaimsSupported: SupportedClaims(c),
|
||||
CodeChallengeMethodsSupported: CodeChallengeMethods(c),
|
||||
UILocalesSupported: c.SupportedUILocales(),
|
||||
RequestParameterSupported: c.RequestObjectSupported(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,6 +132,13 @@ func AuthMethodsTokenEndpoint(c Configuration) []oidc.AuthMethod {
|
|||
return authMethods
|
||||
}
|
||||
|
||||
func TokenSigAlgorithms(c Configuration) []string {
|
||||
if !c.AuthMethodPrivateKeyJWTSupported() {
|
||||
return nil
|
||||
}
|
||||
return c.TokenEndpointSigningAlgorithmsSupported()
|
||||
}
|
||||
|
||||
func AuthMethodsIntrospectionEndpoint(c Configuration) []oidc.AuthMethod {
|
||||
authMethods := []oidc.AuthMethod{
|
||||
oidc.AuthMethodBasic,
|
||||
|
@ -145,3 +156,17 @@ func CodeChallengeMethods(c Configuration) []oidc.CodeChallengeMethod {
|
|||
}
|
||||
return codeMethods
|
||||
}
|
||||
|
||||
func IntrospectionSigAlgorithms(c Configuration) []string {
|
||||
if !c.IntrospectionAuthMethodPrivateKeyJWTSupported() {
|
||||
return nil
|
||||
}
|
||||
return c.IntrospectionEndpointSigningAlgorithmsSupported()
|
||||
}
|
||||
|
||||
func RequestObjectSigAlgorithms(c Configuration) []string {
|
||||
if !c.RequestObjectSupported() {
|
||||
return nil
|
||||
}
|
||||
return c.RequestObjectSigningAlgorithmsSupported()
|
||||
}
|
||||
|
|
21
pkg/op/op.go
21
pkg/op/op.go
|
@ -86,6 +86,7 @@ type Config struct {
|
|||
CodeMethodS256 bool
|
||||
AuthMethodPrivateKeyJWT bool
|
||||
GrantTypeRefreshToken bool
|
||||
RequestObjectSupported bool
|
||||
SupportedUILocales []language.Tag
|
||||
}
|
||||
|
||||
|
@ -191,6 +192,10 @@ func (o *openidProvider) AuthMethodPrivateKeyJWTSupported() bool {
|
|||
return o.config.AuthMethodPrivateKeyJWT
|
||||
}
|
||||
|
||||
func (o *openidProvider) TokenEndpointSigningAlgorithmsSupported() []string {
|
||||
return []string{"RS256"}
|
||||
}
|
||||
|
||||
func (o *openidProvider) GrantTypeRefreshTokenSupported() bool {
|
||||
return o.config.GrantTypeRefreshToken
|
||||
}
|
||||
|
@ -203,6 +208,22 @@ func (o *openidProvider) GrantTypeJWTAuthorizationSupported() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (o *openidProvider) IntrospectionAuthMethodPrivateKeyJWTSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *openidProvider) IntrospectionEndpointSigningAlgorithmsSupported() []string {
|
||||
return []string{"RS256"}
|
||||
}
|
||||
|
||||
func (o *openidProvider) RequestObjectSupported() bool {
|
||||
return o.config.RequestObjectSupported
|
||||
}
|
||||
|
||||
func (o *openidProvider) RequestObjectSigningAlgorithmsSupported() []string {
|
||||
return []string{"RS256"}
|
||||
}
|
||||
|
||||
func (o *openidProvider) SupportedUILocales() []language.Tag {
|
||||
return o.config.SupportedUILocales
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue