(discovery) config and storage
This commit is contained in:
parent
ce6f3182a2
commit
ecea7e3730
9 changed files with 132 additions and 38 deletions
|
@ -12,6 +12,11 @@ type Configuration interface {
|
|||
TokenEndpoint() Endpoint
|
||||
UserinfoEndpoint() Endpoint
|
||||
KeysEndpoint() Endpoint
|
||||
|
||||
// SupportedScopes() []string
|
||||
AuthMethodBasicSupported() bool
|
||||
AuthMethodPostSupported() bool
|
||||
|
||||
Port() string
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ const (
|
|||
defaultIntrospectEndpoint = "introspect"
|
||||
defaultUserinfoEndpoint = "userinfo"
|
||||
defaultKeysEndpoint = "keys"
|
||||
|
||||
authMethodBasic = "client_secret_basic"
|
||||
authMethodPost = "client_secret_post"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -94,19 +97,27 @@ func WithCustomUserinfoEndpoint(endpoint Endpoint) DefaultOPOpts {
|
|||
}
|
||||
}
|
||||
|
||||
func NewDefaultOP(config *Config, storage Storage, opOpts ...DefaultOPOpts) (OpenIDProvider, error) {
|
||||
func NewDefaultOP(config *Config, authStorage AuthStorage, opStorage OPStorage, opOpts ...DefaultOPOpts) (OpenIDProvider, error) {
|
||||
err := ValidateIssuer(config.Issuer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storage := struct {
|
||||
AuthStorage
|
||||
OPStorage
|
||||
}{
|
||||
AuthStorage: authStorage,
|
||||
OPStorage: opStorage,
|
||||
}
|
||||
|
||||
p := &DefaultOP{
|
||||
config: config,
|
||||
storage: storage,
|
||||
endpoints: DefaultEndpoints,
|
||||
}
|
||||
|
||||
p.signer, err = NewDefaultSigner(storage)
|
||||
p.signer, err = NewDefaultSigner(authStorage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -117,7 +128,7 @@ func NewDefaultOP(config *Config, storage Storage, opOpts ...DefaultOPOpts) (Ope
|
|||
}
|
||||
}
|
||||
|
||||
p.discoveryConfig = CreateDiscoveryConfig(p)
|
||||
p.discoveryConfig = CreateDiscoveryConfig(p, p.signer)
|
||||
|
||||
router := CreateRouter(p)
|
||||
p.http = &http.Server{
|
||||
|
@ -152,6 +163,14 @@ func (p *DefaultOP) KeysEndpoint() Endpoint {
|
|||
return Endpoint(p.endpoints.JwksURI)
|
||||
}
|
||||
|
||||
func (p *DefaultOP) AuthMethodBasicSupported() bool {
|
||||
return true //TODO: config
|
||||
}
|
||||
|
||||
func (p *DefaultOP) AuthMethodPostSupported() bool {
|
||||
return true //TODO: config
|
||||
}
|
||||
|
||||
func (p *DefaultOP) Port() string {
|
||||
return p.config.Port
|
||||
}
|
||||
|
@ -218,6 +237,8 @@ func (p *DefaultOP) HandleExchange(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (p *DefaultOP) handleTokenExchange(w http.ResponseWriter, r *http.Request) {
|
||||
ExchangeRequestError(w, r, ErrServerError("not implemented"))
|
||||
return
|
||||
tokenRequest, err := ParseTokenExchangeRequest(w, r)
|
||||
if err != nil {
|
||||
//TODO: return err
|
||||
|
|
|
@ -11,7 +11,7 @@ func Discover(w http.ResponseWriter, config *oidc.DiscoveryConfiguration) {
|
|||
utils.MarshalJSON(w, config)
|
||||
}
|
||||
|
||||
func CreateDiscoveryConfig(c Configuration) *oidc.DiscoveryConfiguration {
|
||||
func CreateDiscoveryConfig(c Configuration, s Signer) *oidc.DiscoveryConfiguration {
|
||||
return &oidc.DiscoveryConfiguration{
|
||||
Issuer: c.Issuer(),
|
||||
AuthorizationEndpoint: c.AuthorizationEndpoint().Absolute(c.Issuer()),
|
||||
|
@ -20,14 +20,61 @@ func CreateDiscoveryConfig(c Configuration) *oidc.DiscoveryConfiguration {
|
|||
UserinfoEndpoint: c.UserinfoEndpoint().Absolute(c.Issuer()),
|
||||
// EndSessionEndpoint: c.TokenEndpoint().Absolute(c.Issuer())(c.EndSessionEndpoint),
|
||||
// CheckSessionIframe: c.TokenEndpoint().Absolute(c.Issuer())(c.CheckSessionIframe),
|
||||
JwksURI: c.KeysEndpoint().Absolute(c.Issuer()),
|
||||
// ScopesSupported: oidc.SupportedScopes,
|
||||
// ResponseTypesSupported: responseTypes,
|
||||
// GrantTypesSupported: oidc.SupportedGrantTypes,
|
||||
JwksURI: c.KeysEndpoint().Absolute(c.Issuer()),
|
||||
ScopesSupported: scopes(c),
|
||||
ResponseTypesSupported: responseTypes(c),
|
||||
GrantTypesSupported: grantTypes(c),
|
||||
// ClaimsSupported: oidc.SupportedClaims,
|
||||
// IdTokenSigningAlgValuesSupported: []string{keys.SigningAlgorithm},
|
||||
// SubjectTypesSupported: []string{"public"},
|
||||
// TokenEndpointAuthMethodsSupported:
|
||||
|
||||
IDTokenSigningAlgValuesSupported: sigAlgorithms(s),
|
||||
SubjectTypesSupported: subjectTypes(c),
|
||||
TokenEndpointAuthMethodsSupported: authMethods(c),
|
||||
}
|
||||
}
|
||||
|
||||
func scopes(c Configuration) []string {
|
||||
return []string{
|
||||
"openid",
|
||||
"profile",
|
||||
"email",
|
||||
"phone",
|
||||
} //TODO: config
|
||||
}
|
||||
|
||||
func responseTypes(c Configuration) []string {
|
||||
return []string{
|
||||
"code",
|
||||
"id_token",
|
||||
// "code token",
|
||||
// "code id_token",
|
||||
"id_token token",
|
||||
// "code id_token token"
|
||||
}
|
||||
}
|
||||
|
||||
func grantTypes(c Configuration) []string {
|
||||
return []string{
|
||||
"client_credentials",
|
||||
"authorization_code",
|
||||
// "password",
|
||||
"urn:ietf:params:oauth:grant-type:token-exchange",
|
||||
}
|
||||
}
|
||||
|
||||
func sigAlgorithms(s Signer) []string {
|
||||
return []string{string(s.SignatureAlgorithm())}
|
||||
}
|
||||
|
||||
func subjectTypes(c Configuration) []string {
|
||||
return []string{"public"} //TODO: config
|
||||
}
|
||||
|
||||
func authMethods(c Configuration) []string {
|
||||
authMethods := make([]string, 0, 2)
|
||||
if c.AuthMethodBasicSupported() {
|
||||
authMethods = append(authMethods, authMethodBasic)
|
||||
}
|
||||
if c.AuthMethodPostSupported() {
|
||||
authMethods = append(authMethods, authMethodPost)
|
||||
}
|
||||
return authMethods
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ func TestDiscover(t *testing.T) {
|
|||
func TestCreateDiscoveryConfig(t *testing.T) {
|
||||
type args struct {
|
||||
c op.Configuration
|
||||
s op.Signer
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -52,7 +53,7 @@ func TestCreateDiscoveryConfig(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := op.CreateDiscoveryConfig(tt.args.c); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := op.CreateDiscoveryConfig(tt.args.c, tt.args.s); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("CreateDiscoveryConfig() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -15,11 +15,11 @@ type Signer interface {
|
|||
|
||||
type idTokenSigner struct {
|
||||
signer jose.Signer
|
||||
storage Storage
|
||||
storage AuthStorage
|
||||
algorithm jose.SignatureAlgorithm
|
||||
}
|
||||
|
||||
func NewDefaultSigner(storage Storage) (Signer, error) {
|
||||
func NewDefaultSigner(storage AuthStorage) (Signer, error) {
|
||||
s := &idTokenSigner{
|
||||
storage: storage,
|
||||
}
|
||||
|
|
|
@ -8,18 +8,27 @@ import (
|
|||
"github.com/caos/oidc/pkg/oidc"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
type AuthStorage interface {
|
||||
CreateAuthRequest(*oidc.AuthRequest) (AuthRequest, error)
|
||||
GetClientByClientID(string) (Client, error)
|
||||
AuthRequestByID(string) (AuthRequest, error)
|
||||
AuthRequestByCode(Client, string, string) (AuthRequest, error)
|
||||
AuthorizeClientIDSecret(string, string) (Client, error)
|
||||
AuthorizeClientIDCodeVerifier(string, string) (Client, error)
|
||||
DeleteAuthRequestAndCode(string, string) error
|
||||
|
||||
GetSigningKey() (*jose.SigningKey, error)
|
||||
GetKeySet() (jose.JSONWebKeySet, error)
|
||||
}
|
||||
|
||||
type OPStorage interface {
|
||||
GetClientByClientID(string) (Client, error)
|
||||
AuthorizeClientIDSecret(string, string) (Client, error)
|
||||
AuthorizeClientIDCodeVerifier(string, string) (Client, error)
|
||||
}
|
||||
|
||||
type Storage interface {
|
||||
AuthStorage
|
||||
OPStorage
|
||||
}
|
||||
|
||||
type AuthRequest interface {
|
||||
GetID() string
|
||||
GetACR() string
|
||||
|
|
|
@ -17,6 +17,8 @@ type Exchanger interface {
|
|||
Storage() Storage
|
||||
Decoder() *schema.Decoder
|
||||
Signer() Signer
|
||||
AuthMethodBasicSupported() bool
|
||||
AuthMethodPostSupported() bool
|
||||
}
|
||||
|
||||
func CodeExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
||||
|
@ -37,7 +39,7 @@ func CodeExchange(w http.ResponseWriter, r *http.Request, exchanger Exchanger) {
|
|||
return
|
||||
}
|
||||
|
||||
client, err := AuthorizeClient(r, tokenReq, exchanger.Storage())
|
||||
client, err := AuthorizeClient(r, tokenReq, exchanger)
|
||||
if err != nil {
|
||||
ExchangeRequestError(w, r, err)
|
||||
return
|
||||
|
@ -99,19 +101,25 @@ func CreateIDToken(issuer string, authReq AuthRequest, validity time.Duration, a
|
|||
return signer.SignIDToken(claims)
|
||||
}
|
||||
|
||||
func AuthorizeClient(r *http.Request, tokenReq *oidc.AccessTokenRequest, storage Storage) (Client, error) {
|
||||
func AuthorizeClient(r *http.Request, tokenReq *oidc.AccessTokenRequest, exchanger Exchanger) (Client, error) {
|
||||
if tokenReq.ClientID == "" {
|
||||
if !exchanger.AuthMethodBasicSupported() {
|
||||
return nil, errors.New("basic not supported")
|
||||
}
|
||||
clientID, clientSecret, ok := r.BasicAuth()
|
||||
if ok {
|
||||
return storage.AuthorizeClientIDSecret(clientID, clientSecret)
|
||||
return exchanger.Storage().AuthorizeClientIDSecret(clientID, clientSecret)
|
||||
}
|
||||
|
||||
}
|
||||
if tokenReq.ClientSecret != "" {
|
||||
return storage.AuthorizeClientIDSecret(tokenReq.ClientID, tokenReq.ClientSecret)
|
||||
if !exchanger.AuthMethodPostSupported() {
|
||||
return nil, errors.New("post not supported")
|
||||
}
|
||||
return exchanger.Storage().AuthorizeClientIDSecret(tokenReq.ClientID, tokenReq.ClientSecret)
|
||||
}
|
||||
if tokenReq.CodeVerifier != "" {
|
||||
return storage.AuthorizeClientIDCodeVerifier(tokenReq.ClientID, tokenReq.CodeVerifier)
|
||||
return exchanger.Storage().AuthorizeClientIDCodeVerifier(tokenReq.ClientID, tokenReq.CodeVerifier)
|
||||
}
|
||||
return nil, errors.New("Unimplemented") //TODO: impl
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue