mirror of
https://github.com/zitadel/zitadel.git
synced 2025-11-02 03:38:46 +00:00
# Which Problems Are Solved
The /userinfo endpoint only returns roles for the current project, even
if the access token includes multiple project aud scopes.
This prevents clients from retrieving all user roles across multiple
projects, making multi-project access control ineffective.
# How the Problems Are Solved
Modified the /userinfo handler logic to resolve roles across all valid
project audience scopes provided in the token, not just the current
project.
Ensured that if **urn:zitadel:iam:org:projects:roles is in the scopes**,
roles from all declared project audiences are collected and included in
the response in **urn:zitadel:iam:org:projects:roles claim**.
# Additional Changes
# Additional Context
This change enables service-to-service authorization workflows and SPA
role resolution across multiple project contexts with a single token.
- Closes #9831
---------
Co-authored-by: Masum Patel <patelmasum98@gmail.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
(cherry picked from commit 295584648d)
82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
package domain
|
|
|
|
const (
|
|
OrgDomainPrimaryScope = "urn:zitadel:iam:org:domain:primary:"
|
|
OrgIDScope = "urn:zitadel:iam:org:id:"
|
|
OrgRoleIDScope = "urn:zitadel:iam:org:roles:id:"
|
|
OrgDomainPrimaryClaim = "urn:zitadel:iam:org:domain:primary"
|
|
OrgIDClaim = "urn:zitadel:iam:org:id"
|
|
ProjectIDScope = "urn:zitadel:iam:org:project:id:"
|
|
ProjectsIDScope = "urn:zitadel:iam:org:projects:roles"
|
|
ProjectIDScopeZITADEL = "zitadel"
|
|
AudSuffix = ":aud"
|
|
ProjectScopeZITADEL = ProjectIDScope + ProjectIDScopeZITADEL + AudSuffix
|
|
SelectIDPScope = "urn:zitadel:iam:org:idp:id:"
|
|
)
|
|
|
|
// TODO: Change AuthRequest to interface and let oidcauthreqesut implement it
|
|
type Request interface {
|
|
Type() AuthRequestType
|
|
IsValid() bool
|
|
}
|
|
|
|
type AuthRequestType int32
|
|
|
|
const (
|
|
AuthRequestTypeOIDC AuthRequestType = iota
|
|
AuthRequestTypeSAML
|
|
AuthRequestTypeDevice
|
|
)
|
|
|
|
type AuthRequestOIDC struct {
|
|
Scopes []string
|
|
ResponseType OIDCResponseType
|
|
ResponseMode OIDCResponseMode
|
|
Nonce string
|
|
CodeChallenge *OIDCCodeChallenge
|
|
}
|
|
|
|
func (a *AuthRequestOIDC) Type() AuthRequestType {
|
|
return AuthRequestTypeOIDC
|
|
}
|
|
|
|
func (a *AuthRequestOIDC) IsValid() bool {
|
|
return len(a.Scopes) > 0 &&
|
|
a.CodeChallenge == nil || a.CodeChallenge != nil && a.CodeChallenge.IsValid()
|
|
}
|
|
|
|
type AuthRequestSAML struct {
|
|
ID string
|
|
BindingType string
|
|
Code string
|
|
Issuer string
|
|
IssuerName string
|
|
Destination string
|
|
}
|
|
|
|
func (a *AuthRequestSAML) Type() AuthRequestType {
|
|
return AuthRequestTypeSAML
|
|
}
|
|
|
|
func (a *AuthRequestSAML) IsValid() bool {
|
|
return true
|
|
}
|
|
|
|
type AuthRequestDevice struct {
|
|
ClientID string
|
|
DeviceCode string
|
|
UserCode string
|
|
Scopes []string
|
|
Audience []string
|
|
AppName string
|
|
ProjectName string
|
|
}
|
|
|
|
func (*AuthRequestDevice) Type() AuthRequestType {
|
|
return AuthRequestTypeDevice
|
|
}
|
|
|
|
func (a *AuthRequestDevice) IsValid() bool {
|
|
return a.DeviceCode != "" && a.UserCode != ""
|
|
}
|