Skip to content

Commit

Permalink
refactor: naming
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-elliott committed Mar 9, 2024
1 parent ff1cd54 commit f2d3317
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 60 deletions.
79 changes: 41 additions & 38 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package oauth2
import (
"context"
"fmt"

"github.com/go-jose/go-jose/v3"

"authelia.com/provider/oauth2/internal/consts"
Expand All @@ -15,115 +14,119 @@ import (
// Client represents a client or an app.
type Client interface {
// GetID returns the client ID.
GetID() string
GetID() (id string)

// GetHashedSecret returns the hashed secret as it is stored in the store.
GetHashedSecret() []byte
GetHashedSecret() (secret []byte)

// GetRedirectURIs returns the client's allowed redirect URIs.
GetRedirectURIs() []string

// GetGrantTypes returns the client's allowed grant types.
GetGrantTypes() Arguments
GetGrantTypes() (types Arguments)

// GetResponseTypes returns the client's allowed response types.
// All allowed combinations of response types have to be listed, each combination having
// response types of the combination separated by a space.
GetResponseTypes() Arguments
GetResponseTypes() (types Arguments)

// GetScopes returns the scopes this client is allowed to request.
GetScopes() Arguments
GetScopes() (scopes Arguments)

// IsPublic returns true, if this client is marked as public.
IsPublic() bool
IsPublic() (public bool)

// GetAudience returns the allowed audience(s) for this client.
GetAudience() Arguments
GetAudience() (audience Arguments)
}

// ClientWithSecretRotation extends Client interface by a method providing a slice of rotated secrets.
type ClientWithSecretRotation interface {
// RotatedSecretHashesClient extends Client interface by a method providing a slice of rotated secrets.
type RotatedSecretHashesClient interface {
// GetRotatedHashedSecrets returns a slice of hashed secrets used for secrets rotation.
GetRotatedHashedSecrets() (secrets [][]byte)

Client
// GetRotatedHashes returns a slice of hashed secrets used for secrets rotation.
GetRotatedHashes() [][]byte
}

// ClientAuthenticationPolicyClient is a Client implementation which also provides client authentication policy values.
type ClientAuthenticationPolicyClient interface {
Client

// GetAllowMultipleAuthenticationMethods should return true if the client policy allows multiple authentication
// methods due to the client implementation breaching RFC6749 Section 2.3.
//
// See: https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.
GetAllowMultipleAuthenticationMethods(ctx context.Context) bool
GetAllowMultipleAuthenticationMethods(ctx context.Context) (allow bool)

Client
}

// OpenIDConnectClient represents a client capable of performing OpenID Connect requests.
type OpenIDConnectClient interface {
Client

// GetRequestURIs is an array of request_uri values that are pre-registered by the RP for use at the OP. Servers MAY
// cache the contents of the files referenced by these URIs and not retrieve them at the time they are used in a request.
// OPs can require that request_uri values used be pre-registered with the require_request_uri_registration
// discovery parameter.
GetRequestURIs() []string
GetRequestURIs() (requestURIs []string)

// GetJSONWebKeys returns the JSON Web Key Set containing the public key used by the client to authenticate.
GetJSONWebKeys() *jose.JSONWebKeySet
GetJSONWebKeys() (jwks *jose.JSONWebKeySet)

// GetJSONWebKeysURI returns the URL for lookup of JSON Web Key Set containing the
// public key used by the client to authenticate.
GetJSONWebKeysURI() string
GetJSONWebKeysURI() (uri string)

// JWS [JWS] alg algorithm [JWA] that MUST be used for signing Request Objects sent to the OP.
// All Request Objects from this Client MUST be rejected, if not signed with this algorithm.
GetRequestObjectSigningAlgorithm() string
// GetRequestObjectSigningAlgorithm returns the JWS [JWS] alg algorithm [JWA] that MUST be used for signing Request
// Objects sent to the OP. All Request Objects from this Client MUST be rejected, if not signed with this algorithm.
GetRequestObjectSigningAlgorithm() (alg string)

// Requested Client Authentication method for the Token Endpoint. The options are client_secret_post,
// client_secret_basic, client_secret_jwt, private_key_jwt, and none.
GetTokenEndpointAuthMethod() string
// GetTokenEndpointAuthMethod requested Client Authentication method for the Token Endpoint. The options are
// client_secret_post, client_secret_basic, client_secret_jwt, private_key_jwt, and none.
GetTokenEndpointAuthMethod() (method string)

// JWS [JWS] alg algorithm [JWA] that MUST be used for signing the JWT [JWT] used to authenticate the
// Client at the Token Endpoint for the private_key_jwt and client_secret_jwt authentication methods.
GetTokenEndpointAuthSigningAlgorithm() string
// GetTokenEndpointAuthSigningAlgorithm returns the JWS [JWS] alg algorithm [JWA] that MUST be used for signing the
// JWT [JWT] used to authenticate the Client at the Token Endpoint for the private_key_jwt and client_secret_jwt
// authentication methods.
GetTokenEndpointAuthSigningAlgorithm() (alg string)

// GetSecretPlainText returns the client secret in plain text.
// This is used to validate the 'token_endpoint_client_auth_method' with a value of 'client_secret_jwt'. If this
// client does NOT have a plain text secret then it MUST return an error.
GetSecretPlainText() (secret []byte, err error)

Client
}

// RefreshFlowScopeClient is a client which can be customized to ignore scopes that were not originally granted.
type RefreshFlowScopeClient interface {
Client

GetRefreshFlowIgnoreOriginalGrantedScopes(ctx context.Context) (ignoreOriginalGrantedScopes bool)

Client
}

// RevokeFlowRevokeRefreshTokensExplicitClient is a client which can be customized to only revoke Refresh Tokens
// explicitly.
type RevokeFlowRevokeRefreshTokensExplicitClient interface {
Client
// GetRevokeRefreshTokensExplicit returns true if this client will only revoke refresh tokens explicitly.
GetRevokeRefreshTokensExplicit(ctx context.Context) (explicit bool)

// GetRevokeRefreshTokensExplicitly returns true if this client will only revoke refresh tokens explicitly.
GetRevokeRefreshTokensExplicitly(ctx context.Context) bool
Client
}

// JARMClient is a client which supports JARM.
type JARMClient interface {
Client

GetAuthorizationSignedResponseKeyID() (kid string)
GetAuthorizationSignedResponseAlg() (alg string)
GetAuthorizationEncryptedResponseAlg() (alg string)
GetAuthorizationEncryptedResponseEncryptionAlg() (alg string)

Client
}

// ResponseModeClient represents a client capable of handling response_mode
type ResponseModeClient interface {
// GetResponseModes returns the response modes that client is allowed to send
GetResponseModes() []ResponseModeType
GetResponseModes() (modes []ResponseModeType)

Client
}

// DefaultClient is a simple default implementation of the Client interface.
Expand Down Expand Up @@ -174,7 +177,7 @@ func (c *DefaultClient) GetHashedSecret() []byte {
return c.Secret
}

func (c *DefaultClient) GetRotatedHashes() [][]byte {
func (c *DefaultClient) GetRotatedHashedSecrets() [][]byte {
return c.RotatedSecrets
}

Expand Down
12 changes: 6 additions & 6 deletions client_authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,15 @@ func (s *DefaultClientAuthenticationStrategy) doAuthenticateClientSecret(ctx con
}

var (
clientwsr ClientWithSecretRotation
ok bool
rclient RotatedSecretHashesClient
ok bool
)

if clientwsr, ok = client.(ClientWithSecretRotation); !ok {
if rclient, ok = client.(RotatedSecretHashesClient); !ok {
return nil, "", err
}

for _, hash := range clientwsr.GetRotatedHashes() {
for _, hash := range rclient.GetRotatedHashedSecrets() {
if hasher.Compare(ctx, hash, value) == nil {
return client, method, nil
}
Expand Down Expand Up @@ -597,11 +597,11 @@ func (f *Fosite) checkClientSecret(ctx context.Context, client Client, clientSec
return nil
}

cc, ok := client.(ClientWithSecretRotation)
cc, ok := client.(RotatedSecretHashesClient)
if !ok {
return err
}
for _, hash := range cc.GetRotatedHashes() {
for _, hash := range cc.GetRotatedHashedSecrets() {
err = f.Config.GetSecretsHasher(ctx).Compare(ctx, hash, clientSecret)
if err == nil {
return nil
Expand Down
4 changes: 2 additions & 2 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestDefaultClient(t *testing.T) {
assert.Equal(t, sc.ID, sc.GetID())
assert.Equal(t, sc.RedirectURIs, sc.GetRedirectURIs())
assert.Equal(t, sc.Secret, sc.GetHashedSecret())
assert.Equal(t, sc.RotatedSecrets, sc.GetRotatedHashes())
assert.Equal(t, sc.RotatedSecrets, sc.GetRotatedHashedSecrets())
assert.EqualValues(t, sc.ResponseTypes, sc.GetResponseTypes())
assert.EqualValues(t, sc.GrantTypes, sc.GetGrantTypes())
assert.EqualValues(t, sc.Scopes, sc.GetScopes())
Expand All @@ -35,7 +35,7 @@ func TestDefaultClient(t *testing.T) {
assert.Equal(t, consts.ResponseTypeAuthorizationCodeFlow, sc.GetResponseTypes()[0])
assert.Equal(t, consts.GrantTypeAuthorizationCode, sc.GetGrantTypes()[0])

var _ ClientWithSecretRotation = sc
var _ RotatedSecretHashesClient = sc
}

func TestDefaultResponseModeClient_GetResponseMode(t *testing.T) {
Expand Down
11 changes: 7 additions & 4 deletions client_with_custom_token_lifespans.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ import (
)

// GetEffectiveLifespan either maps GrantType x TokenType to the client's configured lifespan, or returns the fallback value.
func GetEffectiveLifespan(c Client, gt GrantType, tt TokenType, fallback time.Duration) time.Duration {
if clc, ok := c.(ClientWithCustomTokenLifespans); ok {
func GetEffectiveLifespan(c Client, gt GrantType, tt TokenType, fallback time.Duration) (lifespan time.Duration) {
if clc, ok := c.(CustomTokenLifespansClient); ok {
return clc.GetEffectiveLifespan(gt, tt, fallback)
}
return fallback
}

type ClientWithCustomTokenLifespans interface {
// CustomTokenLifespansClient is a Client with specific lifespans.
type CustomTokenLifespansClient interface {
// GetEffectiveLifespan either maps GrantType x TokenType to the client's configured lifespan, or returns the fallback value.
GetEffectiveLifespan(gt GrantType, tt TokenType, fallback time.Duration) time.Duration
GetEffectiveLifespan(gt GrantType, tt TokenType, fallback time.Duration) (lifespan time.Duration)

Client
}

// ClientLifespanConfig holds default lifespan configuration for the different
Expand Down
2 changes: 1 addition & 1 deletion client_with_custom_token_lifespans_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ func TestDefaultClientWithCustomTokenLifespans(t *testing.T) {
assert.NotEqual(t, clc.GetTokenLifespans(), nil)

require.Equal(t, customLifespan, GetEffectiveLifespan(clc, GrantTypeImplicit, IDToken, time.Minute*42))
var _ ClientWithCustomTokenLifespans = clc
var _ CustomTokenLifespansClient = clc
}
2 changes: 1 addition & 1 deletion handler/oauth2/revocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (r *TokenRevocationHandler) getRevokeRefreshTokensExplicitly(ctx context.Co
return r.Config.GetRevokeRefreshTokensExplicitly(ctx)
}

if ok = c.GetRevokeRefreshTokensExplicitly(ctx); ok || r.Config.GetEnforceRevokeFlowRevokeRefreshTokensExplicitClient(ctx) {
if ok = c.GetRevokeRefreshTokensExplicit(ctx); ok || r.Config.GetEnforceRevokeFlowRevokeRefreshTokensExplicitClient(ctx) {
return ok
}

Expand Down
2 changes: 1 addition & 1 deletion handler/oauth2/revocation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,6 @@ type ExplicitClient struct {
RevokeRefreshTokensExplicitly bool
}

func (c *ExplicitClient) GetRevokeRefreshTokensExplicitly(ctx context.Context) bool {
func (c *ExplicitClient) GetRevokeRefreshTokensExplicit(ctx context.Context) bool {
return c.RevokeRefreshTokensExplicitly
}
2 changes: 1 addition & 1 deletion handler/rfc8693/access_token_type_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (c *AccessTokenTypeHandler) validate(ctx context.Context, request oauth2.Ac

// Check if the client is allowed to exchange this token
if subjectTokenClient, ok := or.GetClient().(Client); ok {
allowed := subjectTokenClient.TokenExchangeAllowed(client)
allowed := subjectTokenClient.GetTokenExchangePermitted(client)
if !allowed {
return nil, nil, errors.WithStack(oauth2.ErrRequestForbidden.WithHintf(
"The OAuth 2.0 client is not permitted to exchange a subject token issued to client %s", subjectTokenClientID))
Expand Down
14 changes: 9 additions & 5 deletions handler/rfc8693/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ package rfc8693

import "authelia.com/provider/oauth2"

// Client is a representation of a client that may support RFC8693.
type Client interface {
// GetSupportedSubjectTokenTypes indicates the token types allowed for subject_token
GetSupportedSubjectTokenTypes() []string
GetSupportedSubjectTokenTypes() (types []string)

// GetSupportedActorTokenTypes indicates the token types allowed for subject_token
GetSupportedActorTokenTypes() []string
GetSupportedActorTokenTypes() (types []string)

// GetSupportedRequestTokenTypes indicates the token types allowed for requested_token_type
GetSupportedRequestTokenTypes() []string
// TokenExchangeAllowed checks if the subject token client allows the specified client
GetSupportedRequestTokenTypes() (types []string)

// GetTokenExchangePermitted checks if the subject token client allows the specified client
// to perform the exchange
TokenExchangeAllowed(client oauth2.Client) bool
GetTokenExchangePermitted(client oauth2.Client) (allowed bool)
}
2 changes: 1 addition & 1 deletion handler/rfc8693/refresh_token_type_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (c *RefreshTokenTypeHandler) validate(ctx context.Context, request oauth2.A

// Check if the client is allowed to exchange this token
if subjectTokenClient, ok := or.GetClient().(Client); ok {
allowed := subjectTokenClient.TokenExchangeAllowed(client)
allowed := subjectTokenClient.GetTokenExchangePermitted(client)
if !allowed {
return nil, nil, errors.WithStack(oauth2.ErrRequestForbidden.WithHintf(
"The OAuth 2.0 client is not permitted to exchange a subject token issued to client %s", tokenClientID))
Expand Down

0 comments on commit f2d3317

Please sign in to comment.