diff --git a/go.mod b/go.mod index bb1487fd36..b91978486e 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/aws/aws-sdk-go v1.35.11 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc github.com/caos/logging v0.0.2 - github.com/caos/oidc v0.12.4 + github.com/caos/oidc v0.12.5 github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect github.com/cockroachdb/cockroach-go/v2 v2.0.8 github.com/envoyproxy/protoc-gen-validate v0.4.1 diff --git a/go.sum b/go.sum index 3156632dcf..5b8985f097 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/caos/oidc v0.12.3 h1:bzUg5BdFwRK+Bi7vPHH0pZ3ni/0vMZTNtayRCFPbD4U= github.com/caos/oidc v0.12.3/go.mod h1:R9UKITZmSo5vNhSLUYcTDH8pAaV2xwPASXg8wpEs2xQ= github.com/caos/oidc v0.12.4 h1:E6E+LcnVQFHzOSN8GnTfJGgXWiDYtdKu/Xm2+YC/xFk= github.com/caos/oidc v0.12.4/go.mod h1:dLvfYUiAt9ORfl77L/KkcWuR/N0ll8Ry1nD2ERsamDY= +github.com/caos/oidc v0.12.5 h1:BN3iu6ZokOIbuoOkLRX/tAZPAfVoTXIkYflKmV156U8= +github.com/caos/oidc v0.12.5/go.mod h1:dLvfYUiAt9ORfl77L/KkcWuR/N0ll8Ry1nD2ERsamDY= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/internal/api/oidc/client_converter.go b/internal/api/oidc/client_converter.go index a79c62a2fc..94eac96f76 100644 --- a/internal/api/oidc/client_converter.go +++ b/internal/api/oidc/client_converter.go @@ -99,6 +99,9 @@ func (c *Client) IsScopeAllowed(scope string) bool { if strings.HasPrefix(scope, authreq_model.OrgDomainPrimaryScope) { return true } + if strings.HasPrefix(scope, authreq_model.ProjectIDScope) { + return true + } for _, allowedScope := range c.allowedScopes { if scope == allowedScope { return true diff --git a/internal/auth/repository/eventsourcing/eventstore/auth_request.go b/internal/auth/repository/eventsourcing/eventstore/auth_request.go index f69e953d36..c849c9234a 100644 --- a/internal/auth/repository/eventsourcing/eventstore/auth_request.go +++ b/internal/auth/repository/eventsourcing/eventstore/auth_request.go @@ -109,6 +109,9 @@ func (repo *AuthRequestRepo) CreateAuthRequest(ctx context.Context, request *mod return nil, err } request.Audience = appIDs + projectIDAud := request.GetScopeProjectIDsForAud() + request.Audience = append(request.Audience, projectIDAud...) + request.AppendAudIfNotExisting(app.ProjectID) if request.LoginHint != "" { err = repo.checkLoginName(ctx, request, request.LoginHint) logging.LogWithFields("EVENT-aG311", "login name", request.LoginHint, "id", request.ID, "applicationID", request.ApplicationID).OnError(err).Debug("login hint invalid") diff --git a/internal/auth_request/model/auth_request.go b/internal/auth_request/model/auth_request.go index d0e0e8a2da..adf36e27bc 100644 --- a/internal/auth_request/model/auth_request.go +++ b/internal/auth_request/model/auth_request.go @@ -137,3 +137,25 @@ func (a *AuthRequest) GetScopeOrgPrimaryDomain() string { } return "" } + +func (a *AuthRequest) GetScopeProjectIDsForAud() []string { + projectIDs := make([]string, 0) + switch request := a.Request.(type) { + case *AuthRequestOIDC: + for _, scope := range request.Scopes { + if strings.HasPrefix(scope, ProjectIDScope) && strings.HasSuffix(scope, AudSuffix) { + projectIDs = append(projectIDs, strings.TrimSuffix(strings.TrimPrefix(scope, ProjectIDScope), AudSuffix)) + } + } + } + return projectIDs +} + +func (a *AuthRequest) AppendAudIfNotExisting(aud string) { + for _, a := range a.Audience { + if a == aud { + return + } + } + a.Audience = append(a.Audience, aud) +} diff --git a/internal/auth_request/model/request.go b/internal/auth_request/model/request.go index e0288ea2a6..72f10ce49f 100644 --- a/internal/auth_request/model/request.go +++ b/internal/auth_request/model/request.go @@ -19,7 +19,9 @@ const ( ) const ( - OrgDomainPrimaryScope = "urn:zitadel:org:domain:primary:" + OrgDomainPrimaryScope = "urn:zitadel:iam:org:domain:primary:" + ProjectIDScope = "urn:zitadel:iam:org:project:id:" + AudSuffix = ":aud" ) type AuthRequestOIDC struct { diff --git a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go index 359c66ace2..11bc5663d9 100644 --- a/internal/authz/repository/eventsourcing/eventstore/token_verifier.go +++ b/internal/authz/repository/eventsourcing/eventstore/token_verifier.go @@ -80,8 +80,12 @@ func (repo *TokenVerifierRepo) VerifyAccessToken(ctx context.Context, tokenStrin return "", "", "", caos_errs.ThrowUnauthenticated(err, "APP-k9KS0", "invalid token") } + projectID, _, err := repo.ProjectIDAndOriginsByClientID(ctx, clientID) + if err != nil { + return "", "", "", caos_errs.ThrowUnauthenticated(err, "APP-5M9so", "invalid token") + } for _, aud := range token.Audience { - if clientID == aud { + if clientID == aud || projectID == aud { return token.UserID, token.UserAgentID, token.PreferredLanguage, nil } } diff --git a/site/docs/documentation/03-openidoauth.en.md b/site/docs/documentation/03-openidoauth.en.md index f37520a7ea..4cd14dff10 100644 --- a/site/docs/documentation/03-openidoauth.en.md +++ b/site/docs/documentation/03-openidoauth.en.md @@ -67,6 +67,7 @@ In addition to the standard compliant scopes we utilize the following scopes. | urn:zitadel:iam:org:project:role:{rolename} | By using this scope a [client](administrate#clients) can request the claim urn:zitadel:iam:roles:rolename} to be asserted when possible. As an alternative approach you can enable all [roles](administrate#Roles) to be asserted from the [project](administrate#projects) a [client](administrate#clients) belongs to. See details [here](administrate#RBAC_Settings) | urn:zitadel:iam:org:project:role:user | | urn:zitadel:iam:org:domain:primary:{domainname} | When requesting this scope **ZITADEL** will enforce that the user is a member of the selected organisation. If the organisation does not exist a failure is displayed | urn:zitadel:iam:org:domain:primary:acme.ch | | urn:zitadel:iam:role:{rolename} | | | +| urn:zitadel:iam:org:project:id:{projectid}:aud | By adding this scope, the requested projectid will be added to the audience of the access and id token | ZITADEL Project: urn:zitadel:iam:org:project:id:69234237810729019:aud | ### Claims