jwt profile and fixes
This commit is contained in:
parent
d91fe7aacf
commit
8b1d405f91
5 changed files with 168 additions and 168 deletions
|
@ -7,8 +7,125 @@ import (
|
||||||
"github.com/caos/oidc/pkg/op"
|
"github.com/caos/oidc/pkg/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
var clients = map[string]*Client{}
|
var (
|
||||||
|
//we use the default login UI and pass the (auth request) id
|
||||||
|
defaultLoginURL = func(id string) string {
|
||||||
|
return "/login/username?authRequestID=" + id
|
||||||
|
}
|
||||||
|
|
||||||
|
//clients to be used by the storage interface
|
||||||
|
clients = map[string]*Client{}
|
||||||
|
)
|
||||||
|
|
||||||
|
//Client represents the internal model of an OAuth/OIDC client
|
||||||
|
//this could also be your database model
|
||||||
|
type Client struct {
|
||||||
|
id string
|
||||||
|
secret string
|
||||||
|
redirectURIs []string
|
||||||
|
applicationType op.ApplicationType
|
||||||
|
authMethod oidc.AuthMethod
|
||||||
|
loginURL func(string) string
|
||||||
|
responseTypes []oidc.ResponseType
|
||||||
|
grantTypes []oidc.GrantType
|
||||||
|
accessTokenType op.AccessTokenType
|
||||||
|
devMode bool
|
||||||
|
idTokenUserinfoClaimsAssertion bool
|
||||||
|
clockSkew time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetID must return the client_id
|
||||||
|
func (c *Client) GetID() string {
|
||||||
|
return c.id
|
||||||
|
}
|
||||||
|
|
||||||
|
//RedirectURIs must return the registered redirect_uris for Code and Implicit Flow
|
||||||
|
func (c *Client) RedirectURIs() []string {
|
||||||
|
return c.redirectURIs
|
||||||
|
}
|
||||||
|
|
||||||
|
//PostLogoutRedirectURIs must return the registered post_logout_redirect_uris for signouts
|
||||||
|
func (c *Client) PostLogoutRedirectURIs() []string {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ApplicationType must return the type of the client (app, native, user agent)
|
||||||
|
func (c *Client) ApplicationType() op.ApplicationType {
|
||||||
|
return c.applicationType
|
||||||
|
}
|
||||||
|
|
||||||
|
//AuthMethod must return the authentication method (client_secret_basic, client_secret_post, none, private_key_jwt)
|
||||||
|
func (c *Client) AuthMethod() oidc.AuthMethod {
|
||||||
|
return c.authMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
//ResponseTypes must return all allowed response types (code, id_token token, id_token)
|
||||||
|
//these must match with the allowed grant types
|
||||||
|
func (c *Client) ResponseTypes() []oidc.ResponseType {
|
||||||
|
return c.responseTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
//GrantTypes must return all allowed grant types (authorization_code, refresh_token, urn:ietf:params:oauth:grant-type:jwt-bearer)
|
||||||
|
func (c *Client) GrantTypes() []oidc.GrantType {
|
||||||
|
return c.grantTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
//LoginURL will be called to redirect the user (agent) to the login UI
|
||||||
|
//you could implement some logic here to redirect the users to different login UIs depending on the client
|
||||||
|
func (c *Client) LoginURL(id string) string {
|
||||||
|
return c.loginURL(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
//AccessTokenType must return the type of access token the client uses (Bearer (opaque) or JWT)
|
||||||
|
func (c *Client) AccessTokenType() op.AccessTokenType {
|
||||||
|
return c.accessTokenType
|
||||||
|
}
|
||||||
|
|
||||||
|
//IDTokenLifetime must return the lifetime of the client's id_tokens
|
||||||
|
func (c *Client) IDTokenLifetime() time.Duration {
|
||||||
|
return 1 * time.Hour
|
||||||
|
}
|
||||||
|
|
||||||
|
//DevMode enables the use of non-compliant configs such as redirect_uris (e.g. http schema for user agent client)
|
||||||
|
func (c *Client) DevMode() bool {
|
||||||
|
return c.devMode
|
||||||
|
}
|
||||||
|
|
||||||
|
//RestrictAdditionalIdTokenScopes allows specifying which custom scopes shall be asserted into the id_token
|
||||||
|
func (c *Client) RestrictAdditionalIdTokenScopes() func(scopes []string) []string {
|
||||||
|
return func(scopes []string) []string {
|
||||||
|
return scopes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//RestrictAdditionalAccessTokenScopes allows specifying which custom scopes shall be asserted into the JWT access_token
|
||||||
|
func (c *Client) RestrictAdditionalAccessTokenScopes() func(scopes []string) []string {
|
||||||
|
return func(scopes []string) []string {
|
||||||
|
return scopes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//IsScopeAllowed enables Client specific custom scopes validation
|
||||||
|
//in this example we allow the CustomScope for all clients
|
||||||
|
func (c *Client) IsScopeAllowed(scope string) bool {
|
||||||
|
return scope == CustomScope
|
||||||
|
}
|
||||||
|
|
||||||
|
//IDTokenUserinfoClaimsAssertion allows specifying if claims of scope profile, email, phone and address are asserted into the id_token
|
||||||
|
//even if an access token if issued which violates the OIDC Core spec
|
||||||
|
//(5.4. Requesting Claims using Scope Values: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims)
|
||||||
|
//some clients though require that e.g. email is always in the id_token when requested even if an access_token is issued
|
||||||
|
func (c *Client) IDTokenUserinfoClaimsAssertion() bool {
|
||||||
|
return c.idTokenUserinfoClaimsAssertion
|
||||||
|
}
|
||||||
|
|
||||||
|
//ClockSkew enables clients to instruct the OP to apply a clock skew on the various times and expirations
|
||||||
|
//(subtract from issued_at, add to expiration, ...)
|
||||||
|
func (c *Client) ClockSkew() time.Duration {
|
||||||
|
return c.clockSkew
|
||||||
|
}
|
||||||
|
|
||||||
|
//RegisterClients enables you to register clients for the example
|
||||||
func RegisterClients(registerClients ...*Client) {
|
func RegisterClients(registerClients ...*Client) {
|
||||||
for _, client := range registerClients {
|
for _, client := range registerClients {
|
||||||
clients[client.id] = client
|
clients[client.id] = client
|
||||||
|
@ -33,7 +150,7 @@ func NativeClient(id string, redirectURIs ...string) *Client {
|
||||||
redirectURIs: redirectURIs,
|
redirectURIs: redirectURIs,
|
||||||
applicationType: op.ApplicationTypeNative,
|
applicationType: op.ApplicationTypeNative,
|
||||||
authMethod: oidc.AuthMethodNone,
|
authMethod: oidc.AuthMethodNone,
|
||||||
defaultLoginURL: defaultLoginURL,
|
loginURL: defaultLoginURL,
|
||||||
responseTypes: []oidc.ResponseType{oidc.ResponseTypeCode},
|
responseTypes: []oidc.ResponseType{oidc.ResponseTypeCode},
|
||||||
grantTypes: []oidc.GrantType{oidc.GrantTypeCode, oidc.GrantTypeRefreshToken},
|
grantTypes: []oidc.GrantType{oidc.GrantTypeCode, oidc.GrantTypeRefreshToken},
|
||||||
accessTokenType: 0,
|
accessTokenType: 0,
|
||||||
|
@ -45,18 +162,21 @@ func NativeClient(id string, redirectURIs ...string) *Client {
|
||||||
|
|
||||||
//WebClient will create a client of type web, which will always use PKCE and allow the use of refresh tokens
|
//WebClient will create a client of type web, which will always use PKCE and allow the use of refresh tokens
|
||||||
//user-defined redirectURIs may include:
|
//user-defined redirectURIs may include:
|
||||||
// - http://localhost without port specification (e.g. http://localhost/auth/callback)
|
// - http://localhost with port specification (e.g. http://localhost:9999/auth/callback)
|
||||||
//(the example will be used as default, if none is provided)
|
//(the example will be used as default, if none is provided)
|
||||||
func WebClient(id, secret string, redirectURIs ...string) *Client {
|
func WebClient(id, secret string, redirectURIs ...string) *Client {
|
||||||
return &Client{
|
if len(redirectURIs) == 0 {
|
||||||
id: id,
|
redirectURIs = []string{
|
||||||
secret: secret,
|
|
||||||
redirectURIs: []string{
|
|
||||||
"http://localhost:9999/auth/callback",
|
"http://localhost:9999/auth/callback",
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
return &Client{
|
||||||
|
id: id,
|
||||||
|
secret: secret,
|
||||||
|
redirectURIs: redirectURIs,
|
||||||
applicationType: op.ApplicationTypeWeb,
|
applicationType: op.ApplicationTypeWeb,
|
||||||
authMethod: oidc.AuthMethodBasic,
|
authMethod: oidc.AuthMethodBasic,
|
||||||
defaultLoginURL: defaultLoginURL,
|
loginURL: defaultLoginURL,
|
||||||
responseTypes: []oidc.ResponseType{oidc.ResponseTypeCode},
|
responseTypes: []oidc.ResponseType{oidc.ResponseTypeCode},
|
||||||
grantTypes: []oidc.GrantType{oidc.GrantTypeCode, oidc.GrantTypeRefreshToken},
|
grantTypes: []oidc.GrantType{oidc.GrantTypeCode, oidc.GrantTypeRefreshToken},
|
||||||
accessTokenType: 0,
|
accessTokenType: 0,
|
||||||
|
@ -65,88 +185,3 @@ func WebClient(id, secret string, redirectURIs ...string) *Client {
|
||||||
clockSkew: 0,
|
clockSkew: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
id string
|
|
||||||
secret string
|
|
||||||
redirectURIs []string
|
|
||||||
applicationType op.ApplicationType
|
|
||||||
authMethod oidc.AuthMethod
|
|
||||||
defaultLoginURL func(string) string
|
|
||||||
responseTypes []oidc.ResponseType
|
|
||||||
grantTypes []oidc.GrantType
|
|
||||||
accessTokenType op.AccessTokenType
|
|
||||||
devMode bool
|
|
||||||
idTokenUserinfoClaimsAssertion bool
|
|
||||||
clockSkew time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GetID() string {
|
|
||||||
return c.id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) RedirectURIs() []string {
|
|
||||||
return c.redirectURIs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) PostLogoutRedirectURIs() []string {
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ApplicationType() op.ApplicationType {
|
|
||||||
return c.applicationType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) AuthMethod() oidc.AuthMethod {
|
|
||||||
return c.authMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ResponseTypes() []oidc.ResponseType {
|
|
||||||
return c.responseTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) GrantTypes() []oidc.GrantType {
|
|
||||||
return c.grantTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) LoginURL(id string) string {
|
|
||||||
//we use the default login UI and pass the (auth request) id,
|
|
||||||
//but you could implement some logic here to redirect the users to different login UIs depending on the client
|
|
||||||
return c.defaultLoginURL(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) AccessTokenType() op.AccessTokenType {
|
|
||||||
return c.accessTokenType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) IDTokenLifetime() time.Duration {
|
|
||||||
return 1 * time.Hour
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) DevMode() bool {
|
|
||||||
return c.devMode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) RestrictAdditionalIdTokenScopes() func(scopes []string) []string {
|
|
||||||
return func(scopes []string) []string {
|
|
||||||
return scopes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) RestrictAdditionalAccessTokenScopes() func(scopes []string) []string {
|
|
||||||
return func(scopes []string) []string {
|
|
||||||
return scopes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) IsScopeAllowed(scope string) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) IDTokenUserinfoClaimsAssertion() bool {
|
|
||||||
return c.idTokenUserinfoClaimsAssertion
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) ClockSkew() time.Duration {
|
|
||||||
return c.clockSkew
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,13 +25,13 @@ type AuthRequest struct {
|
||||||
ApplicationID string
|
ApplicationID string
|
||||||
CallbackURI string
|
CallbackURI string
|
||||||
TransferState string
|
TransferState string
|
||||||
Prompt []Prompt
|
Prompt []string
|
||||||
UiLocales []language.Tag
|
UiLocales []language.Tag
|
||||||
LoginHint string
|
LoginHint string
|
||||||
MaxAuthAge *time.Duration
|
MaxAuthAge *time.Duration
|
||||||
UserID string
|
UserID string
|
||||||
Scopes []string
|
Scopes []string
|
||||||
ResponseType OIDCResponseType
|
ResponseType oidc.ResponseType
|
||||||
Nonce string
|
Nonce string
|
||||||
CodeChallenge *OIDCCodeChallenge
|
CodeChallenge *OIDCCodeChallenge
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ func (a *AuthRequest) GetRedirectURI() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AuthRequest) GetResponseType() oidc.ResponseType {
|
func (a *AuthRequest) GetResponseType() oidc.ResponseType {
|
||||||
return ResponseTypeToOIDC(a.ResponseType)
|
return a.ResponseType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AuthRequest) GetResponseMode() oidc.ResponseMode {
|
func (a *AuthRequest) GetResponseMode() oidc.ResponseMode {
|
||||||
|
@ -103,54 +103,20 @@ func (a *AuthRequest) Done() bool {
|
||||||
return a.passwordChecked //this example only uses password for authentication
|
return a.passwordChecked //this example only uses password for authentication
|
||||||
}
|
}
|
||||||
|
|
||||||
type Prompt int32
|
func PromptToInternal(oidcPrompt oidc.SpaceDelimitedArray) []string {
|
||||||
|
prompts := make([]string, len(oidcPrompt))
|
||||||
const (
|
|
||||||
PromptUnspecified Prompt = iota
|
|
||||||
PromptNone
|
|
||||||
PromptLogin
|
|
||||||
PromptConsent
|
|
||||||
PromptSelectAccount
|
|
||||||
)
|
|
||||||
|
|
||||||
func PromptToInternal(oidcPrompt oidc.SpaceDelimitedArray) []Prompt {
|
|
||||||
prompts := make([]Prompt, len(oidcPrompt))
|
|
||||||
for _, oidcPrompt := range oidcPrompt {
|
for _, oidcPrompt := range oidcPrompt {
|
||||||
switch oidcPrompt {
|
switch oidcPrompt {
|
||||||
case oidc.PromptNone:
|
case oidc.PromptNone,
|
||||||
prompts = append(prompts, PromptNone)
|
oidc.PromptLogin,
|
||||||
case oidc.PromptLogin:
|
oidc.PromptConsent,
|
||||||
prompts = append(prompts, PromptLogin)
|
oidc.PromptSelectAccount:
|
||||||
case oidc.PromptConsent:
|
prompts = append(prompts, oidcPrompt)
|
||||||
prompts = append(prompts, PromptConsent)
|
|
||||||
case oidc.PromptSelectAccount:
|
|
||||||
prompts = append(prompts, PromptSelectAccount)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return prompts
|
return prompts
|
||||||
}
|
}
|
||||||
|
|
||||||
type OIDCResponseType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
OIDCResponseTypeCode OIDCResponseType = iota
|
|
||||||
OIDCResponseTypeIDToken
|
|
||||||
OIDCResponseTypeIDTokenToken
|
|
||||||
)
|
|
||||||
|
|
||||||
func ResponseTypeToInternal(responseType oidc.ResponseType) OIDCResponseType {
|
|
||||||
switch responseType {
|
|
||||||
case oidc.ResponseTypeCode:
|
|
||||||
return OIDCResponseTypeCode
|
|
||||||
case oidc.ResponseTypeIDTokenOnly:
|
|
||||||
return OIDCResponseTypeIDToken
|
|
||||||
case oidc.ResponseTypeIDToken:
|
|
||||||
return OIDCResponseTypeIDTokenToken
|
|
||||||
default:
|
|
||||||
return OIDCResponseTypeCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MaxAgeToInternal(maxAge *uint) *time.Duration {
|
func MaxAgeToInternal(maxAge *uint) *time.Duration {
|
||||||
if maxAge == nil {
|
if maxAge == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -159,13 +125,6 @@ func MaxAgeToInternal(maxAge *uint) *time.Duration {
|
||||||
return &dur
|
return &dur
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthRequestOIDC struct {
|
|
||||||
Scopes []string
|
|
||||||
ResponseType interface{}
|
|
||||||
Nonce string
|
|
||||||
CodeChallenge *OIDCCodeChallenge
|
|
||||||
}
|
|
||||||
|
|
||||||
func authRequestToInternal(authReq *oidc.AuthRequest, userID string) *AuthRequest {
|
func authRequestToInternal(authReq *oidc.AuthRequest, userID string) *AuthRequest {
|
||||||
return &AuthRequest{
|
return &AuthRequest{
|
||||||
CreationDate: time.Now(),
|
CreationDate: time.Now(),
|
||||||
|
@ -178,7 +137,7 @@ func authRequestToInternal(authReq *oidc.AuthRequest, userID string) *AuthReques
|
||||||
MaxAuthAge: MaxAgeToInternal(authReq.MaxAge),
|
MaxAuthAge: MaxAgeToInternal(authReq.MaxAge),
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Scopes: authReq.Scopes,
|
Scopes: authReq.Scopes,
|
||||||
ResponseType: ResponseTypeToInternal(authReq.ResponseType),
|
ResponseType: authReq.ResponseType,
|
||||||
Nonce: authReq.Nonce,
|
Nonce: authReq.Nonce,
|
||||||
CodeChallenge: &OIDCCodeChallenge{
|
CodeChallenge: &OIDCCodeChallenge{
|
||||||
Challenge: authReq.CodeChallenge,
|
Challenge: authReq.CodeChallenge,
|
||||||
|
@ -206,19 +165,6 @@ func CodeChallengeToOIDC(challenge *OIDCCodeChallenge) *oidc.CodeChallenge {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResponseTypeToOIDC(responseType OIDCResponseType) oidc.ResponseType {
|
|
||||||
switch responseType {
|
|
||||||
case OIDCResponseTypeCode:
|
|
||||||
return oidc.ResponseTypeCode
|
|
||||||
case OIDCResponseTypeIDTokenToken:
|
|
||||||
return oidc.ResponseTypeIDToken
|
|
||||||
case OIDCResponseTypeIDToken:
|
|
||||||
return oidc.ResponseTypeIDTokenOnly
|
|
||||||
default:
|
|
||||||
return oidc.ResponseTypeCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//RefreshTokenRequestFromBusiness will simply wrap the internal RefreshToken to implement the op.RefreshTokenRequest interface
|
//RefreshTokenRequestFromBusiness will simply wrap the internal RefreshToken to implement the op.RefreshTokenRequest interface
|
||||||
func RefreshTokenRequestFromBusiness(token *RefreshToken) op.RefreshTokenRequest {
|
func RefreshTokenRequestFromBusiness(token *RefreshToken) op.RefreshTokenRequest {
|
||||||
return &RefreshTokenRequest{token}
|
return &RefreshTokenRequest{token}
|
||||||
|
|
|
@ -23,6 +23,7 @@ type storage struct {
|
||||||
tokens map[string]*Token
|
tokens map[string]*Token
|
||||||
clients map[string]*Client
|
clients map[string]*Client
|
||||||
users map[string]*User
|
users map[string]*User
|
||||||
|
services map[string]Service
|
||||||
refreshTokens map[string]*RefreshToken
|
refreshTokens map[string]*RefreshToken
|
||||||
signingKey signingKey
|
signingKey signingKey
|
||||||
}
|
}
|
||||||
|
@ -33,11 +34,6 @@ type signingKey struct {
|
||||||
Key *rsa.PrivateKey
|
Key *rsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: describe
|
|
||||||
var defaultLoginURL = func(id string) string {
|
|
||||||
return "/login/username?authRequestID=" + id
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewStorage() *storage {
|
func NewStorage() *storage {
|
||||||
key, _ := rsa.GenerateKey(rand.Reader, 2048)
|
key, _ := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
return &storage{
|
return &storage{
|
||||||
|
@ -378,13 +374,28 @@ func (s *storage) GetPrivateClaimsFromScopes(ctx context.Context, userID, client
|
||||||
//GetKeyByIDAndUserID implements the op.Storage interface
|
//GetKeyByIDAndUserID implements the op.Storage interface
|
||||||
//it will be called to validate the signatures of a JWT (JWT Profile Grant and Authentication)
|
//it will be called to validate the signatures of a JWT (JWT Profile Grant and Authentication)
|
||||||
func (s *storage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID string) (*jose.JSONWebKey, error) {
|
func (s *storage) GetKeyByIDAndUserID(ctx context.Context, keyID, userID string) (*jose.JSONWebKey, error) {
|
||||||
return nil, fmt.Errorf("example does not yet support authentication with JWT") //TODO: implement
|
service, ok := s.services[userID]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
key, ok := service.keys[keyID]
|
||||||
|
return &jose.JSONWebKey{
|
||||||
|
KeyID: keyID,
|
||||||
|
Use: "sig",
|
||||||
|
Key: key,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ValidateJWTProfileScopes implements the op.Storage interface
|
//ValidateJWTProfileScopes implements the op.Storage interface
|
||||||
//it will be called to validate the scopes of a JWT Profile Authorization Grant request
|
//it will be called to validate the scopes of a JWT Profile Authorization Grant request
|
||||||
func (s *storage) ValidateJWTProfileScopes(ctx context.Context, userID string, scopes []string) ([]string, error) {
|
func (s *storage) ValidateJWTProfileScopes(ctx context.Context, userID string, scopes []string) ([]string, error) {
|
||||||
return nil, fmt.Errorf("example does not yet support authentication with JWT") //TODO: implement
|
allowedScopes := make([]string, 0)
|
||||||
|
for _, scope := range scopes {
|
||||||
|
if scope == oidc.ScopeOpenID {
|
||||||
|
allowedScopes = append(allowedScopes, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allowedScopes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//Health implements the op.Storage interface
|
//Health implements the op.Storage interface
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import "golang.org/x/text/language"
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
id string
|
id string
|
||||||
|
@ -14,3 +18,7 @@ type User struct {
|
||||||
phoneVerified bool
|
phoneVerified bool
|
||||||
preferredLanguage language.Tag
|
preferredLanguage language.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
keys map[string]*rsa.PublicKey
|
||||||
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ func newOP(ctx context.Context, storage op.Storage, port string, key [32]byte) (
|
||||||
AuthMethodPost: true,
|
AuthMethodPost: true,
|
||||||
|
|
||||||
//enables additional authentication by using private_key_jwt
|
//enables additional authentication by using private_key_jwt
|
||||||
AuthMethodPrivateKeyJWT: false, //TODO: implement and set to true
|
AuthMethodPrivateKeyJWT: true,
|
||||||
|
|
||||||
//enables refresh_token grant use
|
//enables refresh_token grant use
|
||||||
GrantTypeRefreshToken: true,
|
GrantTypeRefreshToken: true,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue