ory-am/hydra

View on GitHub
fositex/config.go

Summary

Maintainability
A
3 hrs
Test Coverage
// Copyright © 2022 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package fositex

import (
    "context"
    "crypto/sha512"
    "hash"
    "html/template"
    "net/url"

    "github.com/hashicorp/go-retryablehttp"

    "github.com/ory/fosite"
    "github.com/ory/fosite/compose"
    "github.com/ory/fosite/i18n"
    "github.com/ory/fosite/token/jwt"
    "github.com/ory/hydra/v2/driver/config"
    "github.com/ory/hydra/v2/oauth2"
    "github.com/ory/hydra/v2/persistence"
    "github.com/ory/hydra/v2/x"
    "github.com/ory/x/stringslice"
    "github.com/ory/x/urlx"
)

type configDependencies interface {
    config.Provider
    persistence.Provider
    x.HTTPClientProvider
    GetJWKSFetcherStrategy() fosite.JWKSFetcherStrategy
    ClientHasher() fosite.Hasher
    ExtraFositeFactories() []Factory
}

type Factory func(config fosite.Configurator, storage interface{}, strategy interface{}) interface{}

type Config struct {
    deps configDependencies

    authorizeEndpointHandlers  fosite.AuthorizeEndpointHandlers
    tokenEndpointHandlers      fosite.TokenEndpointHandlers
    tokenIntrospectionHandlers fosite.TokenIntrospectionHandlers
    revocationHandlers         fosite.RevocationHandlers

    *config.DefaultProvider
}

var defaultResponseModeHandler = fosite.NewDefaultResponseModeHandler()
var defaultFactories = []Factory{
    compose.OAuth2AuthorizeExplicitFactory,
    compose.OAuth2AuthorizeImplicitFactory,
    compose.OAuth2ClientCredentialsGrantFactory,
    compose.OAuth2RefreshTokenGrantFactory,
    compose.OpenIDConnectExplicitFactory,
    compose.OpenIDConnectHybridFactory,
    compose.OpenIDConnectImplicitFactory,
    compose.OpenIDConnectRefreshFactory,
    compose.OAuth2TokenRevocationFactory,
    compose.OAuth2TokenIntrospectionFactory,
    compose.OAuth2PKCEFactory,
    compose.RFC7523AssertionGrantFactory,
    compose.OIDCUserinfoVerifiableCredentialFactory,
}

func NewConfig(deps configDependencies) *Config {
    c := &Config{
        deps:            deps,
        DefaultProvider: deps.Config(),
    }
    return c
}

func (c *Config) LoadDefaultHandlers(strategy interface{}) {
    factories := append(defaultFactories, c.deps.ExtraFositeFactories()...)
    for _, factory := range factories {
        res := factory(c, c.deps.Persister(), strategy)
        if ah, ok := res.(fosite.AuthorizeEndpointHandler); ok {
            c.authorizeEndpointHandlers.Append(ah)
        }
        if th, ok := res.(fosite.TokenEndpointHandler); ok {
            c.tokenEndpointHandlers.Append(th)
        }
        if tv, ok := res.(fosite.TokenIntrospector); ok {
            c.tokenIntrospectionHandlers.Append(tv)
        }
        if rh, ok := res.(fosite.RevocationHandler); ok {
            c.revocationHandlers.Append(rh)
        }
    }
}

func (c *Config) GetJWKSFetcherStrategy(context.Context) fosite.JWKSFetcherStrategy {
    return c.deps.GetJWKSFetcherStrategy()
}

func (c *Config) GetHTTPClient(ctx context.Context) *retryablehttp.Client {
    return c.deps.HTTPClient(ctx)
}

func (c *Config) GetAuthorizeEndpointHandlers(context.Context) fosite.AuthorizeEndpointHandlers {
    return c.authorizeEndpointHandlers
}

func (c *Config) GetTokenEndpointHandlers(context.Context) fosite.TokenEndpointHandlers {
    return c.tokenEndpointHandlers
}

func (c *Config) GetTokenIntrospectionHandlers(context.Context) (r fosite.TokenIntrospectionHandlers) {
    return c.tokenIntrospectionHandlers
}

func (c *Config) GetRevocationHandlers(context.Context) fosite.RevocationHandlers {
    return c.revocationHandlers
}

func (c *Config) GetGrantTypeJWTBearerCanSkipClientAuth(context.Context) bool {
    return false
}

func (c *Config) GetAudienceStrategy(context.Context) fosite.AudienceMatchingStrategy {
    return fosite.DefaultAudienceMatchingStrategy
}

func (c *Config) GetOmitRedirectScopeParam(context.Context) bool {
    return false
}

func (c *Config) GetSanitationWhiteList(context.Context) []string {
    return []string{"code", "redirect_uri"}
}

func (c *Config) GetEnablePKCEPlainChallengeMethod(context.Context) bool {
    return false
}

func (c *Config) GetDisableRefreshTokenValidation(context.Context) bool {
    return false
}

func (c *Config) GetRefreshTokenScopes(context.Context) []string {
    return []string{"offline", "offline_access"}
}

func (c *Config) GetMinParameterEntropy(_ context.Context) int {
    return fosite.MinParameterEntropy
}

func (c *Config) GetClientAuthenticationStrategy(context.Context) fosite.ClientAuthenticationStrategy {
    // Fosite falls back to the default fosite.Fosite.DefaultClientAuthenticationStrategy when this is nil.
    return nil
}

func (c *Config) GetResponseModeHandlerExtension(context.Context) fosite.ResponseModeHandler {
    return defaultResponseModeHandler
}

func (c *Config) GetSendDebugMessagesToClients(ctx context.Context) bool {
    return c.deps.Config().GetSendDebugMessagesToClients(ctx)
}

func (c *Config) GetMessageCatalog(context.Context) i18n.MessageCatalog {
    // Fosite falls back to the default messages when this is nil.
    return nil
}

func (c *Config) GetSecretsHasher(context.Context) fosite.Hasher {
    return c.deps.ClientHasher()
}

func (c *Config) GetTokenEntropy(context.Context) int {
    return 32
}

func (c *Config) GetHMACHasher(context.Context) func() hash.Hash {
    return sha512.New512_256
}

func (c *Config) GetIDTokenIssuer(ctx context.Context) string {
    return c.deps.Config().IssuerURL(ctx).String()
}

func (c *Config) GetAllowedPrompts(context.Context) []string {
    return []string{"login", "none", "consent", "registration"}
}

func (c *Config) GetRedirectSecureChecker(context.Context) func(context.Context, *url.URL) bool {
    return x.IsRedirectURISecure(c.deps.Config())
}

func (c *Config) GetAccessTokenIssuer(ctx context.Context) string {
    return c.deps.Config().IssuerURL(ctx).String()
}

func (c *Config) GetJWTScopeField(ctx context.Context) jwt.JWTScopeFieldEnum {
    return c.deps.Config().GetJWTScopeField(ctx)
}

func (c *Config) GetFormPostHTMLTemplate(context.Context) *template.Template {
    return fosite.DefaultFormPostTemplate
}

func (c *Config) GetTokenURLs(ctx context.Context) []string {
    return stringslice.Unique([]string{
        c.OAuth2TokenURL(ctx).String(),
        urlx.AppendPaths(c.deps.Config().PublicURL(ctx), oauth2.TokenPath).String(),
    })
}