feat: add CanSetUserinfoFromRequest interface (#347)

This commit is contained in:
David Sharnoff 2023-03-24 09:55:41 -07:00 committed by GitHub
parent edc9a1f60d
commit c9555c7f1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 5 deletions

View file

@ -438,10 +438,17 @@ func (s *Storage) AuthorizeClientIDSecret(ctx context.Context, clientID, clientS
return nil return nil
} }
// SetUserinfoFromScopes implements the op.Storage interface // SetUserinfoFromScopes implements the op.Storage interface.
// it will be called for the creation of an id_token, so we'll just pass it to the private function without any further check // Provide an empty implementation and use SetUserinfoFromRequest instead.
func (s *Storage) SetUserinfoFromScopes(ctx context.Context, userinfo *oidc.UserInfo, userID, clientID string, scopes []string) error { func (s *Storage) SetUserinfoFromScopes(ctx context.Context, userinfo *oidc.UserInfo, userID, clientID string, scopes []string) error {
return s.setUserinfo(ctx, userinfo, userID, clientID, scopes) return nil
}
// SetUserinfoFromRequests implements the op.CanSetUserinfoFromRequest interface. In the
// next major release, it will be required for op.Storage.
// It will be called for the creation of an id_token, so we'll just pass it to the private function without any further check
func (s *Storage) SetUserinfoFromRequest(ctx context.Context, userinfo *oidc.UserInfo, token op.IDTokenRequest, scopes []string) error {
return s.setUserinfo(ctx, userinfo, token.GetSubject(), token.GetClientID(), scopes)
} }
// SetUserinfoFromToken implements the op.Storage interface // SetUserinfoFromToken implements the op.Storage interface

View file

@ -196,8 +196,8 @@ func (s *multiStorage) AuthorizeClientIDSecret(ctx context.Context, clientID, cl
return storage.AuthorizeClientIDSecret(ctx, clientID, clientSecret) return storage.AuthorizeClientIDSecret(ctx, clientID, clientSecret)
} }
// SetUserinfoFromScopes implements the op.Storage interface // SetUserinfoFromScopes implements the op.Storage interface.
// it will be called for the creation of an id_token, so we'll just pass it to the private function without any further check // Provide an empty implementation and use SetUserinfoFromRequest instead.
func (s *multiStorage) SetUserinfoFromScopes(ctx context.Context, userinfo *oidc.UserInfo, userID, clientID string, scopes []string) error { func (s *multiStorage) SetUserinfoFromScopes(ctx context.Context, userinfo *oidc.UserInfo, userID, clientID string, scopes []string) error {
storage, err := s.storageFromContext(ctx) storage, err := s.storageFromContext(ctx)
if err != nil { if err != nil {
@ -206,6 +206,17 @@ func (s *multiStorage) SetUserinfoFromScopes(ctx context.Context, userinfo *oidc
return storage.SetUserinfoFromScopes(ctx, userinfo, userID, clientID, scopes) return storage.SetUserinfoFromScopes(ctx, userinfo, userID, clientID, scopes)
} }
// SetUserinfoFromRequests implements the op.CanSetUserinfoFromRequest interface. In the
// next major release, it will be required for op.Storage.
// It will be called for the creation of an id_token, so we'll just pass it to the private function without any further check
func (s *multiStorage) SetUserinfoFromRequest(ctx context.Context, userinfo *oidc.UserInfo, token op.IDTokenRequest, scopes []string) error {
storage, err := s.storageFromContext(ctx)
if err != nil {
return err
}
return storage.SetUserinfoFromRequest(ctx, userinfo, token, scopes)
}
// SetUserinfoFromToken implements the op.Storage interface // SetUserinfoFromToken implements the op.Storage interface
// it will be called for the userinfo endpoint, so we read the token and pass the information from that to the private function // it will be called for the userinfo endpoint, so we read the token and pass the information from that to the private function
func (s *multiStorage) SetUserinfoFromToken(ctx context.Context, userinfo *oidc.UserInfo, tokenID, subject, origin string) error { func (s *multiStorage) SetUserinfoFromToken(ctx context.Context, userinfo *oidc.UserInfo, tokenID, subject, origin string) error {

View file

@ -113,6 +113,8 @@ type OPStorage interface {
// handle the current request. // handle the current request.
GetClientByClientID(ctx context.Context, clientID string) (Client, error) GetClientByClientID(ctx context.Context, clientID string) (Client, error)
AuthorizeClientIDSecret(ctx context.Context, clientID, clientSecret string) error AuthorizeClientIDSecret(ctx context.Context, clientID, clientSecret string) error
// SetUserinfoFromScopes is deprecated and should have an empty implementation for now.
// Implement SetUserinfoFromRequest instead.
SetUserinfoFromScopes(ctx context.Context, userinfo *oidc.UserInfo, userID, clientID string, scopes []string) error SetUserinfoFromScopes(ctx context.Context, userinfo *oidc.UserInfo, userID, clientID string, scopes []string) error
SetUserinfoFromToken(ctx context.Context, userinfo *oidc.UserInfo, tokenID, subject, origin string) error SetUserinfoFromToken(ctx context.Context, userinfo *oidc.UserInfo, tokenID, subject, origin string) error
SetIntrospectionFromToken(ctx context.Context, userinfo *oidc.IntrospectionResponse, tokenID, subject, clientID string) error SetIntrospectionFromToken(ctx context.Context, userinfo *oidc.IntrospectionResponse, tokenID, subject, clientID string) error
@ -127,6 +129,13 @@ type JWTProfileTokenStorage interface {
JWTProfileTokenType(ctx context.Context, request TokenRequest) (AccessTokenType, error) JWTProfileTokenType(ctx context.Context, request TokenRequest) (AccessTokenType, error)
} }
// CanSetUserinfoFromRequest is an optional additional interface that may be implemented by
// implementors of Storage. It allows additional data to be set in id_tokens based on the
// request.
type CanSetUserinfoFromRequest interface {
SetUserinfoFromRequest(ctx context.Context, userinfo *oidc.UserInfo, request IDTokenRequest, scopes []string) error
}
// Storage is a required parameter for NewOpenIDProvider(). In addition to the // Storage is a required parameter for NewOpenIDProvider(). In addition to the
// embedded interfaces below, if the passed Storage implements ClientCredentialsStorage // embedded interfaces below, if the passed Storage implements ClientCredentialsStorage
// then the grant type "client_credentials" will be supported. In that case, the access // then the grant type "client_credentials" will be supported. In that case, the access

View file

@ -190,6 +190,12 @@ func CreateIDToken(ctx context.Context, issuer string, request IDTokenRequest, v
if err != nil { if err != nil {
return "", err return "", err
} }
if fromRequest, ok := storage.(CanSetUserinfoFromRequest); ok {
err := fromRequest.SetUserinfoFromRequest(ctx, userInfo, request, scopes)
if err != nil {
return "", err
}
}
claims.SetUserInfo(userInfo) claims.SetUserInfo(userInfo)
} }
if code != "" { if code != "" {