2021-05-04 22:06:05 +00:00
package oidc
import (
"github.com/ory/fosite"
2023-01-03 15:03:23 +00:00
"github.com/ory/x/errorsx"
2021-05-04 22:06:05 +00:00
2021-08-11 01:04:35 +00:00
"github.com/authelia/authelia/v4/internal/authentication"
"github.com/authelia/authelia/v4/internal/authorization"
"github.com/authelia/authelia/v4/internal/configuration/schema"
2022-04-01 11:18:58 +00:00
"github.com/authelia/authelia/v4/internal/model"
2021-05-04 22:06:05 +00:00
)
2022-04-07 05:33:53 +00:00
// NewClient creates a new Client.
func NewClient ( config schema . OpenIDConnectClientConfiguration ) ( client * Client ) {
client = & Client {
2022-04-07 06:13:01 +00:00
ID : config . ID ,
Description : config . Description ,
2022-10-20 03:21:45 +00:00
Secret : config . Secret ,
2022-04-07 06:13:01 +00:00
SectorIdentifier : config . SectorIdentifier . String ( ) ,
Public : config . Public ,
2021-07-15 11:02:03 +00:00
2023-01-03 15:03:23 +00:00
EnforcePKCE : config . EnforcePKCE || config . PKCEChallengeMethod != "" ,
EnforcePKCEChallengeMethod : config . PKCEChallengeMethod != "" ,
PKCEChallengeMethod : config . PKCEChallengeMethod ,
2021-07-15 11:02:03 +00:00
Audience : config . Audience ,
Scopes : config . Scopes ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
RedirectURIs : config . RedirectURIs ,
GrantTypes : config . GrantTypes ,
ResponseTypes : config . ResponseTypes ,
2023-04-11 11:29:02 +00:00
ResponseModes : [ ] fosite . ResponseModeType { } ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
2023-03-06 03:58:50 +00:00
EnforcePAR : config . EnforcePAR ,
2021-07-10 04:56:33 +00:00
UserinfoSigningAlgorithm : config . UserinfoSigningAlgorithm ,
2022-04-08 05:35:21 +00:00
2022-12-17 12:39:24 +00:00
Policy : authorization . NewLevel ( config . Policy ) ,
2022-04-08 05:35:21 +00:00
2022-10-20 02:16:36 +00:00
Consent : NewClientConsent ( config . ConsentMode , config . ConsentPreConfiguredDuration ) ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
}
for _ , mode := range config . ResponseModes {
client . ResponseModes = append ( client . ResponseModes , fosite . ResponseModeType ( mode ) )
}
return client
2021-05-04 22:06:05 +00:00
}
2023-03-06 03:58:50 +00:00
// ValidatePKCEPolicy is a helper function to validate PKCE policy constraints on a per-client basis.
func ( c * Client ) ValidatePKCEPolicy ( r fosite . Requester ) ( err error ) {
2023-01-03 15:03:23 +00:00
form := r . GetRequestForm ( )
if c . EnforcePKCE {
2023-03-06 03:58:50 +00:00
if form . Get ( FormParameterCodeChallenge ) == "" {
2023-01-03 15:03:23 +00:00
return errorsx . WithStack ( fosite . ErrInvalidRequest .
WithHint ( "Clients must include a code_challenge when performing the authorize code flow, but it is missing." ) .
WithDebug ( "The server is configured in a way that enforces PKCE for this client." ) )
}
if c . EnforcePKCEChallengeMethod {
2023-03-06 03:58:50 +00:00
if method := form . Get ( FormParameterCodeChallengeMethod ) ; method != c . PKCEChallengeMethod {
2023-01-03 15:03:23 +00:00
return errorsx . WithStack ( fosite . ErrInvalidRequest .
2023-03-06 03:58:50 +00:00
WithHintf ( "Client must use code_challenge_method=%s, %s is not allowed." , c . PKCEChallengeMethod , method ) .
WithDebugf ( "The server is configured in a way that enforces PKCE %s as challenge method for this client." , c . PKCEChallengeMethod ) )
2023-01-03 15:03:23 +00:00
}
}
}
return nil
}
2023-03-06 03:58:50 +00:00
// ValidatePARPolicy is a helper function to validate additional policy constraints on a per-client basis.
func ( c * Client ) ValidatePARPolicy ( r fosite . Requester , prefix string ) ( err error ) {
if c . EnforcePAR {
2023-04-11 11:29:02 +00:00
if ! IsPushedAuthorizedRequest ( r , prefix ) {
switch requestURI := r . GetRequestForm ( ) . Get ( FormParameterRequestURI ) ; requestURI {
case "" :
2023-03-06 03:58:50 +00:00
return errorsx . WithStack ( ErrPAREnforcedClientMissingPAR . WithDebug ( "The request_uri parameter was empty." ) )
2023-04-11 11:29:02 +00:00
default :
return errorsx . WithStack ( ErrPAREnforcedClientMissingPAR . WithDebugf ( "The request_uri parameter '%s' is malformed." , requestURI ) )
2023-03-06 03:58:50 +00:00
}
}
}
return nil
}
2023-04-11 11:29:02 +00:00
// ValidateResponseModePolicy is an additional check to the response mode parameter to ensure if it's omitted that the
// default response mode for the fosite.AuthorizeRequester is permitted.
func ( c * Client ) ValidateResponseModePolicy ( r fosite . AuthorizeRequester ) ( err error ) {
if r . GetResponseMode ( ) != fosite . ResponseModeDefault {
return nil
}
m := r . GetDefaultResponseMode ( )
modes := c . GetResponseModes ( )
if len ( modes ) == 0 {
return nil
}
for _ , mode := range modes {
if m == mode {
return nil
}
}
return errorsx . WithStack ( fosite . ErrUnsupportedResponseMode . WithHintf ( ` The request omitted the response_mode making the default response_mode "%s" based on the other authorization request parameters but registered OAuth 2.0 client doesn't support this response_mode ` , m ) )
}
2021-05-04 22:06:05 +00:00
// IsAuthenticationLevelSufficient returns if the provided authentication.Level is sufficient for the client of the AutheliaClient.
2022-10-20 02:16:36 +00:00
func ( c * Client ) IsAuthenticationLevelSufficient ( level authentication . Level ) bool {
if level == authentication . NotAuthenticated {
return false
}
2021-05-04 22:06:05 +00:00
return authorization . IsAuthLevelSufficient ( level , c . Policy )
}
2022-04-07 05:33:53 +00:00
// GetSectorIdentifier returns the SectorIdentifier for this client.
2022-10-20 02:16:36 +00:00
func ( c * Client ) GetSectorIdentifier ( ) string {
2022-04-07 05:33:53 +00:00
return c . SectorIdentifier
}
// GetConsentResponseBody returns the proper consent response body for this session.OIDCWorkflowSession.
2022-10-20 02:16:36 +00:00
func ( c * Client ) GetConsentResponseBody ( consent * model . OAuth2ConsentSession ) ConsentGetResponseBody {
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
body := ConsentGetResponseBody {
ClientID : c . ID ,
ClientDescription : c . Description ,
2022-10-20 02:16:36 +00:00
PreConfiguration : c . Consent . Mode == ClientConsentModePreConfigured ,
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
}
2022-04-07 05:33:53 +00:00
if consent != nil {
body . Scopes = consent . RequestedScopes
body . Audience = consent . RequestedAudience
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
}
return body
}
2023-01-03 15:03:23 +00:00
// GetID returns the ID.
func ( c * Client ) GetID ( ) string {
return c . ID
}
2021-05-04 22:06:05 +00:00
// GetHashedSecret returns the Secret.
2023-03-06 03:58:50 +00:00
func ( c * Client ) GetHashedSecret ( ) ( secret [ ] byte ) {
2022-10-20 03:21:45 +00:00
if c . Secret == nil {
return [ ] byte ( nil )
}
return [ ] byte ( c . Secret . Encode ( ) )
2021-05-04 22:06:05 +00:00
}
// GetRedirectURIs returns the RedirectURIs.
2023-03-06 03:58:50 +00:00
func ( c * Client ) GetRedirectURIs ( ) ( redirectURIs [ ] string ) {
2021-05-04 22:06:05 +00:00
return c . RedirectURIs
}
// GetGrantTypes returns the GrantTypes.
2022-10-20 02:16:36 +00:00
func ( c * Client ) GetGrantTypes ( ) fosite . Arguments {
2021-05-04 22:06:05 +00:00
if len ( c . GrantTypes ) == 0 {
return fosite . Arguments { "authorization_code" }
}
return c . GrantTypes
}
// GetResponseTypes returns the ResponseTypes.
2022-10-20 02:16:36 +00:00
func ( c * Client ) GetResponseTypes ( ) fosite . Arguments {
2021-05-04 22:06:05 +00:00
if len ( c . ResponseTypes ) == 0 {
return fosite . Arguments { "code" }
}
return c . ResponseTypes
}
// GetScopes returns the Scopes.
2022-10-20 02:16:36 +00:00
func ( c * Client ) GetScopes ( ) fosite . Arguments {
2021-05-04 22:06:05 +00:00
return c . Scopes
}
// IsPublic returns the value of the Public property.
2022-10-20 02:16:36 +00:00
func ( c * Client ) IsPublic ( ) bool {
2021-05-04 22:06:05 +00:00
return c . Public
}
// GetAudience returns the Audience.
2022-10-20 02:16:36 +00:00
func ( c * Client ) GetAudience ( ) fosite . Arguments {
2021-05-04 22:06:05 +00:00
return c . Audience
}
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
// GetResponseModes returns the valid response modes for this client.
//
// Implements the fosite.ResponseModeClient.
2022-10-20 02:16:36 +00:00
func ( c * Client ) GetResponseModes ( ) [ ] fosite . ResponseModeType {
feat(oidc): add additional config options, accurate token times, and refactoring (#1991)
* This gives admins more control over their OIDC installation exposing options that had defaults before. Things like lifespans for authorize codes, access tokens, id tokens, refresh tokens, a option to enable the debug client messages, minimum parameter entropy. It also allows admins to configure the response modes.
* Additionally this records specific values about a users session indicating when they performed a specific authz factor so this is represented in the token accurately.
* Lastly we also implemented a OIDC key manager which calculates the kid for jwk's using the SHA1 digest instead of being static, or more specifically the first 7 chars. As per https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key#section-8.1.1 the kid should not exceed 8 chars. While it's allowed to exceed 8 chars, it must only be done so with a compelling reason, which we do not have.
2021-07-03 23:44:30 +00:00
return c . ResponseModes
}