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 6b620bb
Show file tree
Hide file tree
Showing 13 changed files with 106 additions and 97 deletions.
87 changes: 48 additions & 39 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 Expand Up @@ -229,7 +232,7 @@ func (c *DefaultOpenIDConnectClient) GetRequestObjectSigningAlgorithm() string {
}

func (c *DefaultOpenIDConnectClient) GetSecretPlainText() (secret []byte, err error) {
return nil, fmt.Errorf("this registered client does not suport plain text")
return nil, fmt.Errorf("this registered client does not support plain text")
}

func (c *DefaultOpenIDConnectClient) GetTokenEndpointAuthMethod() string {
Expand All @@ -243,3 +246,9 @@ func (c *DefaultOpenIDConnectClient) GetRequestURIs() []string {
func (c *DefaultResponseModeClient) GetResponseModes() []ResponseModeType {
return c.ResponseModes
}

var (
_ Client = (*DefaultClient)(nil)
_ ResponseModeClient = (*DefaultResponseModeClient)(nil)
_ OpenIDConnectClient = (*DefaultOpenIDConnectClient)(nil)
)
16 changes: 8 additions & 8 deletions client_authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (s *DefaultClientAuthenticationStrategy) AuthenticateClient(ctx context.Con
hasPost, hasBasic, hasAssertion bool
)

idBasic, secretBasic, hasBasic, err = s.getClientCredentialsSecretBasic(r)
idBasic, secretBasic, hasBasic, err = getClientCredentialsSecretBasic(r)
if err != nil {
return nil, "", errorsx.WithStack(ErrInvalidRequest.WithHint("The client credentials in the HTTP authorization header could not be parsed. Either the scheme was missing, the scheme was invalid, or the value had malformed data.").WithWrap(err).WithDebugError(err))
}
Expand Down 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 @@ -332,7 +332,7 @@ func (s *DefaultClientAuthenticationStrategy) doAuthenticateAssertionParseAssert
return client, method, kid, alg, token, claims, nil
}

func (s *DefaultClientAuthenticationStrategy) getClientCredentialsSecretBasic(r *http.Request) (id, secret string, ok bool, err error) {
func getClientCredentialsSecretBasic(r *http.Request) (id, secret string, ok bool, err error) {
auth := r.Header.Get(consts.HeaderAuthorization)

if auth == "" {
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
}
4 changes: 2 additions & 2 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ type SendDebugMessagesToClientsProvider interface {

// RevokeRefreshTokensExplicitlyProvider returns the provider for configuring the Refresh Token Explicit Revocation policy.
type RevokeRefreshTokensExplicitlyProvider interface {
// GetRevokeRefreshTokensExplicitly returns true if a refresh token should only be revoked explicitly.
GetRevokeRefreshTokensExplicitly(ctx context.Context) bool
// GetRevokeRefreshTokensExplicit returns true if a refresh token should only be revoked explicitly.
GetRevokeRefreshTokensExplicit(ctx context.Context) bool

// GetEnforceRevokeFlowRevokeRefreshTokensExplicitClient returns true if a
// RevokeFlowRevokeRefreshTokensExplicitClient returning false should be enforced.
Expand Down
8 changes: 4 additions & 4 deletions config_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ type Config struct {
// codes or other information. Proceed with caution!
SendDebugMessagesToClients bool

// RevokeRefreshTokensExplicitly determines if Refresh Tokens should only be revoked explicitly.
RevokeRefreshTokensExplicitly bool
// RevokeRefreshTokensExplicit determines if Refresh Tokens should only be revoked explicitly.
RevokeRefreshTokensExplicit bool

// EnforceRevokeFlowRevokeRefreshTokensExplicitClient determines if a RevokeFlowRevokeRefreshTokensExplicitClient
// should be prioritized even if it returns false.
Expand Down Expand Up @@ -294,8 +294,8 @@ func (c *Config) GetSendDebugMessagesToClients(ctx context.Context) bool {
return c.SendDebugMessagesToClients
}

func (c *Config) GetRevokeRefreshTokensExplicitly(ctx context.Context) bool {
return c.RevokeRefreshTokensExplicitly
func (c *Config) GetRevokeRefreshTokensExplicit(ctx context.Context) bool {
return c.RevokeRefreshTokensExplicit
}

func (c *Config) GetEnforceRevokeFlowRevokeRefreshTokensExplicitClient(ctx context.Context) bool {
Expand Down
6 changes: 3 additions & 3 deletions handler/oauth2/revocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ func (r *TokenRevocationHandler) getRevokeRefreshTokensExplicitly(ctx context.Co
)

if c, ok = client.(oauth2.RevokeFlowRevokeRefreshTokensExplicitClient); !ok {
return r.Config.GetRevokeRefreshTokensExplicitly(ctx)
return r.Config.GetRevokeRefreshTokensExplicit(ctx)
}

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

return r.Config.GetRevokeRefreshTokensExplicitly(ctx)
return r.Config.GetRevokeRefreshTokensExplicit(ctx)
}

func (r *TokenRevocationHandler) handleGetRefreshTokenRequester(ctx context.Context, token string) (requester oauth2.Requester, tokenType oauth2.TokenType, err error) {
Expand Down
Loading

0 comments on commit 6b620bb

Please sign in to comment.