ContainerImage.Pinniped/internal/oidc/oidc.go

78 lines
2.9 KiB
Go
Raw Normal View History

// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package oidc contains common OIDC functionality needed by Pinniped.
package oidc
import (
"crypto/ecdsa"
"time"
"github.com/ory/fosite"
"github.com/ory/fosite/compose"
)
const (
WellKnownEndpointPath = "/.well-known/openid-configuration"
AuthorizationEndpointPath = "/oauth2/authorize"
TokenEndpointPath = "/oauth2/token" //nolint:gosec // ignore lint warning that this is a credential
JWKSEndpointPath = "/jwks.json"
)
func PinnipedCLIOIDCClient() *fosite.DefaultOpenIDConnectClient {
return &fosite.DefaultOpenIDConnectClient{
DefaultClient: &fosite.DefaultClient{
ID: "pinniped-cli",
Public: true,
RedirectURIs: []string{"http://127.0.0.1/callback"},
ResponseTypes: []string{"code"},
GrantTypes: []string{"authorization_code"},
Scopes: []string{"openid", "profile", "email"},
},
TokenEndpointAuthMethod: "none",
}
}
func FositeOauth2Helper(
issuerURL string,
oauthStore fosite.Storage,
hmacSecretOfLengthAtLeast32 []byte,
jwtSigningKey *ecdsa.PrivateKey,
) fosite.OAuth2Provider {
oauthConfig := &compose.Config{
AuthorizeCodeLifespan: 3 * time.Minute, // seems more than long enough to exchange a code
IDTokenLifespan: 5 * time.Minute, // match clientCertificateTTL since it has similar properties to this token
AccessTokenLifespan: 5 * time.Minute, // match clientCertificateTTL since it has similar properties to this token
RefreshTokenLifespan: 16 * time.Hour, // long enough for a single workday
IDTokenIssuer: issuerURL,
TokenURL: "", // TODO set once we have this endpoint written
ScopeStrategy: fosite.ExactScopeStrategy, // be careful and only support exact string matching for scopes
AudienceMatchingStrategy: nil, // I believe the default is fine
EnforcePKCE: true, // follow current set of best practices and always require PKCE
AllowedPromptValues: []string{"none"}, // TODO unclear what we should set here
RefreshTokenScopes: nil, // TODO decide what makes sense when we add refresh token support
MinParameterEntropy: 32, // 256 bits seems about right
}
return compose.Compose(
oauthConfig,
oauthStore,
&compose.CommonStrategy{
// Note that Fosite requires the HMAC secret to be at least 32 bytes.
CoreStrategy: compose.NewOAuth2HMACStrategy(oauthConfig, hmacSecretOfLengthAtLeast32, nil),
OpenIDConnectTokenStrategy: compose.NewOpenIDConnectECDSAStrategy(oauthConfig, jwtSigningKey),
},
nil, // hasher, defaults to using BCrypt when nil. Used for hashing client secrets.
compose.OAuth2AuthorizeExplicitFactory,
// compose.OAuth2RefreshTokenGrantFactory,
compose.OpenIDConnectExplicitFactory,
// compose.OpenIDConnectRefreshFactory,
compose.OAuth2PKCEFactory,
)
}