hydra/fositex/config.go

232 lines
6.9 KiB
Go

// 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/hydra/v2/driver/config"
"github.com/ory/hydra/v2/fosite"
"github.com/ory/hydra/v2/fosite/compose"
"github.com/ory/hydra/v2/fosite/i18n"
"github.com/ory/hydra/v2/fosite/token/jwt"
"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
ClientHasher() fosite.Hasher
ExtraFositeFactories() []Factory
}
type Factory func(config fosite.Configurator, storage fosite.Storage, strategy interface{}) interface{}
type Config struct {
deps configDependencies
authorizeEndpointHandlers fosite.AuthorizeEndpointHandlers
tokenEndpointHandlers fosite.TokenEndpointHandlers
tokenIntrospectionHandlers fosite.TokenIntrospectionHandlers
revocationHandlers fosite.RevocationHandlers
deviceEndpointHandlers fosite.DeviceEndpointHandlers
jwksFetcherStrategy fosite.JWKSFetcherStrategy
*config.DefaultProvider
}
var (
defaultResponseModeHandler = fosite.NewDefaultResponseModeHandler()
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,
compose.RFC8628DeviceFactory,
compose.RFC8628DeviceAuthorizationTokenFactory,
compose.OpenIDConnectDeviceFactory,
}
)
func NewConfig(deps configDependencies) *Config {
return &Config{
deps: deps,
DefaultProvider: deps.Config(),
}
}
func (c *Config) LoadDefaultHandlers(storage fosite.Storage, strategy interface{}) {
factories := append(defaultFactories, c.deps.ExtraFositeFactories()...)
for _, factory := range factories {
res := factory(c, storage, 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)
}
if dh, ok := res.(fosite.DeviceEndpointHandler); ok {
c.deviceEndpointHandlers.Append(dh)
}
}
}
func (c *Config) GetJWKSFetcherStrategy(context.Context) fosite.JWKSFetcherStrategy {
if c.jwksFetcherStrategy == nil {
c.jwksFetcherStrategy = fosite.NewDefaultJWKSFetcherStrategy(fosite.JWKSFetcherWithHTTPClientSource(
func(ctx context.Context) *retryablehttp.Client { return c.deps.HTTPClient(ctx) },
))
}
return c.jwksFetcherStrategy
}
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
}
// GetDeviceEndpointHandlers returns the deviceEndpointHandlers
func (c *Config) GetDeviceEndpointHandlers(context.Context) fosite.DeviceEndpointHandlers {
return c.deviceEndpointHandlers
}
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(),
})
}
// GetDeviceVerificationURL returns the device verification url
func (c *Config) GetDeviceVerificationURL(ctx context.Context) string {
return urlx.AppendPaths(c.deps.Config().PublicURL(ctx), oauth2.DeviceVerificationPath).String()
}