Skip to content

Commit

Permalink
Merge pull request #1959 from openziti/tweak.oidc.token.exchange
Browse files Browse the repository at this point in the history
tweaks behavior of token exchange
  • Loading branch information
andrewpmartinez authored Apr 18, 2024
2 parents df1e3d1 + 739bcf6 commit 4214e22
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 24 deletions.
12 changes: 1 addition & 11 deletions controller/oidc_auth/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import (
"github.com/zitadel/oidc/v2/pkg/oidc"
)

const (
ScopeTokenId = "tid-"
ScopeApiSessionId = "asid-"
)

// AuthRequest represents an OIDC authentication request and implements op.AuthRequest
type AuthRequest struct {
oidc.AuthRequest
Expand Down Expand Up @@ -134,13 +129,8 @@ func (a *AuthRequest) GetResponseMode() oidc.ResponseMode {
}

// GetScopes returns the current scopes and implements op.AuthRequest
// Scopes are also used to transport custom claims into access tokens.
// The zitadel oidc framework does not provide a method for accessing the request object during JWT signing time,
// and any claims supplied are overwritten.
func (a *AuthRequest) GetScopes() []string {
result := append(a.Scopes, ScopeApiSessionId+a.ApiSessionId)
result = append(result, ScopeTokenId+a.Id)
return result
return a.Scopes
}

// GetState returns the rp provided state and implements op.AuthRequest
Expand Down
58 changes: 45 additions & 13 deletions controller/oidc_auth/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,13 +444,19 @@ func (s *HybridStorage) createAccessToken(request op.TokenRequest) (string, *com
val, ok = claims[common.CustomClaimsConfigTypes]

if ok {
configTypes = val.([]string)
valArr := val.([]any)
for _, i := range valArr {
configTypes = append(configTypes, i.(string))
}
}

val, ok = claims[common.CustomClaimsCertFingerprints]

if ok {
certsFingerprints = val.([]string)
valArr := val.([]any)
for _, i := range valArr {
certsFingerprints = append(certsFingerprints, i.(string))
}
}

val, ok = claims[common.CustomClaimRemoteAddress]
Expand Down Expand Up @@ -780,7 +786,7 @@ func (s *HybridStorage) GetKeyByIDAndClientID(_ context.Context, keyID, _ string
func (s *HybridStorage) ValidateJWTProfileScopes(_ context.Context, _ string, scopes []string) ([]string, error) {
allowedScopes := make([]string, 0)
for _, scope := range scopes {
if scope == oidc.ScopeOpenID {
if scope == oidc.ScopeOpenID || scope == oidc.ScopeOfflineAccess {
allowedScopes = append(allowedScopes, scope)
}
}
Expand Down Expand Up @@ -865,33 +871,59 @@ func (s *HybridStorage) setInfo(userInfo *oidc.UserInfo, identityId string, scop
return nil
}

func tokenTypeToName(oidcType oidc.TokenType) string {
switch oidcType {
case oidc.AccessTokenType:
return "access_token"
case oidc.IDTokenType:
return "id_token"
case oidc.RefreshTokenType:
return "refresh_token"
}

return "unknown_token"

}

// ValidateTokenExchangeRequest implements the op.TokenExchangeStorage interface
func (s *HybridStorage) ValidateTokenExchangeRequest(_ context.Context, request op.TokenExchangeRequest) error {
if request.GetRequestedTokenType() == "" {
request.SetRequestedTokenType(oidc.RefreshTokenType)
}

// Just an example, some use cases might need this use case
if request.GetExchangeSubjectTokenType() == oidc.IDTokenType && request.GetRequestedTokenType() == oidc.RefreshTokenType {
return errors.New("exchanging id_token to refresh_token is not supported")
requestedType := request.GetExchangeSubjectTokenType()
proofType := request.GetExchangeSubjectTokenType()

switch proofType {
case oidc.AccessTokenType:
if requestedType != oidc.AccessTokenType {
return fmt.Errorf("exchanging %s for %s is not supported", tokenTypeToName(proofType), tokenTypeToName(requestedType))
}
case oidc.IDTokenType:
return fmt.Errorf("exchanging %s for any token type is not supported", tokenTypeToName(proofType))
case oidc.RefreshTokenType:
if requestedType != oidc.AccessTokenType && requestedType != oidc.RefreshTokenType {
return fmt.Errorf("exchanging %s for %s is not supported", tokenTypeToName(proofType), tokenTypeToName(requestedType))
}
default:
return fmt.Errorf("exchange subject type (%s) is not supported", proofType)
}

allowedScopes := make([]string, 0)
allowedScopes := []string{oidc.ScopeOpenID}

for _, scope := range request.GetScopes() {
if scope == oidc.ScopeAddress {
continue
if scope == oidc.ScopeOfflineAccess {
allowedScopes = append(allowedScopes, scope)
}

allowedScopes = append(allowedScopes, scope)
}

request.SetCurrentScopes(allowedScopes)

return nil
}

func (s *HybridStorage) CreateTokenExchangeRequest(_ context.Context, _ op.TokenExchangeRequest) error {
return fmt.Errorf("unsupported")
func (s *HybridStorage) CreateTokenExchangeRequest(_ context.Context, req op.TokenExchangeRequest) error {
return nil
}

// GetPrivateClaimsFromTokenExchangeRequest implements the op.TokenExchangeStorage interface
Expand Down

0 comments on commit 4214e22

Please sign in to comment.