mirror of
https://github.com/zitadel/zitadel.git
synced 2025-03-01 01:47:23 +00:00
fix: assert roles when using refresh token (#2868)
This commit is contained in:
parent
8b0c3e63d6
commit
57368d151b
@ -25,17 +25,9 @@ func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-sd436", "no user agent id")
|
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-sd436", "no user agent id")
|
||||||
}
|
}
|
||||||
projectID, err := o.query.ProjectIDFromOIDCClientID(ctx, req.ClientID)
|
req.Scopes, err = o.assertProjectRoleScopes(ctx, req.ClientID, req.Scopes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-AEG4d", "Errors.Internal")
|
return nil, errors.ThrowPreconditionFailed(err, "OIDC-Gqrfg", "Errors.Internal")
|
||||||
}
|
|
||||||
project, err := o.query.ProjectByID(ctx, projectID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-w4wIn", "Errors.Internal")
|
|
||||||
}
|
|
||||||
req.Scopes, err = o.assertProjectRoleScopes(project, req.Scopes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-Gqrfg", "Errors.Internal")
|
|
||||||
}
|
}
|
||||||
authRequest := CreateAuthRequestToBusiness(ctx, req, userAgentID, userID)
|
authRequest := CreateAuthRequestToBusiness(ctx, req, userAgentID, userID)
|
||||||
//TODO: ensure splitting of command and query side durring auth request and login refactoring
|
//TODO: ensure splitting of command and query side durring auth request and login refactoring
|
||||||
@ -117,8 +109,15 @@ func (o *OPStorage) CreateAccessAndRefreshTokens(ctx context.Context, req op.Tok
|
|||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
userAgentID, applicationID, userOrgID, authTime, authMethodsReferences := getInfoFromRequest(req)
|
userAgentID, applicationID, userOrgID, authTime, authMethodsReferences := getInfoFromRequest(req)
|
||||||
|
scopes, err := o.assertProjectRoleScopes(ctx, applicationID, req.GetScopes())
|
||||||
|
if err != nil {
|
||||||
|
return "", "", time.Time{}, errors.ThrowPreconditionFailed(err, "OIDC-Df2fq", "Errors.Internal")
|
||||||
|
}
|
||||||
|
if request, ok := req.(op.RefreshTokenRequest); ok {
|
||||||
|
request.SetCurrentScopes(scopes)
|
||||||
|
}
|
||||||
resp, token, err := o.command.AddAccessAndRefreshToken(ctx, userOrgID, userAgentID, applicationID, req.GetSubject(),
|
resp, token, err := o.command.AddAccessAndRefreshToken(ctx, userOrgID, userAgentID, applicationID, req.GetSubject(),
|
||||||
refreshToken, req.GetAudience(), req.GetScopes(), authMethodsReferences, o.defaultAccessTokenLifetime,
|
refreshToken, req.GetAudience(), scopes, authMethodsReferences, o.defaultAccessTokenLifetime,
|
||||||
o.defaultRefreshTokenIdleExpiration, o.defaultRefreshTokenExpiration, authTime) //PLANNED: lifetime from client
|
o.defaultRefreshTokenIdleExpiration, o.defaultRefreshTokenExpiration, authTime) //PLANNED: lifetime from client
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.IsErrorInvalidArgument(err) {
|
if errors.IsErrorInvalidArgument(err) {
|
||||||
@ -209,15 +208,23 @@ func (o *OPStorage) GetKeySet(ctx context.Context) (_ *jose.JSONWebKeySet, err e
|
|||||||
return o.repo.GetKeySet(ctx)
|
return o.repo.GetKeySet(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OPStorage) assertProjectRoleScopes(project *query.Project, scopes []string) ([]string, error) {
|
func (o *OPStorage) assertProjectRoleScopes(ctx context.Context, clientID string, scopes []string) ([]string, error) {
|
||||||
if !project.ProjectRoleAssertion {
|
|
||||||
return scopes, nil
|
|
||||||
}
|
|
||||||
for _, scope := range scopes {
|
for _, scope := range scopes {
|
||||||
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
|
||||||
return scopes, nil
|
return scopes, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
projectID, err := o.query.ProjectIDFromOIDCClientID(ctx, clientID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-AEG4d", "Errors.Internal")
|
||||||
|
}
|
||||||
|
project, err := o.query.ProjectByID(ctx, projectID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowPreconditionFailed(nil, "OIDC-w4wIn", "Errors.Internal")
|
||||||
|
}
|
||||||
|
if !project.ProjectRoleAssertion {
|
||||||
|
return scopes, nil
|
||||||
|
}
|
||||||
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(project.ID)
|
projectIDQuery, err := query.NewProjectRoleProjectIDSearchQuery(project.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.ThrowInternal(err, "OIDC-Cyc78", "Errors.Internal")
|
return nil, errors.ThrowInternal(err, "OIDC-Cyc78", "Errors.Internal")
|
||||||
|
@ -129,10 +129,51 @@ func (o *OPStorage) SetUserinfoFromToken(ctx context.Context, userInfo oidc.User
|
|||||||
return errors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
|
return errors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return o.SetUserinfoFromScopes(ctx, userInfo, token.UserID, token.ApplicationID, token.Scopes)
|
return o.setUserinfo(ctx, userInfo, token.UserID, token.ApplicationID, token.Scopes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OPStorage) SetUserinfoFromScopes(ctx context.Context, userInfo oidc.UserInfoSetter, userID, applicationID string, scopes []string) (err error) {
|
func (o *OPStorage) SetUserinfoFromScopes(ctx context.Context, userInfo oidc.UserInfoSetter, userID, applicationID string, scopes []string) (err error) {
|
||||||
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
|
defer func() { span.EndWithError(err) }()
|
||||||
|
if applicationID != "" {
|
||||||
|
app, err := o.query.AppByOIDCClientID(ctx, applicationID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if app.OIDCConfig.AssertIDTokenRole {
|
||||||
|
scopes, err = o.assertProjectRoleScopes(ctx, applicationID, scopes)
|
||||||
|
if err != nil {
|
||||||
|
return errors.ThrowPreconditionFailed(err, "OIDC-Dfe2s", "Errors.Internal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o.setUserinfo(ctx, userInfo, userID, applicationID, scopes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OPStorage) SetIntrospectionFromToken(ctx context.Context, introspection oidc.IntrospectionResponse, tokenID, subject, clientID string) error {
|
||||||
|
token, err := o.repo.TokenByID(ctx, subject, tokenID)
|
||||||
|
if err != nil {
|
||||||
|
return errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
|
||||||
|
}
|
||||||
|
projectID, err := o.query.ProjectIDFromClientID(ctx, clientID)
|
||||||
|
if err != nil {
|
||||||
|
return errors.ThrowPermissionDenied(nil, "OIDC-Adfg5", "client not found")
|
||||||
|
}
|
||||||
|
for _, aud := range token.Audience {
|
||||||
|
if aud == clientID || aud == projectID {
|
||||||
|
err := o.setUserinfo(ctx, introspection, token.UserID, clientID, token.Scopes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
introspection.SetScopes(token.Scopes)
|
||||||
|
introspection.SetClientID(token.ApplicationID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.ThrowPermissionDenied(nil, "OIDC-sdg3G", "token is not valid for this client")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OPStorage) setUserinfo(ctx context.Context, userInfo oidc.UserInfoSetter, userID, applicationID string, scopes []string) (err error) {
|
||||||
ctx, span := tracing.NewSpan(ctx)
|
ctx, span := tracing.NewSpan(ctx)
|
||||||
defer func() { span.EndWithError(err) }()
|
defer func() { span.EndWithError(err) }()
|
||||||
user, err := o.repo.UserByID(ctx, userID)
|
user, err := o.repo.UserByID(ctx, userID)
|
||||||
@ -216,29 +257,6 @@ func (o *OPStorage) SetUserinfoFromScopes(ctx context.Context, userInfo oidc.Use
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OPStorage) SetIntrospectionFromToken(ctx context.Context, introspection oidc.IntrospectionResponse, tokenID, subject, clientID string) error {
|
|
||||||
token, err := o.repo.TokenByID(ctx, subject, tokenID)
|
|
||||||
if err != nil {
|
|
||||||
return errors.ThrowPermissionDenied(nil, "OIDC-Dsfb2", "token is not valid or has expired")
|
|
||||||
}
|
|
||||||
projectID, err := o.query.ProjectIDFromClientID(ctx, clientID)
|
|
||||||
if err != nil {
|
|
||||||
return errors.ThrowPermissionDenied(nil, "OIDC-Adfg5", "client not found")
|
|
||||||
}
|
|
||||||
for _, aud := range token.Audience {
|
|
||||||
if aud == clientID || aud == projectID {
|
|
||||||
err := o.SetUserinfoFromScopes(ctx, introspection, token.UserID, clientID, token.Scopes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
introspection.SetScopes(token.Scopes)
|
|
||||||
introspection.SetClientID(token.ApplicationID)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors.ThrowPermissionDenied(nil, "OIDC-sdg3G", "token is not valid for this client")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *OPStorage) GetPrivateClaimsFromScopes(ctx context.Context, userID, clientID string, scopes []string) (claims map[string]interface{}, err error) {
|
func (o *OPStorage) GetPrivateClaimsFromScopes(ctx context.Context, userID, clientID string, scopes []string) (claims map[string]interface{}, err error) {
|
||||||
roles := make([]string, 0)
|
roles := make([]string, 0)
|
||||||
for _, scope := range scopes {
|
for _, scope := range scopes {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user