119 lines
3.2 KiB
Go
119 lines
3.2 KiB
Go
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package provider
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"sync"
|
|
|
|
"go.pinniped.dev/pkg/oidcclient"
|
|
"go.pinniped.dev/pkg/oidcclient/nonce"
|
|
"go.pinniped.dev/pkg/oidcclient/pkce"
|
|
)
|
|
|
|
type UpstreamOIDCIdentityProviderI interface {
|
|
// A name for this upstream provider, which will be used as a component of the path for the callback endpoint
|
|
// hosted by the Supervisor.
|
|
GetName() string
|
|
|
|
// The Oauth client ID registered with the upstream provider to be used in the authorization code flow.
|
|
GetClientID() string
|
|
|
|
// The Authorization Endpoint fetched from discovery.
|
|
GetAuthorizationURL() *url.URL
|
|
|
|
// Scopes to request in authorization flow.
|
|
GetScopes() []string
|
|
|
|
// ID Token username claim name. May return empty string, in which case we will use some reasonable defaults.
|
|
GetUsernameClaim() string
|
|
|
|
// ID Token groups claim name. May return empty string, in which case we won't try to read groups from the upstream provider.
|
|
GetGroupsClaim() string
|
|
|
|
AuthcodeExchanger
|
|
}
|
|
|
|
// Performs upstream OIDC authorization code exchange and token validation.
|
|
// Returns the validated raw tokens as well as the parsed claims of the ID token.
|
|
type AuthcodeExchanger interface {
|
|
ExchangeAuthcodeAndValidateTokens(
|
|
ctx context.Context,
|
|
authcode string,
|
|
pkceCodeVerifier pkce.Code,
|
|
expectedIDTokenNonce nonce.Nonce,
|
|
) (tokens oidcclient.Token, parsedIDTokenClaims map[string]interface{}, err error)
|
|
}
|
|
|
|
type UpstreamOIDCIdentityProvider struct {
|
|
Name string
|
|
ClientID string
|
|
AuthorizationURL url.URL
|
|
UsernameClaim string
|
|
GroupsClaim string
|
|
Scopes []string
|
|
}
|
|
|
|
func (u *UpstreamOIDCIdentityProvider) GetName() string {
|
|
return u.Name
|
|
}
|
|
|
|
func (u *UpstreamOIDCIdentityProvider) GetClientID() string {
|
|
return u.ClientID
|
|
}
|
|
|
|
func (u *UpstreamOIDCIdentityProvider) GetAuthorizationURL() *url.URL {
|
|
return &u.AuthorizationURL
|
|
}
|
|
|
|
func (u *UpstreamOIDCIdentityProvider) GetScopes() []string {
|
|
return u.Scopes
|
|
}
|
|
|
|
func (u *UpstreamOIDCIdentityProvider) GetUsernameClaim() string {
|
|
return u.UsernameClaim
|
|
}
|
|
|
|
func (u *UpstreamOIDCIdentityProvider) GetGroupsClaim() string {
|
|
return u.GroupsClaim
|
|
}
|
|
|
|
func (u *UpstreamOIDCIdentityProvider) ExchangeAuthcodeAndValidateTokens(
|
|
ctx context.Context,
|
|
authcode string,
|
|
pkceCodeVerifier pkce.Code,
|
|
expectedIDTokenNonce nonce.Nonce,
|
|
) (oidcclient.Token, map[string]interface{}, error) {
|
|
panic("TODO implement me") // TODO
|
|
}
|
|
|
|
type DynamicUpstreamIDPProvider interface {
|
|
SetIDPList(oidcIDPs []UpstreamOIDCIdentityProviderI)
|
|
GetIDPList() []UpstreamOIDCIdentityProviderI
|
|
}
|
|
|
|
type dynamicUpstreamIDPProvider struct {
|
|
oidcProviders []UpstreamOIDCIdentityProviderI
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
func NewDynamicUpstreamIDPProvider() DynamicUpstreamIDPProvider {
|
|
return &dynamicUpstreamIDPProvider{
|
|
oidcProviders: []UpstreamOIDCIdentityProviderI{},
|
|
}
|
|
}
|
|
|
|
func (p *dynamicUpstreamIDPProvider) SetIDPList(oidcIDPs []UpstreamOIDCIdentityProviderI) {
|
|
p.mutex.Lock() // acquire a write lock
|
|
defer p.mutex.Unlock()
|
|
p.oidcProviders = oidcIDPs
|
|
}
|
|
|
|
func (p *dynamicUpstreamIDPProvider) GetIDPList() []UpstreamOIDCIdentityProviderI {
|
|
p.mutex.RLock() // acquire a read lock
|
|
defer p.mutex.RUnlock()
|
|
return p.oidcProviders
|
|
}
|