feat: Token Revocation, Request Object and OP Certification (#130)
FEATURES (and FIXES): - support OAuth 2.0 Token Revocation [RFC 7009](https://datatracker.ietf.org/doc/html/rfc7009) - handle request object using `request` parameter [OIDC Core 1.0 Request Object](https://openid.net/specs/openid-connect-core-1_0.html#RequestObject) - handle response mode - added some information to the discovery endpoint: - revocation_endpoint (added with token revocation) - revocation_endpoint_auth_methods_supported (added with token revocation) - revocation_endpoint_auth_signing_alg_values_supported (added with token revocation) - token_endpoint_auth_signing_alg_values_supported (was missing) - introspection_endpoint_auth_signing_alg_values_supported (was missing) - request_object_signing_alg_values_supported (added with request object) - request_parameter_supported (added with request object) - fixed `removeUserinfoScopes ` now returns the scopes without "userinfo" scopes (profile, email, phone, addedd) [source diff](https://github.com/caos/oidc/pull/130/files#diff-fad50c8c0f065d4dbc49d6c6a38f09c992c8f5d651a479ba00e31b500543559eL170-R171) - improved error handling (pkg/oidc/error.go) and fixed some wrong OAuth errors (e.g. `invalid_grant` instead of `invalid_request`) - improved MarshalJSON and added MarshalJSONWithStatus - removed deprecated PEM decryption from `BytesToPrivateKey` [source diff](https://github.com/caos/oidc/pull/130/files#diff-fe246e428e399ccff599627c71764de51387b60b4df84c67de3febd0954e859bL11-L19) - NewAccessTokenVerifier now uses correct (internal) `accessTokenVerifier` [source diff](https://github.com/caos/oidc/pull/130/files#diff-3a01c7500ead8f35448456ef231c7c22f8d291710936cac91de5edeef52ffc72L52-R52) BREAKING CHANGE: - move functions from `utils` package into separate packages - added various methods to the (OP) `Configuration` interface [source diff](https://github.com/caos/oidc/pull/130/files#diff-2538e0dfc772fdc37f057aecd6fcc2943f516c24e8be794cce0e368a26d20a82R19-R32) - added revocationEndpoint to `WithCustomEndpoints ` [source diff](https://github.com/caos/oidc/pull/130/files#diff-19ae13a743eb7cebbb96492798b1bec556673eb6236b1387e38d722900bae1c3L355-R391) - remove unnecessary context parameter from JWTProfileExchange [source diff](https://github.com/caos/oidc/pull/130/files#diff-4ed8f6affa4a9631fa8a034b3d5752fbb6a819107141aae00029014e950f7b4cL14)
This commit is contained in:
parent
763d3334e7
commit
eb10752e48
63 changed files with 1738 additions and 624 deletions
|
@ -42,6 +42,9 @@ const (
|
|||
DisplayTouch Display = "touch"
|
||||
DisplayWAP Display = "wap"
|
||||
|
||||
ResponseModeQuery ResponseMode = "query"
|
||||
ResponseModeFragment ResponseMode = "fragment"
|
||||
|
||||
//PromptNone (`none`) disallows the Authorization Server to display any authentication or consent user interface pages.
|
||||
//An error (login_required, interaction_required, ...) will be returned if the user is not already authenticated or consent is needed
|
||||
PromptNone = "none"
|
||||
|
@ -59,27 +62,28 @@ const (
|
|||
//AuthRequest according to:
|
||||
//https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||
type AuthRequest struct {
|
||||
ID string
|
||||
Scopes SpaceDelimitedArray `schema:"scope"`
|
||||
ResponseType ResponseType `schema:"response_type"`
|
||||
ClientID string `schema:"client_id"`
|
||||
RedirectURI string `schema:"redirect_uri"` //TODO: type
|
||||
Scopes SpaceDelimitedArray `json:"scope" schema:"scope"`
|
||||
ResponseType ResponseType `json:"response_type" schema:"response_type"`
|
||||
ClientID string `json:"client_id" schema:"client_id"`
|
||||
RedirectURI string `json:"redirect_uri" schema:"redirect_uri"`
|
||||
|
||||
State string `schema:"state"`
|
||||
State string `json:"state" schema:"state"`
|
||||
Nonce string `json:"nonce" schema:"nonce"`
|
||||
|
||||
// ResponseMode TODO: ?
|
||||
ResponseMode ResponseMode `json:"response_mode" schema:"response_mode"`
|
||||
Display Display `json:"display" schema:"display"`
|
||||
Prompt SpaceDelimitedArray `json:"prompt" schema:"prompt"`
|
||||
MaxAge *uint `json:"max_age" schema:"max_age"`
|
||||
UILocales Locales `json:"ui_locales" schema:"ui_locales"`
|
||||
IDTokenHint string `json:"id_token_hint" schema:"id_token_hint"`
|
||||
LoginHint string `json:"login_hint" schema:"login_hint"`
|
||||
ACRValues []string `json:"acr_values" schema:"acr_values"`
|
||||
|
||||
Nonce string `schema:"nonce"`
|
||||
Display Display `schema:"display"`
|
||||
Prompt SpaceDelimitedArray `schema:"prompt"`
|
||||
MaxAge *uint `schema:"max_age"`
|
||||
UILocales Locales `schema:"ui_locales"`
|
||||
IDTokenHint string `schema:"id_token_hint"`
|
||||
LoginHint string `schema:"login_hint"`
|
||||
ACRValues []string `schema:"acr_values"`
|
||||
CodeChallenge string `json:"code_challenge" schema:"code_challenge"`
|
||||
CodeChallengeMethod CodeChallengeMethod `json:"code_challenge_method" schema:"code_challenge_method"`
|
||||
|
||||
CodeChallenge string `schema:"code_challenge"`
|
||||
CodeChallengeMethod CodeChallengeMethod `schema:"code_challenge_method"`
|
||||
//RequestParam enables OIDC requests to be passed in a single, self-contained parameter (as JWT, called Request Object)
|
||||
RequestParam string `schema:"request"`
|
||||
}
|
||||
|
||||
//GetRedirectURI returns the redirect_uri value for the ErrAuthRequest interface
|
||||
|
|
|
@ -3,7 +3,7 @@ package oidc
|
|||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/caos/oidc/pkg/utils"
|
||||
"github.com/caos/oidc/pkg/crypto"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -19,7 +19,7 @@ type CodeChallenge struct {
|
|||
}
|
||||
|
||||
func NewSHACodeChallenge(code string) string {
|
||||
return utils.HashString(sha256.New(), code, false)
|
||||
return crypto.HashString(sha256.New(), code, false)
|
||||
}
|
||||
|
||||
func VerifyCodeChallenge(c *CodeChallenge, codeVerifier string) bool {
|
||||
|
|
|
@ -9,49 +9,144 @@ const (
|
|||
)
|
||||
|
||||
type DiscoveryConfiguration struct {
|
||||
Issuer string `json:"issuer,omitempty"`
|
||||
AuthorizationEndpoint string `json:"authorization_endpoint,omitempty"`
|
||||
TokenEndpoint string `json:"token_endpoint,omitempty"`
|
||||
IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`
|
||||
UserinfoEndpoint string `json:"userinfo_endpoint,omitempty"`
|
||||
RevocationEndpoint string `json:"revocation_endpoint,omitempty"`
|
||||
EndSessionEndpoint string `json:"end_session_endpoint,omitempty"`
|
||||
CheckSessionIframe string `json:"check_session_iframe,omitempty"`
|
||||
JwksURI string `json:"jwks_uri,omitempty"`
|
||||
ScopesSupported []string `json:"scopes_supported,omitempty"`
|
||||
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
|
||||
ResponseModesSupported []string `json:"response_modes_supported,omitempty"`
|
||||
GrantTypesSupported []GrantType `json:"grant_types_supported,omitempty"`
|
||||
ACRValuesSupported []string `json:"acr_values_supported,omitempty"`
|
||||
SubjectTypesSupported []string `json:"subject_types_supported,omitempty"`
|
||||
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported,omitempty"`
|
||||
IDTokenEncryptionAlgValuesSupported []string `json:"id_token_encryption_alg_values_supported,omitempty"`
|
||||
IDTokenEncryptionEncValuesSupported []string `json:"id_token_encryption_enc_values_supported,omitempty"`
|
||||
UserinfoSigningAlgValuesSupported []string `json:"userinfo_signing_alg_values_supported,omitempty"`
|
||||
UserinfoEncryptionAlgValuesSupported []string `json:"userinfo_encryption_alg_values_supported,omitempty"`
|
||||
UserinfoEncryptionEncValuesSupported []string `json:"userinfo_encryption_enc_values_supported,omitempty"`
|
||||
RequestObjectSigningAlgValuesSupported []string `json:"request_object_signing_alg_values_supported,omitempty"`
|
||||
RequestObjectEncryptionAlgValuesSupported []string `json:"request_object_encryption_alg_values_supported,omitempty"`
|
||||
RequestObjectEncryptionEncValuesSupported []string `json:"request_object_encryption_enc_values_supported,omitempty"`
|
||||
TokenEndpointAuthMethodsSupported []AuthMethod `json:"token_endpoint_auth_methods_supported,omitempty"`
|
||||
TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported,omitempty"`
|
||||
RevocationEndpointAuthMethodsSupported []AuthMethod `json:"revocation_endpoint_auth_methods_supported,omitempty"`
|
||||
RevocationEndpointAuthSigningAlgValuesSupported []string `json:"revocation_endpoint_auth_signing_alg_values_supported,omitempty"`
|
||||
IntrospectionEndpointAuthMethodsSupported []AuthMethod `json:"introspection_endpoint_auth_methods_supported,omitempty"`
|
||||
IntrospectionEndpointAuthSigningAlgValuesSupported []string `json:"introspection_endpoint_auth_signing_alg_values_supported,omitempty"`
|
||||
DisplayValuesSupported []Display `json:"display_values_supported,omitempty"`
|
||||
ClaimTypesSupported []string `json:"claim_types_supported,omitempty"`
|
||||
ClaimsSupported []string `json:"claims_supported,omitempty"`
|
||||
ClaimsParameterSupported bool `json:"claims_parameter_supported,omitempty"`
|
||||
CodeChallengeMethodsSupported []CodeChallengeMethod `json:"code_challenge_methods_supported,omitempty"`
|
||||
ServiceDocumentation string `json:"service_documentation,omitempty"`
|
||||
ClaimsLocalesSupported []language.Tag `json:"claims_locales_supported,omitempty"`
|
||||
UILocalesSupported []language.Tag `json:"ui_locales_supported,omitempty"`
|
||||
RequestParameterSupported bool `json:"request_parameter_supported,omitempty"`
|
||||
RequestURIParameterSupported bool `json:"request_uri_parameter_supported"` //no omitempty because: If omitted, the default value is true
|
||||
RequireRequestURIRegistration bool `json:"require_request_uri_registration,omitempty"`
|
||||
OPPolicyURI string `json:"op_policy_uri,omitempty"`
|
||||
OPTermsOfServiceURI string `json:"op_tos_uri,omitempty"`
|
||||
//Issuer is the identifier of the OP and is used in the tokens as `iss` claim.
|
||||
Issuer string `json:"issuer,omitempty"`
|
||||
|
||||
//AuthorizationEndpoint is the URL of the OAuth 2.0 Authorization Endpoint where all user interactive login start
|
||||
AuthorizationEndpoint string `json:"authorization_endpoint,omitempty"`
|
||||
|
||||
//TokenEndpoint is the URL of the OAuth 2.0 Token Endpoint where all tokens are issued, except when using Implicit Flow
|
||||
TokenEndpoint string `json:"token_endpoint,omitempty"`
|
||||
|
||||
//IntrospectionEndpoint is the URL of the OAuth 2.0 Introspection Endpoint.
|
||||
IntrospectionEndpoint string `json:"introspection_endpoint,omitempty"`
|
||||
|
||||
//UserinfoEndpoint is the URL where an access_token can be used to retrieve the Userinfo.
|
||||
UserinfoEndpoint string `json:"userinfo_endpoint,omitempty"`
|
||||
|
||||
//RevocationEndpoint is the URL of the OAuth 2.0 Revocation Endpoint.
|
||||
RevocationEndpoint string `json:"revocation_endpoint,omitempty"`
|
||||
|
||||
//EndSessionEndpoint is a URL where the RP can perform a redirect to request that the End-User be logged out at the OP.
|
||||
EndSessionEndpoint string `json:"end_session_endpoint,omitempty"`
|
||||
|
||||
//CheckSessionIframe is a URL where the OP provides an iframe that support cross-origin communications for session state information with the RP Client.
|
||||
CheckSessionIframe string `json:"check_session_iframe,omitempty"`
|
||||
|
||||
//JwksURI is the URL of the JSON Web Key Set. This site contains the signing keys that RPs can use to validate the signature.
|
||||
//It may also contain the OP's encryption keys that RPs can use to encrypt request to the OP.
|
||||
JwksURI string `json:"jwks_uri,omitempty"`
|
||||
|
||||
//RegistrationEndpoint is the URL for the Dynamic Client Registration.
|
||||
RegistrationEndpoint string `json:"registration_endpoint,omitempty"`
|
||||
|
||||
//ScopesSupported lists an array of supported scopes. This list must not include every supported scope by the OP.
|
||||
ScopesSupported []string `json:"scopes_supported,omitempty"`
|
||||
|
||||
//ResponseTypesSupported contains a list of the OAuth 2.0 response_type values that the OP supports (code, id_token, token id_token, ...).
|
||||
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
|
||||
|
||||
//ResponseModesSupported contains a list of the OAuth 2.0 response_mode values that the OP supports. If omitted, the default value is ["query", "fragment"].
|
||||
ResponseModesSupported []string `json:"response_modes_supported,omitempty"`
|
||||
|
||||
//GrantTypesSupported contains a list of the OAuth 2.0 grant_type values that the OP supports. If omitted, the default value is ["authorization_code", "implicit"].
|
||||
GrantTypesSupported []GrantType `json:"grant_types_supported,omitempty"`
|
||||
|
||||
//ACRValuesSupported contains a list of Authentication Context Class References that the OP supports.
|
||||
ACRValuesSupported []string `json:"acr_values_supported,omitempty"`
|
||||
|
||||
//SubjectTypesSupported contains a list of Subject Identifier types that the OP supports (pairwise, public).
|
||||
SubjectTypesSupported []string `json:"subject_types_supported,omitempty"`
|
||||
|
||||
//IDTokenSigningAlgValuesSupported contains a list of JWS signing algorithms (alg values) supported by the OP for the ID Token.
|
||||
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported,omitempty"`
|
||||
|
||||
//IDTokenEncryptionAlgValuesSupported contains a list of JWE encryption algorithms (alg values) supported by the OP for the ID Token.
|
||||
IDTokenEncryptionAlgValuesSupported []string `json:"id_token_encryption_alg_values_supported,omitempty"`
|
||||
|
||||
//IDTokenEncryptionEncValuesSupported contains a list of JWE encryption algorithms (enc values) supported by the OP for the ID Token.
|
||||
IDTokenEncryptionEncValuesSupported []string `json:"id_token_encryption_enc_values_supported,omitempty"`
|
||||
|
||||
//UserinfoSigningAlgValuesSupported contains a list of JWS signing algorithms (alg values) supported by the OP for UserInfo Endpoint.
|
||||
UserinfoSigningAlgValuesSupported []string `json:"userinfo_signing_alg_values_supported,omitempty"`
|
||||
|
||||
//UserinfoEncryptionAlgValuesSupported contains a list of JWE encryption algorithms (alg values) supported by the OP for the UserInfo Endpoint.
|
||||
UserinfoEncryptionAlgValuesSupported []string `json:"userinfo_encryption_alg_values_supported,omitempty"`
|
||||
|
||||
//UserinfoEncryptionEncValuesSupported contains a list of JWE encryption algorithms (enc values) supported by the OP for the UserInfo Endpoint.
|
||||
UserinfoEncryptionEncValuesSupported []string `json:"userinfo_encryption_enc_values_supported,omitempty"`
|
||||
|
||||
//RequestObjectSigningAlgValuesSupported contains a list of JWS signing algorithms (alg values) supported by the OP for Request Objects.
|
||||
//These algorithms are used both then the Request Object is passed by value (using the request parameter) and when it is passed by reference (using the request_uri parameter).
|
||||
RequestObjectSigningAlgValuesSupported []string `json:"request_object_signing_alg_values_supported,omitempty"`
|
||||
|
||||
//RequestObjectEncryptionAlgValuesSupported contains a list of JWE encryption algorithms (alg values) supported by the OP for Request Objects.
|
||||
//These algorithms are used both when the Request Object is passed by value and by reference.
|
||||
RequestObjectEncryptionAlgValuesSupported []string `json:"request_object_encryption_alg_values_supported,omitempty"`
|
||||
|
||||
//RequestObjectEncryptionEncValuesSupported contains a list of JWE encryption algorithms (enc values) supported by the OP for Request Objects.
|
||||
//These algorithms are used both when the Request Object is passed by value and by reference.
|
||||
RequestObjectEncryptionEncValuesSupported []string `json:"request_object_encryption_enc_values_supported,omitempty"`
|
||||
|
||||
//TokenEndpointAuthMethodsSupported contains a list of Client Authentication methods supported by the Token Endpoint. If omitted, the default is client_secret_basic.
|
||||
TokenEndpointAuthMethodsSupported []AuthMethod `json:"token_endpoint_auth_methods_supported,omitempty"`
|
||||
|
||||
//TokenEndpointAuthSigningAlgValuesSupported contains a list of JWS signing algorithms (alg values) supported by the Token Endpoint
|
||||
//for the signature of the JWT used to authenticate the Client by private_key_jwt and client_secret_jwt.
|
||||
TokenEndpointAuthSigningAlgValuesSupported []string `json:"token_endpoint_auth_signing_alg_values_supported,omitempty"`
|
||||
|
||||
//RevocationEndpointAuthMethodsSupported contains a list of Client Authentication methods supported by the Revocation Endpoint. If omitted, the default is client_secret_basic.
|
||||
RevocationEndpointAuthMethodsSupported []AuthMethod `json:"revocation_endpoint_auth_methods_supported,omitempty"`
|
||||
|
||||
//RevocationEndpointAuthSigningAlgValuesSupported contains a list of JWS signing algorithms (alg values) supported by the Revocation Endpoint
|
||||
//for the signature of the JWT used to authenticate the Client by private_key_jwt and client_secret_jwt.
|
||||
RevocationEndpointAuthSigningAlgValuesSupported []string `json:"revocation_endpoint_auth_signing_alg_values_supported,omitempty"`
|
||||
|
||||
//IntrospectionEndpointAuthMethodsSupported contains a list of Client Authentication methods supported by the Introspection Endpoint.
|
||||
IntrospectionEndpointAuthMethodsSupported []AuthMethod `json:"introspection_endpoint_auth_methods_supported,omitempty"`
|
||||
|
||||
//IntrospectionEndpointAuthSigningAlgValuesSupported contains a list of JWS signing algorithms (alg values) supported by the Revocation Endpoint
|
||||
//for the signature of the JWT used to authenticate the Client by private_key_jwt and client_secret_jwt.
|
||||
IntrospectionEndpointAuthSigningAlgValuesSupported []string `json:"introspection_endpoint_auth_signing_alg_values_supported,omitempty"`
|
||||
|
||||
//DisplayValuesSupported contains a list of display parameter values that the OP supports (page, popup, touch, wap).
|
||||
DisplayValuesSupported []Display `json:"display_values_supported,omitempty"`
|
||||
|
||||
//ClaimTypesSupported contains a list of Claim Types that the OP supports (normal, aggregated, distributed). If omitted, the default is normal Claims.
|
||||
ClaimTypesSupported []string `json:"claim_types_supported,omitempty"`
|
||||
|
||||
//ClaimsSupported contains a list of Claim Names the OP may be able to supply values for. This list might not be exhaustive.
|
||||
ClaimsSupported []string `json:"claims_supported,omitempty"`
|
||||
|
||||
//ClaimsParameterSupported specifies whether the OP supports use of the `claims` parameter. If omitted, the default is false.
|
||||
ClaimsParameterSupported bool `json:"claims_parameter_supported,omitempty"`
|
||||
|
||||
//CodeChallengeMethodsSupported contains a list of Proof Key for Code Exchange (PKCE) code challenge methods supported by the OP.
|
||||
CodeChallengeMethodsSupported []CodeChallengeMethod `json:"code_challenge_methods_supported,omitempty"`
|
||||
|
||||
//ServiceDocumentation is a URL where developers can get information about the OP and its usage.
|
||||
ServiceDocumentation string `json:"service_documentation,omitempty"`
|
||||
|
||||
//ClaimsLocalesSupported contains a list of BCP47 language tag values that the OP supports for values of Claims returned.
|
||||
ClaimsLocalesSupported []language.Tag `json:"claims_locales_supported,omitempty"`
|
||||
|
||||
//UILocalesSupported contains a list of BCP47 language tag values that the OP supports for the user interface.
|
||||
UILocalesSupported []language.Tag `json:"ui_locales_supported,omitempty"`
|
||||
|
||||
//RequestParameterSupported specifies whether the OP supports use of the `request` parameter. If omitted, the default value is false.
|
||||
RequestParameterSupported bool `json:"request_parameter_supported,omitempty"`
|
||||
|
||||
//RequestURIParameterSupported specifies whether the OP supports use of the `request_uri` parameter. If omitted, the default value is true. (therefore no omitempty)
|
||||
RequestURIParameterSupported bool `json:"request_uri_parameter_supported"`
|
||||
|
||||
//RequireRequestURIRegistration specifies whether the OP requires any `request_uri` to be pre-registered using the request_uris registration parameter. If omitted, the default value is false.
|
||||
RequireRequestURIRegistration bool `json:"require_request_uri_registration,omitempty"`
|
||||
|
||||
//OPPolicyURI is a URL the OP provides to the person registering the Client to read about the OP's requirements on how the RP can use the data provided by the OP.
|
||||
OPPolicyURI string `json:"op_policy_uri,omitempty"`
|
||||
|
||||
//OPTermsOfServiceURI is a URL the OpenID Provider provides to the person registering the Client to read about OpenID Provider's terms of service.
|
||||
OPTermsOfServiceURI string `json:"op_tos_uri,omitempty"`
|
||||
}
|
||||
|
||||
type AuthMethod string
|
||||
|
|
139
pkg/oidc/error.go
Normal file
139
pkg/oidc/error.go
Normal file
|
@ -0,0 +1,139 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type errorType string
|
||||
|
||||
const (
|
||||
InvalidRequest errorType = "invalid_request"
|
||||
InvalidScope errorType = "invalid_scope"
|
||||
InvalidClient errorType = "invalid_client"
|
||||
InvalidGrant errorType = "invalid_grant"
|
||||
UnauthorizedClient errorType = "unauthorized_client"
|
||||
UnsupportedGrantType errorType = "unsupported_grant_type"
|
||||
ServerError errorType = "server_error"
|
||||
InteractionRequired errorType = "interaction_required"
|
||||
LoginRequired errorType = "login_required"
|
||||
RequestNotSupported errorType = "request_not_supported"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidRequest = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: InvalidRequest,
|
||||
}
|
||||
}
|
||||
ErrInvalidRequestRedirectURI = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: InvalidRequest,
|
||||
redirectDisabled: true,
|
||||
}
|
||||
}
|
||||
ErrInvalidScope = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: InvalidScope,
|
||||
}
|
||||
}
|
||||
ErrInvalidClient = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: InvalidClient,
|
||||
}
|
||||
}
|
||||
ErrInvalidGrant = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: InvalidGrant,
|
||||
}
|
||||
}
|
||||
ErrUnauthorizedClient = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: UnauthorizedClient,
|
||||
}
|
||||
}
|
||||
ErrUnsupportedGrantType = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: UnsupportedGrantType,
|
||||
}
|
||||
}
|
||||
ErrServerError = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: ServerError,
|
||||
}
|
||||
}
|
||||
ErrInteractionRequired = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: InteractionRequired,
|
||||
}
|
||||
}
|
||||
ErrLoginRequired = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: LoginRequired,
|
||||
}
|
||||
}
|
||||
ErrRequestNotSupported = func() *Error {
|
||||
return &Error{
|
||||
ErrorType: RequestNotSupported,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Parent error `json:"-" schema:"-"`
|
||||
ErrorType errorType `json:"error" schema:"error"`
|
||||
Description string `json:"error_description,omitempty" schema:"error_description,omitempty"`
|
||||
State string `json:"state,omitempty" schema:"state,omitempty"`
|
||||
redirectDisabled bool `schema:"-"`
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
message := "ErrorType=" + string(e.ErrorType)
|
||||
if e.Description != "" {
|
||||
message += " Description=" + e.Description
|
||||
}
|
||||
if e.Parent != nil {
|
||||
message += " Parent=" + e.Parent.Error()
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
func (e *Error) Unwrap() error {
|
||||
return e.Parent
|
||||
}
|
||||
|
||||
func (e *Error) Is(target error) bool {
|
||||
t, ok := target.(*Error)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return e.ErrorType == t.ErrorType &&
|
||||
(e.Description == t.Description || t.Description == "") &&
|
||||
(e.State == t.State || t.State == "")
|
||||
}
|
||||
|
||||
func (e *Error) WithParent(err error) *Error {
|
||||
e.Parent = err
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Error) WithDescription(desc string, args ...interface{}) *Error {
|
||||
e.Description = fmt.Sprintf(desc, args...)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Error) IsRedirectDisabled() bool {
|
||||
return e.redirectDisabled
|
||||
}
|
||||
|
||||
// DefaultToServerError checks if the error is an Error
|
||||
// if not the provided error will be wrapped into a ServerError
|
||||
func DefaultToServerError(err error, description string) *Error {
|
||||
oauth := new(Error)
|
||||
if ok := errors.As(err, &oauth); !ok {
|
||||
oauth.ErrorType = ServerError
|
||||
oauth.Description = description
|
||||
oauth.Parent = err
|
||||
}
|
||||
return oauth
|
||||
}
|
|
@ -42,181 +42,181 @@ type introspectionResponse struct {
|
|||
claims map[string]interface{}
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) IsActive() bool {
|
||||
return u.Active
|
||||
func (i *introspectionResponse) IsActive() bool {
|
||||
return i.Active
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetScopes(scope []string) {
|
||||
u.Scope = scope
|
||||
func (i *introspectionResponse) SetScopes(scope []string) {
|
||||
i.Scope = scope
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetClientID(id string) {
|
||||
u.ClientID = id
|
||||
func (i *introspectionResponse) SetClientID(id string) {
|
||||
i.ClientID = id
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetSubject() string {
|
||||
return u.Subject
|
||||
func (i *introspectionResponse) GetSubject() string {
|
||||
return i.Subject
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetName() string {
|
||||
return u.Name
|
||||
func (i *introspectionResponse) GetName() string {
|
||||
return i.Name
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetGivenName() string {
|
||||
return u.GivenName
|
||||
func (i *introspectionResponse) GetGivenName() string {
|
||||
return i.GivenName
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetFamilyName() string {
|
||||
return u.FamilyName
|
||||
func (i *introspectionResponse) GetFamilyName() string {
|
||||
return i.FamilyName
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetMiddleName() string {
|
||||
return u.MiddleName
|
||||
func (i *introspectionResponse) GetMiddleName() string {
|
||||
return i.MiddleName
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetNickname() string {
|
||||
return u.Nickname
|
||||
func (i *introspectionResponse) GetNickname() string {
|
||||
return i.Nickname
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetProfile() string {
|
||||
return u.Profile
|
||||
func (i *introspectionResponse) GetProfile() string {
|
||||
return i.Profile
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetPicture() string {
|
||||
return u.Picture
|
||||
func (i *introspectionResponse) GetPicture() string {
|
||||
return i.Picture
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetWebsite() string {
|
||||
return u.Website
|
||||
func (i *introspectionResponse) GetWebsite() string {
|
||||
return i.Website
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetGender() Gender {
|
||||
return u.Gender
|
||||
func (i *introspectionResponse) GetGender() Gender {
|
||||
return i.Gender
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetBirthdate() string {
|
||||
return u.Birthdate
|
||||
func (i *introspectionResponse) GetBirthdate() string {
|
||||
return i.Birthdate
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetZoneinfo() string {
|
||||
return u.Zoneinfo
|
||||
func (i *introspectionResponse) GetZoneinfo() string {
|
||||
return i.Zoneinfo
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetLocale() language.Tag {
|
||||
return u.Locale
|
||||
func (i *introspectionResponse) GetLocale() language.Tag {
|
||||
return i.Locale
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetPreferredUsername() string {
|
||||
return u.PreferredUsername
|
||||
func (i *introspectionResponse) GetPreferredUsername() string {
|
||||
return i.PreferredUsername
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetEmail() string {
|
||||
return u.Email
|
||||
func (i *introspectionResponse) GetEmail() string {
|
||||
return i.Email
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) IsEmailVerified() bool {
|
||||
return bool(u.EmailVerified)
|
||||
func (i *introspectionResponse) IsEmailVerified() bool {
|
||||
return bool(i.EmailVerified)
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetPhoneNumber() string {
|
||||
return u.PhoneNumber
|
||||
func (i *introspectionResponse) GetPhoneNumber() string {
|
||||
return i.PhoneNumber
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) IsPhoneNumberVerified() bool {
|
||||
return u.PhoneNumberVerified
|
||||
func (i *introspectionResponse) IsPhoneNumberVerified() bool {
|
||||
return i.PhoneNumberVerified
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetAddress() UserInfoAddress {
|
||||
return u.Address
|
||||
func (i *introspectionResponse) GetAddress() UserInfoAddress {
|
||||
return i.Address
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) GetClaim(key string) interface{} {
|
||||
return u.claims[key]
|
||||
func (i *introspectionResponse) GetClaim(key string) interface{} {
|
||||
return i.claims[key]
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetActive(active bool) {
|
||||
u.Active = active
|
||||
func (i *introspectionResponse) SetActive(active bool) {
|
||||
i.Active = active
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetSubject(sub string) {
|
||||
u.Subject = sub
|
||||
func (i *introspectionResponse) SetSubject(sub string) {
|
||||
i.Subject = sub
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetName(name string) {
|
||||
u.Name = name
|
||||
func (i *introspectionResponse) SetName(name string) {
|
||||
i.Name = name
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetGivenName(name string) {
|
||||
u.GivenName = name
|
||||
func (i *introspectionResponse) SetGivenName(name string) {
|
||||
i.GivenName = name
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetFamilyName(name string) {
|
||||
u.FamilyName = name
|
||||
func (i *introspectionResponse) SetFamilyName(name string) {
|
||||
i.FamilyName = name
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetMiddleName(name string) {
|
||||
u.MiddleName = name
|
||||
func (i *introspectionResponse) SetMiddleName(name string) {
|
||||
i.MiddleName = name
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetNickname(name string) {
|
||||
u.Nickname = name
|
||||
func (i *introspectionResponse) SetNickname(name string) {
|
||||
i.Nickname = name
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetUpdatedAt(date time.Time) {
|
||||
u.UpdatedAt = Time(date)
|
||||
func (i *introspectionResponse) SetUpdatedAt(date time.Time) {
|
||||
i.UpdatedAt = Time(date)
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetProfile(profile string) {
|
||||
u.Profile = profile
|
||||
func (i *introspectionResponse) SetProfile(profile string) {
|
||||
i.Profile = profile
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetPicture(picture string) {
|
||||
u.Picture = picture
|
||||
func (i *introspectionResponse) SetPicture(picture string) {
|
||||
i.Picture = picture
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetWebsite(website string) {
|
||||
u.Website = website
|
||||
func (i *introspectionResponse) SetWebsite(website string) {
|
||||
i.Website = website
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetGender(gender Gender) {
|
||||
u.Gender = gender
|
||||
func (i *introspectionResponse) SetGender(gender Gender) {
|
||||
i.Gender = gender
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetBirthdate(birthdate string) {
|
||||
u.Birthdate = birthdate
|
||||
func (i *introspectionResponse) SetBirthdate(birthdate string) {
|
||||
i.Birthdate = birthdate
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetZoneinfo(zoneInfo string) {
|
||||
u.Zoneinfo = zoneInfo
|
||||
func (i *introspectionResponse) SetZoneinfo(zoneInfo string) {
|
||||
i.Zoneinfo = zoneInfo
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetLocale(locale language.Tag) {
|
||||
u.Locale = locale
|
||||
func (i *introspectionResponse) SetLocale(locale language.Tag) {
|
||||
i.Locale = locale
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetPreferredUsername(name string) {
|
||||
u.PreferredUsername = name
|
||||
func (i *introspectionResponse) SetPreferredUsername(name string) {
|
||||
i.PreferredUsername = name
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetEmail(email string, verified bool) {
|
||||
u.Email = email
|
||||
u.EmailVerified = boolString(verified)
|
||||
func (i *introspectionResponse) SetEmail(email string, verified bool) {
|
||||
i.Email = email
|
||||
i.EmailVerified = boolString(verified)
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetPhone(phone string, verified bool) {
|
||||
u.PhoneNumber = phone
|
||||
u.PhoneNumberVerified = verified
|
||||
func (i *introspectionResponse) SetPhone(phone string, verified bool) {
|
||||
i.PhoneNumber = phone
|
||||
i.PhoneNumberVerified = verified
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) SetAddress(address UserInfoAddress) {
|
||||
u.Address = address
|
||||
func (i *introspectionResponse) SetAddress(address UserInfoAddress) {
|
||||
i.Address = address
|
||||
}
|
||||
|
||||
func (u *introspectionResponse) AppendClaims(key string, value interface{}) {
|
||||
if u.claims == nil {
|
||||
u.claims = make(map[string]interface{})
|
||||
func (i *introspectionResponse) AppendClaims(key string, value interface{}) {
|
||||
if i.claims == nil {
|
||||
i.claims = make(map[string]interface{})
|
||||
}
|
||||
u.claims[key] = value
|
||||
i.claims[key] = value
|
||||
}
|
||||
|
||||
func (i *introspectionResponse) MarshalJSON() ([]byte, error) {
|
||||
|
|
6
pkg/oidc/revocation.go
Normal file
6
pkg/oidc/revocation.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
package oidc
|
||||
|
||||
type RevocationRequest struct {
|
||||
Token string `schema:"token"`
|
||||
TokenTypeHint string `schema:"token_type_hint"`
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
package oidc
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
@ -12,7 +9,8 @@ import (
|
|||
"golang.org/x/oauth2"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
|
||||
"github.com/caos/oidc/pkg/utils"
|
||||
"github.com/caos/oidc/pkg/crypto"
|
||||
"github.com/caos/oidc/pkg/http"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -188,7 +186,7 @@ func (a *accessTokenClaims) MarshalJSON() ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.ConcatenateJSON(b, info)
|
||||
return http.ConcatenateJSON(b, info)
|
||||
}
|
||||
|
||||
func (a *accessTokenClaims) UnmarshalJSON(data []byte) error {
|
||||
|
@ -325,7 +323,7 @@ func (t *idTokenClaims) GetSignatureAlgorithm() jose.SignatureAlgorithm {
|
|||
return t.signatureAlg
|
||||
}
|
||||
|
||||
//SetSignatureAlgorithm implements the IDTokenClaims interface
|
||||
//SetAccessTokenHash implements the IDTokenClaims interface
|
||||
func (t *idTokenClaims) SetAccessTokenHash(hash string) {
|
||||
t.AccessTokenHash = hash
|
||||
}
|
||||
|
@ -375,7 +373,7 @@ func (t *idTokenClaims) MarshalJSON() ([]byte, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.ConcatenateJSON(b, info)
|
||||
return http.ConcatenateJSON(b, info)
|
||||
}
|
||||
|
||||
func (t *idTokenClaims) UnmarshalJSON(data []byte) error {
|
||||
|
@ -572,12 +570,12 @@ func NewJWTProfileAssertion(userID, keyID string, audience []string, key []byte,
|
|||
}
|
||||
|
||||
func ClaimHash(claim string, sigAlgorithm jose.SignatureAlgorithm) (string, error) {
|
||||
hash, err := utils.GetHashAlgorithm(sigAlgorithm)
|
||||
hash, err := crypto.GetHashAlgorithm(sigAlgorithm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return utils.HashString(hash, claim, true), nil
|
||||
return crypto.HashString(hash, claim, true), nil
|
||||
}
|
||||
|
||||
func AppendClientIDToAudience(clientID string, audience []string) []string {
|
||||
|
@ -590,7 +588,7 @@ func AppendClientIDToAudience(clientID string, audience []string) []string {
|
|||
}
|
||||
|
||||
func GenerateJWTProfileToken(assertion JWTProfileAssertionClaims) (string, error) {
|
||||
privateKey, err := bytesToPrivateKey(assertion.GetPrivateKey())
|
||||
privateKey, err := crypto.BytesToPrivateKey(assertion.GetPrivateKey())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -613,21 +611,3 @@ func GenerateJWTProfileToken(assertion JWTProfileAssertionClaims) (string, error
|
|||
}
|
||||
return signedAssertion.CompactSerialize()
|
||||
}
|
||||
|
||||
func bytesToPrivateKey(priv []byte) (*rsa.PrivateKey, error) {
|
||||
block, _ := pem.Decode(priv)
|
||||
enc := x509.IsEncryptedPEMBlock(block)
|
||||
b := block.Bytes
|
||||
var err error
|
||||
if enc {
|
||||
b, err = x509.DecryptPEMBlock(block, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
key, err := x509.ParsePKCS1PrivateKey(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ const (
|
|||
//GrantTypeCode defines the grant_type `authorization_code` used for the Token Request in the Authorization Code Flow
|
||||
GrantTypeCode GrantType = "authorization_code"
|
||||
|
||||
//GrantTypeCode defines the grant_type `refresh_token` used for the Token Request in the Refresh Token Flow
|
||||
//GrantTypeRefreshToken defines the grant_type `refresh_token` used for the Token Request in the Refresh Token Flow
|
||||
GrantTypeRefreshToken GrantType = "refresh_token"
|
||||
|
||||
//GrantTypeBearer defines the grant_type `urn:ietf:params:oauth:grant-type:jwt-bearer` used for the JWT Authorization Grant
|
||||
|
@ -183,7 +183,7 @@ func (j *JWTTokenRequest) GetSubject() string {
|
|||
return j.Subject
|
||||
}
|
||||
|
||||
//GetSubject implements the TokenRequest interface
|
||||
//GetScopes implements the TokenRequest interface
|
||||
func (j *JWTTokenRequest) GetScopes() []string {
|
||||
return j.Scopes
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
)
|
||||
|
||||
type Audience []string
|
||||
|
@ -66,6 +67,8 @@ type Prompt SpaceDelimitedArray
|
|||
|
||||
type ResponseType string
|
||||
|
||||
type ResponseMode string
|
||||
|
||||
func (s SpaceDelimitedArray) Encode() string {
|
||||
return strings.Join(s, " ")
|
||||
}
|
||||
|
@ -106,3 +109,16 @@ func (t *Time) UnmarshalJSON(data []byte) error {
|
|||
func (t *Time) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(time.Time(*t).UTC().Unix())
|
||||
}
|
||||
|
||||
type RequestObject struct {
|
||||
Issuer string `json:"iss"`
|
||||
Audience Audience `json:"aud"`
|
||||
AuthRequest
|
||||
}
|
||||
|
||||
func (r *RequestObject) GetIssuer() string {
|
||||
return r.Issuer
|
||||
}
|
||||
|
||||
func (r *RequestObject) SetSignatureAlgorithm(algorithm jose.SignatureAlgorithm) {
|
||||
}
|
||||
|
|
|
@ -339,20 +339,20 @@ func NewUserInfoAddress(streetAddress, locality, region, postalCode, country, fo
|
|||
}
|
||||
}
|
||||
|
||||
func (i *userinfo) MarshalJSON() ([]byte, error) {
|
||||
func (u *userinfo) MarshalJSON() ([]byte, error) {
|
||||
type Alias userinfo
|
||||
a := &struct {
|
||||
*Alias
|
||||
Locale interface{} `json:"locale,omitempty"`
|
||||
UpdatedAt int64 `json:"updated_at,omitempty"`
|
||||
}{
|
||||
Alias: (*Alias)(i),
|
||||
Alias: (*Alias)(u),
|
||||
}
|
||||
if !i.Locale.IsRoot() {
|
||||
a.Locale = i.Locale
|
||||
if !u.Locale.IsRoot() {
|
||||
a.Locale = u.Locale
|
||||
}
|
||||
if !time.Time(i.UpdatedAt).IsZero() {
|
||||
a.UpdatedAt = time.Time(i.UpdatedAt).Unix()
|
||||
if !time.Time(u.UpdatedAt).IsZero() {
|
||||
a.UpdatedAt = time.Time(u.UpdatedAt).Unix()
|
||||
}
|
||||
|
||||
b, err := json.Marshal(a)
|
||||
|
@ -360,34 +360,34 @@ func (i *userinfo) MarshalJSON() ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if len(i.claims) == 0 {
|
||||
if len(u.claims) == 0 {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, &i.claims)
|
||||
err = json.Unmarshal(b, &u.claims)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("jws: invalid map of custom claims %v", i.claims)
|
||||
return nil, fmt.Errorf("jws: invalid map of custom claims %v", u.claims)
|
||||
}
|
||||
|
||||
return json.Marshal(i.claims)
|
||||
return json.Marshal(u.claims)
|
||||
}
|
||||
|
||||
func (i *userinfo) UnmarshalJSON(data []byte) error {
|
||||
func (u *userinfo) UnmarshalJSON(data []byte) error {
|
||||
type Alias userinfo
|
||||
a := &struct {
|
||||
Address *userInfoAddress `json:"address,omitempty"`
|
||||
*Alias
|
||||
UpdatedAt int64 `json:"update_at,omitempty"`
|
||||
}{
|
||||
Alias: (*Alias)(i),
|
||||
Alias: (*Alias)(u),
|
||||
}
|
||||
if err := json.Unmarshal(data, &a); err != nil {
|
||||
return err
|
||||
}
|
||||
i.Address = a.Address
|
||||
i.UpdatedAt = Time(time.Unix(a.UpdatedAt, 0).UTC())
|
||||
u.Address = a.Address
|
||||
u.UpdatedAt = Time(time.Unix(a.UpdatedAt, 0).UTC())
|
||||
|
||||
if err := json.Unmarshal(data, &i.claims); err != nil {
|
||||
if err := json.Unmarshal(data, &u.claims); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
|
||||
"github.com/caos/oidc/pkg/utils"
|
||||
str "github.com/caos/oidc/pkg/strings"
|
||||
)
|
||||
|
||||
type Claims interface {
|
||||
|
@ -25,6 +25,10 @@ type Claims interface {
|
|||
GetAuthenticationContextClassReference() string
|
||||
GetAuthTime() time.Time
|
||||
GetAuthorizedParty() string
|
||||
ClaimsSignature
|
||||
}
|
||||
|
||||
type ClaimsSignature interface {
|
||||
SetSignatureAlgorithm(algorithm jose.SignatureAlgorithm)
|
||||
}
|
||||
|
||||
|
@ -61,10 +65,10 @@ type Verifier interface {
|
|||
type ACRVerifier func(string) error
|
||||
|
||||
//DefaultACRVerifier implements `ACRVerifier` returning an error
|
||||
//if non of the provided values matches the acr claim
|
||||
//if none of the provided values matches the acr claim
|
||||
func DefaultACRVerifier(possibleValues []string) ACRVerifier {
|
||||
return func(acr string) error {
|
||||
if !utils.Contains(possibleValues, acr) {
|
||||
if !str.Contains(possibleValues, acr) {
|
||||
return fmt.Errorf("expected one of: %v, got: %q", possibleValues, acr)
|
||||
}
|
||||
return nil
|
||||
|
@ -103,7 +107,7 @@ func CheckIssuer(claims Claims, issuer string) error {
|
|||
}
|
||||
|
||||
func CheckAudience(claims Claims, clientID string) error {
|
||||
if !utils.Contains(claims.GetAudience(), clientID) {
|
||||
if !str.Contains(claims.GetAudience(), clientID) {
|
||||
return fmt.Errorf("%w: Audience must contain client_id %q", ErrAudience, clientID)
|
||||
}
|
||||
|
||||
|
@ -123,7 +127,7 @@ func CheckAuthorizedParty(claims Claims, clientID string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func CheckSignature(ctx context.Context, token string, payload []byte, claims Claims, supportedSigAlgs []string, set KeySet) error {
|
||||
func CheckSignature(ctx context.Context, token string, payload []byte, claims ClaimsSignature, supportedSigAlgs []string, set KeySet) error {
|
||||
jws, err := jose.ParseSigned(token)
|
||||
if err != nil {
|
||||
return ErrParse
|
||||
|
@ -138,7 +142,7 @@ func CheckSignature(ctx context.Context, token string, payload []byte, claims Cl
|
|||
if len(supportedSigAlgs) == 0 {
|
||||
supportedSigAlgs = []string{"RS256"}
|
||||
}
|
||||
if !utils.Contains(supportedSigAlgs, sig.Header.Algorithm) {
|
||||
if !str.Contains(supportedSigAlgs, sig.Header.Algorithm) {
|
||||
return fmt.Errorf("%w: id token signed with unsupported algorithm, expected %q got %q", ErrSignatureUnsupportedAlg, supportedSigAlgs, sig.Header.Algorithm)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue