Make supported scopes configurable
This commit is contained in:
parent
01021e71a0
commit
3e75107c9c
5 changed files with 76 additions and 22 deletions
|
@ -11,6 +11,7 @@ import (
|
|||
"golang.org/x/text/language"
|
||||
|
||||
"github.com/zitadel/oidc/example/server/storage"
|
||||
"github.com/zitadel/oidc/pkg/oidc"
|
||||
"github.com/zitadel/oidc/pkg/op"
|
||||
)
|
||||
|
||||
|
@ -80,31 +81,33 @@ func SetupServer(ctx context.Context, issuer string, storage Storage) *mux.Route
|
|||
// and a predefined default logout uri
|
||||
// it will enable all options (see descriptions)
|
||||
func newOP(ctx context.Context, storage op.Storage, issuer string, key [32]byte) (op.OpenIDProvider, error) {
|
||||
config := &op.Config{
|
||||
Issuer: issuer,
|
||||
CryptoKey: key,
|
||||
config := op.NewConfig()
|
||||
config.Issuer = issuer
|
||||
config.CryptoKey = key
|
||||
|
||||
// will be used if the end_session endpoint is called without a post_logout_redirect_uri
|
||||
DefaultLogoutRedirectURI: pathLoggedOut,
|
||||
config.SupportedScopes = []string{oidc.ScopeOpenID, oidc.ScopeOfflineAccess}
|
||||
|
||||
// enables code_challenge_method S256 for PKCE (and therefore PKCE in general)
|
||||
CodeMethodS256: true,
|
||||
// will be used if the end_session endpoint is called without a post_logout_redirect_uri
|
||||
config.DefaultLogoutRedirectURI = pathLoggedOut
|
||||
|
||||
// enables additional client_id/client_secret authentication by form post (not only HTTP Basic Auth)
|
||||
AuthMethodPost: true,
|
||||
// enables code_challenge_method S256 for PKCE (and therefore PKCE in general)
|
||||
config.CodeMethodS256 = true
|
||||
|
||||
// enables additional authentication by using private_key_jwt
|
||||
AuthMethodPrivateKeyJWT: true,
|
||||
// enables additional client_id/client_secret authentication by form post (not only HTTP Basic Auth)
|
||||
config.AuthMethodPost = true
|
||||
|
||||
// enables refresh_token grant use
|
||||
GrantTypeRefreshToken: true,
|
||||
// enables additional authentication by using private_key_jwt
|
||||
config.AuthMethodPrivateKeyJWT = true
|
||||
|
||||
// enables use of the `request` Object parameter
|
||||
RequestObjectSupported: true,
|
||||
// enables refresh_token grant use
|
||||
config.GrantTypeRefreshToken = true
|
||||
|
||||
// enables use of the `request` Object parameter
|
||||
config.RequestObjectSupported = true
|
||||
|
||||
// this example has only static texts (in English), so we'll set the here accordingly
|
||||
config.SupportedUILocales = []language.Tag{language.English}
|
||||
|
||||
// this example has only static texts (in English), so we'll set the here accordingly
|
||||
SupportedUILocales: []language.Tag{language.English},
|
||||
}
|
||||
handler, err := op.NewOpenIDProvider(ctx, config, storage,
|
||||
// as an example on how to customize an endpoint this will change the authorization_endpoint from /authorize to /auth
|
||||
op.WithCustomAuthEndpoint(op.NewEndpoint("auth")),
|
||||
|
|
|
@ -36,6 +36,8 @@ type Configuration interface {
|
|||
RequestObjectSigningAlgorithmsSupported() []string
|
||||
|
||||
SupportedUILocales() []language.Tag
|
||||
|
||||
SupportedScopes() []string
|
||||
}
|
||||
|
||||
func ValidateIssuer(issuer string) error {
|
||||
|
|
|
@ -27,7 +27,7 @@ func CreateDiscoveryConfig(c Configuration, s Signer) *oidc.DiscoveryConfigurati
|
|||
RevocationEndpoint: c.RevocationEndpoint().Absolute(c.Issuer()),
|
||||
EndSessionEndpoint: c.EndSessionEndpoint().Absolute(c.Issuer()),
|
||||
JwksURI: c.KeysEndpoint().Absolute(c.Issuer()),
|
||||
ScopesSupported: Scopes(c),
|
||||
ScopesSupported: c.SupportedScopes(),
|
||||
ResponseTypesSupported: ResponseTypes(c),
|
||||
GrantTypesSupported: GrantTypes(c),
|
||||
SubjectTypesSupported: SubjectTypes(c),
|
||||
|
|
|
@ -301,6 +301,20 @@ func (mr *MockConfigurationMockRecorder) RevocationEndpointSigningAlgorithmsSupp
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RevocationEndpointSigningAlgorithmsSupported", reflect.TypeOf((*MockConfiguration)(nil).RevocationEndpointSigningAlgorithmsSupported))
|
||||
}
|
||||
|
||||
// SupportedScopes mocks base method.
|
||||
func (m *MockConfiguration) SupportedScopes() []string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SupportedScopes")
|
||||
ret0, _ := ret[0].([]string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SupportedScopes indicates an expected call of SupportedScopes.
|
||||
func (mr *MockConfigurationMockRecorder) SupportedScopes() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SupportedScopes", reflect.TypeOf((*MockConfiguration)(nil).SupportedScopes))
|
||||
}
|
||||
|
||||
// SupportedUILocales mocks base method.
|
||||
func (m *MockConfiguration) SupportedUILocales() []language.Tag {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
41
pkg/op/op.go
41
pkg/op/op.go
|
@ -14,6 +14,7 @@ import (
|
|||
|
||||
httphelper "github.com/zitadel/oidc/pkg/http"
|
||||
"github.com/zitadel/oidc/pkg/oidc"
|
||||
str "github.com/zitadel/oidc/pkg/strings"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -92,7 +93,7 @@ func authCallbackPath(o OpenIDProvider) string {
|
|||
return o.AuthorizationEndpoint().Relative() + authCallbackPathSuffix
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
type config struct {
|
||||
Issuer string
|
||||
CryptoKey [32]byte
|
||||
DefaultLogoutRedirectURI string
|
||||
|
@ -102,6 +103,7 @@ type Config struct {
|
|||
GrantTypeRefreshToken bool
|
||||
RequestObjectSupported bool
|
||||
SupportedUILocales []language.Tag
|
||||
SupportedScopes []string
|
||||
}
|
||||
|
||||
type endpoints struct {
|
||||
|
@ -115,6 +117,14 @@ type endpoints struct {
|
|||
JwksURI Endpoint
|
||||
}
|
||||
|
||||
func NewConfig() *config {
|
||||
// config defaults
|
||||
config := &config{
|
||||
SupportedScopes: DefaultSupportedScopes,
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// NewOpenIDProvider creates a provider. The provider provides (with HttpHandler())
|
||||
// a http.Router that handles a suite of endpoints (some paths can be overridden):
|
||||
// /healthz
|
||||
|
@ -133,7 +143,7 @@ type endpoints struct {
|
|||
// Successful logins should mark the request as authorized and redirect back to to
|
||||
// op.AuthCallbackURL(provider) which is probably /callback. On the redirect back
|
||||
// to the AuthCallbackURL, the request id should be passed as the "id" parameter.
|
||||
func NewOpenIDProvider(ctx context.Context, config *Config, storage Storage, opOpts ...Option) (OpenIDProvider, error) {
|
||||
func NewOpenIDProvider(ctx context.Context, config *config, storage Storage, opOpts ...Option) (OpenIDProvider, error) {
|
||||
err := ValidateIssuer(config.Issuer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -175,7 +185,7 @@ func NewOpenIDProvider(ctx context.Context, config *Config, storage Storage, opO
|
|||
}
|
||||
|
||||
type openidProvider struct {
|
||||
config *Config
|
||||
config *config
|
||||
endpoints *endpoints
|
||||
storage Storage
|
||||
signer Signer
|
||||
|
@ -192,6 +202,23 @@ type openidProvider struct {
|
|||
accessTokenVerifierOpts []AccessTokenVerifierOpt
|
||||
}
|
||||
|
||||
func RestrictToSupportedScopes(provider *openidProvider, scopes []string) []string {
|
||||
newScopeList := make([]string, 0, len(scopes))
|
||||
// filter out unsupported scopes
|
||||
for _, scope := range scopes {
|
||||
if str.Contains(provider.config.SupportedScopes, scope) {
|
||||
newScopeList = append(newScopeList, scope)
|
||||
}
|
||||
}
|
||||
|
||||
return newScopeList
|
||||
}
|
||||
|
||||
func (o *openidProvider) ValidateAuthRequest(ctx context.Context, authReq *oidc.AuthRequest, storage Storage, verifier IDTokenHintVerifier) (string, error) {
|
||||
authReq.Scopes = RestrictToSupportedScopes(o, authReq.Scopes)
|
||||
return ValidateAuthRequest(ctx, authReq, storage, verifier)
|
||||
}
|
||||
|
||||
func (o *openidProvider) Issuer() string {
|
||||
return o.config.Issuer
|
||||
}
|
||||
|
@ -285,6 +312,14 @@ func (o *openidProvider) SupportedUILocales() []language.Tag {
|
|||
return o.config.SupportedUILocales
|
||||
}
|
||||
|
||||
func (o *openidProvider) SupportedScopes() []string {
|
||||
return o.config.SupportedScopes
|
||||
}
|
||||
|
||||
func (o *openidProvider) SetScopesSupported(scopes []string) {
|
||||
o.config.SupportedScopes = scopes
|
||||
}
|
||||
|
||||
func (o *openidProvider) Storage() Storage {
|
||||
return o.storage
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue