mirror of
				https://github.com/zitadel/zitadel.git
				synced 2025-10-31 09:40:17 +00:00 
			
		
		
		
	fix: assert roles when using refresh token (#2868)
This commit is contained in:
		| @@ -25,17 +25,9 @@ func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest | ||||
| 	if !ok { | ||||
| 		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 { | ||||
| 		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") | ||||
| 	} | ||||
| 	req.Scopes, err = o.assertProjectRoleScopes(project, req.Scopes) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.ThrowPreconditionFailed(nil, "OIDC-Gqrfg", "Errors.Internal") | ||||
| 		return nil, errors.ThrowPreconditionFailed(err, "OIDC-Gqrfg", "Errors.Internal") | ||||
| 	} | ||||
| 	authRequest := CreateAuthRequestToBusiness(ctx, req, userAgentID, userID) | ||||
| 	//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) | ||||
| 	defer func() { span.EndWithError(err) }() | ||||
| 	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(), | ||||
| 		refreshToken, req.GetAudience(), req.GetScopes(), authMethodsReferences, o.defaultAccessTokenLifetime, | ||||
| 		refreshToken, req.GetAudience(), scopes, authMethodsReferences, o.defaultAccessTokenLifetime, | ||||
| 		o.defaultRefreshTokenIdleExpiration, o.defaultRefreshTokenExpiration, authTime) //PLANNED: lifetime from client | ||||
| 	if err != nil { | ||||
| 		if errors.IsErrorInvalidArgument(err) { | ||||
| @@ -209,15 +208,23 @@ func (o *OPStorage) GetKeySet(ctx context.Context) (_ *jose.JSONWebKeySet, err e | ||||
| 	return o.repo.GetKeySet(ctx) | ||||
| } | ||||
|  | ||||
| func (o *OPStorage) assertProjectRoleScopes(project *query.Project, scopes []string) ([]string, error) { | ||||
| 	if !project.ProjectRoleAssertion { | ||||
| 		return scopes, nil | ||||
| 	} | ||||
| func (o *OPStorage) assertProjectRoleScopes(ctx context.Context, clientID string, scopes []string) ([]string, error) { | ||||
| 	for _, scope := range scopes { | ||||
| 		if strings.HasPrefix(scope, ScopeProjectRolePrefix) { | ||||
| 			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) | ||||
| 	if err != nil { | ||||
| 		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 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) { | ||||
| 	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) | ||||
| 	defer func() { span.EndWithError(err) }() | ||||
| 	user, err := o.repo.UserByID(ctx, userID) | ||||
| @@ -216,29 +257,6 @@ func (o *OPStorage) SetUserinfoFromScopes(ctx context.Context, userInfo oidc.Use | ||||
| 	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) { | ||||
| 	roles := make([]string, 0) | ||||
| 	for _, scope := range scopes { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Livio Amstutz
					Livio Amstutz