VYPR
Moderate severityNVD Advisory· Published Mar 20, 2026· Updated Mar 20, 2026

ZITADEL is missing enforcement of organization scopes

CVE-2026-33132

Description

ZITADEL is an open source identity management platform. Versions prior to 3.4.9 and 4.0.0 through 4.12.2 allowed users to bypass organization enforcement during authentication. Zitadel allows applications to enforce an organzation context during authentication using scopes (urn:zitadel:iam:org:id:{id} and urn:zitadel:iam:org:domain:primary:{domainname}). If enforced, a user needs to be part of the required organization to sign in. While this was properly enforced for OAuth2/OIDC authorization requests in login V1, corresponding controls were missing for device authorization requests and all login V2 and OIDC API V2 endpoints. This allowed users to bypass the restriction and sign in with users from other organizations. Note that this enforcement allows for an additional check during authentication and applications relying on authorizations / roles assignments are not affected by this bypass. This issue has been patched in versions 3.4.9 and 4.12.3.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/zitadel/zitadelGo
>= 4.0.0-rc.1, < 4.12.34.12.3
github.com/zitadel/zitadelGo
>= 3.0.0-rc.1, < 3.4.93.4.9
github.com/zitadel/zitadelGo
< 1.80.0-v2.20.0.20260317120401-d90285929ca01.80.0-v2.20.0.20260317120401-d90285929ca0

Affected products

1

Patches

1
d90285929ca0

fix: enforce organization scopes

https://github.com/zitadel/zitadelWim Van LaerMar 17, 2026via ghsa
21 files changed · +730 118
  • apps/login/src/app/(login)/accounts/page.tsx+20 7 modified
    @@ -17,13 +17,27 @@ export async function generateMetadata(): Promise<Metadata> {
       return { title: t("title") };
     }
     
    -async function loadSessions({ serviceConfig }: { serviceConfig: ServiceConfig }) {
    +async function loadSessions({
    +  serviceConfig,
    +  organization,
    +}: {
    +  serviceConfig: ServiceConfig;
    +  organization?: string;
    +}) {
       const cookieIds = await getAllSessionCookieIds();
     
       if (cookieIds && cookieIds.length) {
    -    const response = await listSessions({ serviceConfig, ids: cookieIds.filter((id) => !!id) as string[],
    +    const response = await listSessions({
    +      serviceConfig,
    +      ids: cookieIds.filter((id) => !!id) as string[],
         });
    -    return response?.sessions ?? [];
    +
    +    let sessions = response?.sessions ?? [];
    +    if (organization) {
    +      sessions = sessions.filter((s) => s.factors?.user?.organizationId === organization);
    +    }
    +
    +    return sessions;
       } else {
         console.info("No session cookie found.");
         return [];
    @@ -41,16 +55,15 @@ export default async function Page(props: { searchParams: Promise<Record<string
     
       let defaultOrganization;
       if (!organization) {
    -    const org: Organization | null = await getDefaultOrg({ serviceConfig, });
    +    const org: Organization | null = await getDefaultOrg({ serviceConfig });
         if (org) {
           defaultOrganization = org.id;
         }
       }
     
    -  let sessions = await loadSessions({ serviceConfig });
    +  let sessions = await loadSessions({ serviceConfig, organization });
     
    -  const branding = await getBrandingSettings({ serviceConfig, organization: organization ?? defaultOrganization,
    -  });
    +  const branding = await getBrandingSettings({ serviceConfig, organization: organization ?? defaultOrganization });
     
       const params = new URLSearchParams();
     
    
  • apps/login/src/lib/server/flow-initiation.ts+2 2 modified
    @@ -258,7 +258,7 @@ export async function handleOIDCFlowInitiation(params: FlowInitiationParams): Pr
         } else if (authRequest.prompt.includes(Prompt.NONE)) {
           const securitySettings = await getSecuritySettings({ serviceConfig });
     
    -      const selectedSession = await findValidSession({ serviceConfig, sessions, authRequest });
    +      const selectedSession = await findValidSession({ serviceConfig, sessions, authRequest, organization });
     
           const noSessionResponse = NextResponse.json({ error: "No active session found" }, { status: 400 });
           setCSPHeaders(noSessionResponse, serviceConfig, securitySettings);
    @@ -294,7 +294,7 @@ export async function handleOIDCFlowInitiation(params: FlowInitiationParams): Pr
     
           return callbackResponse;
         } else {
    -      let selectedSession = await findValidSession({ serviceConfig, sessions, authRequest });
    +      let selectedSession = await findValidSession({ serviceConfig, sessions, authRequest, organization });
     
           if (!selectedSession || !selectedSession.id) {
             return gotoAccounts({
    
  • apps/login/src/lib/session.ts+7 1 modified
    @@ -142,13 +142,15 @@ export async function findValidSession({
       sessions,
       authRequest,
       samlRequest,
    +  organization,
     }: {
       serviceConfig: ServiceConfig;
       sessions: Session[];
       authRequest?: AuthRequest;
       samlRequest?: SAMLRequest;
    +  organization?: string;
     }): Promise<Session | undefined> {
    -  const sessionsWithHint = sessions.filter((s) => {
    +  let sessionsWithHint = sessions.filter((s) => {
         if (authRequest && authRequest.hintUserId) {
           return s.factors?.user?.id === authRequest.hintUserId;
         }
    @@ -163,6 +165,10 @@ export async function findValidSession({
         return true;
       });
     
    +  if (organization) {
    +    sessionsWithHint = sessionsWithHint.filter((s) => s.factors?.user?.organizationId === organization);
    +  }
    +
       if (sessionsWithHint.length === 0) {
         return undefined;
       }
    
  • internal/api/grpc/oidc/v2/integration_test/oidc_test.go+106 6 modified
    @@ -15,6 +15,7 @@ import (
     	"github.com/zitadel/oidc/v3/pkg/oidc"
     	"google.golang.org/protobuf/types/known/timestamppb"
     
    +	"github.com/zitadel/zitadel/internal/domain"
     	"github.com/zitadel/zitadel/internal/integration"
     	"github.com/zitadel/zitadel/pkg/grpc/app"
     	filter "github.com/zitadel/zitadel/pkg/grpc/filter/v2beta"
    @@ -163,6 +164,25 @@ func TestServer_CreateCallback(t *testing.T) {
     			},
     			wantErr: true,
     		},
    +		{
    +			name: "invalid organization",
    +			ctx:  CTXLoginClient,
    +			req: &oidc_pb.CreateCallbackRequest{
    +				AuthRequestId: func() string {
    +					org := Instance.CreateOrganization(IAMCTX, integration.OrganizationName(), integration.Email())
    +					_, authRequestID, err := Instance.CreateOIDCAuthRequest(CTXLoginClient, client.GetClientId(), Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID, domain.OrgIDScope+org.OrganizationId)
    +					require.NoError(t, err)
    +					return authRequestID
    +				}(),
    +				CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
    +					Session: &oidc_pb.Session{
    +						SessionId:    sessionResp.GetSessionId(),
    +						SessionToken: sessionResp.GetSessionToken(),
    +					},
    +				},
    +			},
    +			wantErr: true,
    +		},
     		{
     			name: "fail callback",
     			ctx:  CTXLoginClient,
    @@ -356,6 +376,31 @@ func TestServer_CreateCallback(t *testing.T) {
     			},
     			wantErr: false,
     		},
    +		{
    +			name: "callback with required organization",
    +			ctx:  CTXLoginClient,
    +			req: &oidc_pb.CreateCallbackRequest{
    +				AuthRequestId: func() string {
    +					_, authRequestID, err := Instance.CreateOIDCAuthRequest(CTXLoginClient, client.GetClientId(), Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID, domain.OrgIDScope+Instance.DefaultOrg.Id)
    +					require.NoError(t, err)
    +					return authRequestID
    +				}(),
    +				CallbackKind: &oidc_pb.CreateCallbackRequest_Session{
    +					Session: &oidc_pb.Session{
    +						SessionId:    sessionResp.GetSessionId(),
    +						SessionToken: sessionResp.GetSessionToken(),
    +					},
    +				},
    +			},
    +			want: &oidc_pb.CreateCallbackResponse{
    +				CallbackUrl: `oidcintegrationtest:\/\/callback\?code=(.*)&state=state`,
    +				Details: &object.Details{
    +					ChangeDate:    timestamppb.Now(),
    +					ResourceOwner: Instance.ID(),
    +				},
    +			},
    +			wantErr: false,
    +		},
     	}
     	for _, tt := range tests {
     		t.Run(tt.name, func(t *testing.T) {
    @@ -749,7 +794,7 @@ func TestServer_AuthorizeOrDenyDeviceAuthorization(t *testing.T) {
     			ctx:  CTXLoginClient,
     			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
     				DeviceAuthorizationId: func() string {
    -					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), "openid")
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID)
     					require.NoError(t, err)
     					var id string
     					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    @@ -776,7 +821,7 @@ func TestServer_AuthorizeOrDenyDeviceAuthorization(t *testing.T) {
     			ctx:  CTXLoginClient,
     			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
     				DeviceAuthorizationId: func() string {
    -					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), "openid")
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID)
     					require.NoError(t, err)
     					var id string
     					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    @@ -798,12 +843,40 @@ func TestServer_AuthorizeOrDenyDeviceAuthorization(t *testing.T) {
     			},
     			wantErr: true,
     		},
    +		{
    +			name: "invalid organization",
    +			ctx:  CTXLoginClient,
    +			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
    +				DeviceAuthorizationId: func() string {
    +					org := Instance.CreateOrganization(IAMCTX, integration.OrganizationName(), integration.Email())
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID, domain.OrgIDScope+org.OrganizationId)
    +					require.NoError(t, err)
    +					var id string
    +					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    +					require.EventuallyWithT(t, func(collectT *assert.CollectT) {
    +						resp, err := Instance.Client.OIDCv2.GetDeviceAuthorizationRequest(CTXLoginClient, &oidc_pb.GetDeviceAuthorizationRequestRequest{
    +							UserCode: req.UserCode,
    +						})
    +						assert.NoError(collectT, err)
    +						id = resp.GetDeviceAuthorizationRequest().GetId()
    +					}, retryDuration, tick)
    +					return id
    +				}(),
    +				Decision: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest_Session{
    +					Session: &oidc_pb.Session{
    +						SessionId:    sessionResp.GetSessionId(),
    +						SessionToken: sessionResp.GetSessionToken(),
    +					},
    +				},
    +			},
    +			wantErr: true,
    +		},
     		{
     			name: "deny device authorization",
     			ctx:  CTXLoginClient,
     			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
     				DeviceAuthorizationId: func() string {
    -					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), "openid")
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID)
     					require.NoError(t, err)
     					var id string
     					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    @@ -826,7 +899,7 @@ func TestServer_AuthorizeOrDenyDeviceAuthorization(t *testing.T) {
     			ctx:  CTX,
     			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
     				DeviceAuthorizationId: func() string {
    -					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), "openid")
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID)
     					require.NoError(t, err)
     					var id string
     					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    @@ -849,7 +922,7 @@ func TestServer_AuthorizeOrDenyDeviceAuthorization(t *testing.T) {
     			ctx:  CTX,
     			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
     				DeviceAuthorizationId: func() string {
    -					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), "openid")
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID)
     					require.NoError(t, err)
     					var id string
     					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    @@ -876,7 +949,34 @@ func TestServer_AuthorizeOrDenyDeviceAuthorization(t *testing.T) {
     			ctx:  CTXLoginClient,
     			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
     				DeviceAuthorizationId: func() string {
    -					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), "openid")
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID)
    +					require.NoError(t, err)
    +					var id string
    +					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    +					require.EventuallyWithT(t, func(collectT *assert.CollectT) {
    +						resp, err := Instance.Client.OIDCv2.GetDeviceAuthorizationRequest(CTXLoginClient, &oidc_pb.GetDeviceAuthorizationRequestRequest{
    +							UserCode: req.UserCode,
    +						})
    +						assert.NoError(collectT, err)
    +						id = resp.GetDeviceAuthorizationRequest().GetId()
    +					}, retryDuration, tick)
    +					return id
    +				}(),
    +				Decision: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest_Session{
    +					Session: &oidc_pb.Session{
    +						SessionId:    sessionResp.GetSessionId(),
    +						SessionToken: sessionResp.GetSessionToken(),
    +					},
    +				},
    +			},
    +			wantErr: false,
    +		},
    +		{
    +			name: "authorize, with organization scope",
    +			ctx:  CTXLoginClient,
    +			req: &oidc_pb.AuthorizeOrDenyDeviceAuthorizationRequest{
    +				DeviceAuthorizationId: func() string {
    +					req, err := Instance.CreateDeviceAuthorizationRequest(CTXLoginClient, client.GetClientId(), oidc.ScopeOpenID, domain.OrgIDScope+Instance.DefaultOrg.GetId())
     					require.NoError(t, err)
     					var id string
     					retryDuration, tick := integration.WaitForAndTickWithMaxDuration(CTXLoginClient, time.Minute)
    
  • internal/api/oidc/auth_request_converter.go+7 7 modified
    @@ -119,13 +119,13 @@ func CreateAuthRequestToBusiness(ctx context.Context, authReq *oidc.AuthRequest,
     		UserID:              userID,
     		InstanceID:          authz.GetInstance(ctx).InstanceID(),
     		Audience:            audience,
    -		Request: &domain.AuthRequestOIDC{
    -			Scopes:        authReq.Scopes,
    -			ResponseType:  ResponseTypeToBusiness(authReq.ResponseType),
    -			ResponseMode:  ResponseModeToBusiness(authReq.ResponseMode),
    -			Nonce:         authReq.Nonce,
    -			CodeChallenge: CodeChallengeToBusiness(authReq.CodeChallenge, authReq.CodeChallengeMethod),
    -		},
    +		Request: domain.NewAuthRequestOIDC(
    +			authReq.Scopes,
    +			ResponseTypeToBusiness(authReq.ResponseType),
    +			ResponseModeToBusiness(authReq.ResponseMode),
    +			authReq.Nonce,
    +			CodeChallengeToBusiness(authReq.CodeChallenge, authReq.CodeChallengeMethod),
    +		),
     	}
     }
     
    
  • internal/api/oidc/auth_request.go+48 7 modified
    @@ -80,25 +80,31 @@ func (o *OPStorage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest
     	}
     }
     
    -func (o *OPStorage) createAuthRequestScopeAndAudience(ctx context.Context, clientID string, reqScope []string) (scope, audience []string, err error) {
    +func (o *OPStorage) createAuthRequestScopeAndAudience(ctx context.Context, clientID string, reqScope []string) (scope, audience []string, orgID string, err error) {
     	project, err := o.query.ProjectByClientID(ctx, clientID)
     	if err != nil {
    -		return nil, nil, err
    +		return nil, nil, "", err
     	}
    +
    +	orgID, err = o.assertOrgScope(ctx, reqScope)
    +	if err != nil {
    +		return nil, nil, "", err
    +	}
    +
     	scope, err = o.assertProjectRoleScopesByProject(ctx, project, reqScope)
     	if err != nil {
    -		return nil, nil, err
    +		return nil, nil, "", err
     	}
     	audience, err = o.audienceFromProjectID(ctx, project.ID)
     	audience = domain.AddAudScopeToAudience(ctx, audience, scope)
     	if err != nil {
    -		return nil, nil, err
    +		return nil, nil, "", err
     	}
    -	return scope, audience, nil
    +	return scope, audience, orgID, nil
     }
     
     func (o *OPStorage) createAuthRequestLoginClient(ctx context.Context, req *oidc.AuthRequest, hintUserID, loginClient string) (op.AuthRequest, error) {
    -	scope, audience, err := o.createAuthRequestScopeAndAudience(ctx, req.ClientID, req.Scopes)
    +	scope, audience, orgID, err := o.createAuthRequestScopeAndAudience(ctx, req.ClientID, req.Scopes)
     	if err != nil {
     		return nil, err
     	}
    @@ -118,6 +124,7 @@ func (o *OPStorage) createAuthRequestLoginClient(ctx context.Context, req *oidc.
     		UILocales:        UILocalesToBusiness(req.UILocales),
     		MaxAge:           MaxAgeToBusiness(req.MaxAge),
     		Issuer:           o.contextToIssuer(ctx),
    +		OrganizationID:   orgID,
     	}
     	if req.LoginHint != "" {
     		authRequest.LoginHint = &req.LoginHint
    @@ -138,7 +145,8 @@ func (o *OPStorage) createAuthRequest(ctx context.Context, req *oidc.AuthRequest
     	if !ok {
     		return nil, zerrors.ThrowPreconditionFailed(nil, "OIDC-sd436", "no user agent id")
     	}
    -	scope, audience, err := o.createAuthRequestScopeAndAudience(ctx, req.ClientID, req.Scopes)
    +	// we do not need to handle the orgID for the v1 login, since it handles it already
    +	scope, audience, _, err := o.createAuthRequestScopeAndAudience(ctx, req.ClientID, req.Scopes)
     	if err != nil {
     		return nil, err
     	}
    @@ -530,6 +538,39 @@ func (o *OPStorage) GetRefreshTokenInfo(ctx context.Context, clientID string, to
     	return refreshToken.UserID, refreshToken.ID, nil
     }
     
    +// assertOrgScope checks the scopes for organization scopes and returns the orgID if exactly one org scope is found.
    +// If multiple org scopes are found or if the org scope is invalid, an error is returned.
    +// For backwards compatibility, we support both orgID and orgDomain scopes, but they need to be consistent,
    +// meaning that if both are provided, they need to belong to the same organization.
    +func (o *OPStorage) assertOrgScope(ctx context.Context, scopes []string) (string, error) {
    +	var id string
    +	for _, scope := range scopes {
    +		if orgID, ok := strings.CutPrefix(scope, domain.OrgIDScope); ok {
    +			org, err := o.query.OrgByID(ctx, orgID)
    +			if err != nil {
    +				return "", err
    +			}
    +			if id != "" && id != org.ID {
    +				return "", oidc.ErrInvalidScope().WithDescription("Only one organization scope may be provided")
    +			}
    +			id = org.ID
    +			continue
    +		}
    +
    +		if orgDomain, ok := strings.CutPrefix(scope, domain.OrgDomainPrimaryScope); ok {
    +			org, err := o.query.OrgByPrimaryDomain(ctx, orgDomain)
    +			if err != nil {
    +				return "", err
    +			}
    +			if id != "" && id != org.ID {
    +				return "", oidc.ErrInvalidScope().WithDescription("Only one organization scope may be provided")
    +			}
    +			id = org.ID
    +		}
    +	}
    +	return id, nil
    +}
    +
     func (o *OPStorage) assertProjectRoleScopesByProject(ctx context.Context, project *query.Project, scopes []string) ([]string, error) {
     	for _, scope := range scopes {
     		if strings.HasPrefix(scope, ScopeProjectRolePrefix) {
    
  • internal/api/oidc/device_auth.go+2 2 modified
    @@ -76,11 +76,11 @@ func (o *OPStorage) StoreDeviceAuthorization(ctx context.Context, clientID, devi
     		logger.OnError(err).Error(logMsg)
     		span.EndWithError(err)
     	}()
    -	scope, audience, err := o.createAuthRequestScopeAndAudience(ctx, clientID, scope)
    +	scope, audience, orgID, err := o.createAuthRequestScopeAndAudience(ctx, clientID, scope)
     	if err != nil {
     		return err
     	}
    -	details, err := o.command.AddDeviceAuth(ctx, clientID, deviceCode, userCode, expires, scope, audience, slices.Contains(scope, oidc.ScopeOfflineAccess))
    +	details, err := o.command.AddDeviceAuth(ctx, clientID, deviceCode, userCode, orgID, expires, scope, audience, slices.Contains(scope, oidc.ScopeOfflineAccess))
     	if err == nil {
     		logger.SetFields("details", details).Debug(logMsg)
     	}
    
  • internal/api/oidc/integration_test/auth_request_test.go+15 0 modified
    @@ -17,6 +17,7 @@ import (
     	http_utils "github.com/zitadel/zitadel/internal/api/http"
     	oidc_api "github.com/zitadel/zitadel/internal/api/oidc"
     	"github.com/zitadel/zitadel/internal/command"
    +	"github.com/zitadel/zitadel/internal/domain"
     	"github.com/zitadel/zitadel/internal/integration"
     	oidc_pb "github.com/zitadel/zitadel/pkg/grpc/oidc/v2"
     	"github.com/zitadel/zitadel/pkg/grpc/session/v2"
    @@ -36,6 +37,20 @@ func TestOPStorage_CreateAuthRequest(t *testing.T) {
     
     	id2 := createAuthRequestNoLoginClientHeader(t, Instance, clientIDV2, redirectURI)
     	require.Contains(t, id2, command.IDPrefixV2)
    +
    +	// valid org scope must succeed
    +	_, _, err := Instance.CreateOIDCAuthRequest(CTX, clientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID, domain.OrgIDScope+Instance.DefaultOrg.Id)
    +	require.NoError(t, err)
    +
    +	_, _, err = Instance.CreateOIDCAuthRequest(CTX, clientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID, domain.OrgIDScope+Instance.DefaultOrg.Id)
    +	require.NoError(t, err)
    +
    +	// invalid org scope must fail
    +	_, _, err = Instance.CreateOIDCAuthRequest(CTX, clientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID, domain.OrgIDScope+"invalid")
    +	require.Error(t, err)
    +
    +	_, _, err = Instance.CreateOIDCAuthRequest(CTX, clientID, Instance.Users.Get(integration.UserTypeLogin).ID, redirectURI, oidc.ScopeOpenID, domain.OrgIDScope+"invalid")
    +	require.Error(t, err)
     }
     
     func TestOPStorage_CreateAccessToken_code(t *testing.T) {
    
  • internal/command/auth_request.go+23 17 modified
    @@ -30,6 +30,7 @@ type AuthRequest struct {
     	HintUserID       *string
     	NeedRefreshToken bool
     	Issuer           string
    +	OrganizationID   string
     }
     
     type CurrentAuthRequest struct {
    @@ -75,6 +76,7 @@ func (c *Commands) AddAuthRequest(ctx context.Context, authRequest *AuthRequest)
     		authRequest.HintUserID,
     		authRequest.NeedRefreshToken,
     		authRequest.Issuer,
    +		authRequest.OrganizationID,
     	))
     	if err != nil {
     		return nil, err
    @@ -116,6 +118,9 @@ func (c *Commands) LinkSessionToAuthRequest(ctx context.Context, id, sessionID,
     			return nil, nil, err
     		}
     	}
    +	if writeModel.OrganizationID != "" && writeModel.OrganizationID != sessionWriteModel.UserResourceOwner {
    +		return nil, nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-59ljd", "Errors.User.NotAllowedOrg")
    +	}
     
     	if err := c.pushAppendAndReduce(ctx, writeModel, authrequest.NewSessionLinkedEvent(
     		ctx, &authrequest.NewAggregate(id, authz.GetInstance(ctx).InstanceID()).Aggregate,
    @@ -171,23 +176,24 @@ func (c *Commands) AddAuthRequestCode(ctx context.Context, authRequestID, code s
     func authRequestWriteModelToCurrentAuthRequest(writeModel *AuthRequestWriteModel) (_ *CurrentAuthRequest) {
     	return &CurrentAuthRequest{
     		AuthRequest: &AuthRequest{
    -			ID:            writeModel.AggregateID,
    -			LoginClient:   writeModel.LoginClient,
    -			ClientID:      writeModel.ClientID,
    -			RedirectURI:   writeModel.RedirectURI,
    -			State:         writeModel.State,
    -			Nonce:         writeModel.Nonce,
    -			Scope:         writeModel.Scope,
    -			Audience:      writeModel.Audience,
    -			ResponseType:  writeModel.ResponseType,
    -			ResponseMode:  writeModel.ResponseMode,
    -			CodeChallenge: writeModel.CodeChallenge,
    -			Prompt:        writeModel.Prompt,
    -			UILocales:     writeModel.UILocales,
    -			MaxAge:        writeModel.MaxAge,
    -			LoginHint:     writeModel.LoginHint,
    -			HintUserID:    writeModel.HintUserID,
    -			Issuer:        writeModel.Issuer,
    +			ID:             writeModel.AggregateID,
    +			LoginClient:    writeModel.LoginClient,
    +			ClientID:       writeModel.ClientID,
    +			RedirectURI:    writeModel.RedirectURI,
    +			State:          writeModel.State,
    +			Nonce:          writeModel.Nonce,
    +			Scope:          writeModel.Scope,
    +			Audience:       writeModel.Audience,
    +			ResponseType:   writeModel.ResponseType,
    +			ResponseMode:   writeModel.ResponseMode,
    +			CodeChallenge:  writeModel.CodeChallenge,
    +			Prompt:         writeModel.Prompt,
    +			UILocales:      writeModel.UILocales,
    +			MaxAge:         writeModel.MaxAge,
    +			LoginHint:      writeModel.LoginHint,
    +			HintUserID:     writeModel.HintUserID,
    +			Issuer:         writeModel.Issuer,
    +			OrganizationID: writeModel.OrganizationID,
     		},
     		SessionID:   writeModel.SessionID,
     		UserID:      writeModel.UserID,
    
  • internal/command/auth_request_model.go+2 0 modified
    @@ -37,6 +37,7 @@ type AuthRequestWriteModel struct {
     	AuthRequestState domain.AuthRequestState
     	NeedRefreshToken bool
     	Issuer           string
    +	OrganizationID   string
     }
     
     func NewAuthRequestWriteModel(ctx context.Context, id string) *AuthRequestWriteModel {
    @@ -70,6 +71,7 @@ func (m *AuthRequestWriteModel) Reduce() error {
     			m.AuthRequestState = domain.AuthRequestStateAdded
     			m.NeedRefreshToken = e.NeedRefreshToken
     			m.Issuer = e.Issuer
    +			m.OrganizationID = e.OrganizationID
     		case *authrequest.SessionLinkedEvent:
     			m.SessionID = e.SessionID
     			m.UserID = e.UserID
    
  • internal/command/auth_request_test.go+187 12 modified
    @@ -63,6 +63,7 @@ func TestCommands_AddAuthRequest(t *testing.T) {
     								nil,
     								false,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -103,6 +104,7 @@ func TestCommands_AddAuthRequest(t *testing.T) {
     							gu.Ptr("hintUserID"),
     							false,
     							"issuer",
    +							"organizationID",
     						),
     					),
     				),
    @@ -124,12 +126,13 @@ func TestCommands_AddAuthRequest(t *testing.T) {
     						Challenge: "challenge",
     						Method:    domain.CodeChallengeMethodS256,
     					},
    -					Prompt:     []domain.Prompt{domain.PromptNone},
    -					UILocales:  []string{"en", "de"},
    -					MaxAge:     gu.Ptr(time.Duration(0)),
    -					LoginHint:  gu.Ptr("loginHint"),
    -					HintUserID: gu.Ptr("hintUserID"),
    -					Issuer:     "issuer",
    +					Prompt:         []domain.Prompt{domain.PromptNone},
    +					UILocales:      []string{"en", "de"},
    +					MaxAge:         gu.Ptr(time.Duration(0)),
    +					LoginHint:      gu.Ptr("loginHint"),
    +					HintUserID:     gu.Ptr("hintUserID"),
    +					Issuer:         "issuer",
    +					OrganizationID: "organizationID",
     				},
     			},
     			&CurrentAuthRequest{
    @@ -148,12 +151,13 @@ func TestCommands_AddAuthRequest(t *testing.T) {
     						Challenge: "challenge",
     						Method:    domain.CodeChallengeMethodS256,
     					},
    -					Prompt:     []domain.Prompt{domain.PromptNone},
    -					UILocales:  []string{"en", "de"},
    -					MaxAge:     gu.Ptr(time.Duration(0)),
    -					LoginHint:  gu.Ptr("loginHint"),
    -					HintUserID: gu.Ptr("hintUserID"),
    -					Issuer:     "issuer",
    +					Prompt:         []domain.Prompt{domain.PromptNone},
    +					UILocales:      []string{"en", "de"},
    +					MaxAge:         gu.Ptr(time.Duration(0)),
    +					LoginHint:      gu.Ptr("loginHint"),
    +					HintUserID:     gu.Ptr("hintUserID"),
    +					Issuer:         "issuer",
    +					OrganizationID: "organizationID",
     				},
     			},
     			nil,
    @@ -239,6 +243,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    @@ -282,6 +287,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -324,6 +330,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -364,6 +371,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -427,6 +435,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -455,6 +464,71 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     				wantErr: zerrors.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid"),
     			},
     		},
    +		{
    +			"invalid organization",
    +			fields{
    +				eventstore: expectEventstore(
    +					expectFilter(
    +						eventFromEventPusher(
    +							authrequest.NewAddedEvent(mockCtx, &authrequest.NewAggregate("V2_id", "instanceID").Aggregate,
    +								"loginClient",
    +								"clientID",
    +								"redirectURI",
    +								"state",
    +								"nonce",
    +								[]string{"openid"},
    +								[]string{"audience"},
    +								domain.OIDCResponseTypeCode,
    +								domain.OIDCResponseModeQuery,
    +								nil,
    +								nil,
    +								nil,
    +								nil,
    +								nil,
    +								nil,
    +								true,
    +								"issuer",
    +								"organizationID",
    +							),
    +						),
    +					),
    +					expectFilter(
    +						eventFromEventPusher(
    +							session.NewAddedEvent(mockCtx,
    +								&session.NewAggregate("sessionID", "instance1").Aggregate,
    +								&domain.UserAgent{
    +									FingerprintID: gu.Ptr("fp1"),
    +									IP:            net.ParseIP("1.2.3.4"),
    +									Description:   gu.Ptr("firefox"),
    +									Header:        http.Header{"foo": []string{"bar"}},
    +								},
    +							)),
    +						eventFromEventPusher(
    +							session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								"userID", "org1", testNow, &language.Afrikaans),
    +						),
    +						eventFromEventPusher(
    +							session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								testNow),
    +						),
    +						eventFromEventPusherWithCreationDateNow(
    +							session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								2*time.Minute),
    +						),
    +					),
    +				),
    +				tokenVerifier: newMockTokenVerifierValid(),
    +			},
    +			args{
    +				ctx:          mockCtx,
    +				id:           "V2_id",
    +				sessionID:    "sessionID",
    +				sessionToken: "token",
    +			},
    +			res{
    +				wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-59ljd", "Errors.User.NotAllowedOrg"),
    +			},
    +		},
     		{
     			"linked",
     			fields{
    @@ -479,6 +553,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -545,6 +620,98 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     				},
     			},
     		},
    +		{
    +			"linked with organization check",
    +			fields{
    +				eventstore: expectEventstore(
    +					expectFilter(
    +						eventFromEventPusher(
    +							authrequest.NewAddedEvent(mockCtx, &authrequest.NewAggregate("V2_id", "instanceID").Aggregate,
    +								"loginClient",
    +								"clientID",
    +								"redirectURI",
    +								"state",
    +								"nonce",
    +								[]string{"openid"},
    +								[]string{"audience"},
    +								domain.OIDCResponseTypeCode,
    +								domain.OIDCResponseModeQuery,
    +								nil,
    +								nil,
    +								nil,
    +								nil,
    +								nil,
    +								nil,
    +								true,
    +								"issuer",
    +								"org1",
    +							),
    +						),
    +					),
    +					expectFilter(
    +						eventFromEventPusher(
    +							session.NewAddedEvent(mockCtx,
    +								&session.NewAggregate("sessionID", "instance1").Aggregate,
    +								&domain.UserAgent{
    +									FingerprintID: gu.Ptr("fp1"),
    +									IP:            net.ParseIP("1.2.3.4"),
    +									Description:   gu.Ptr("firefox"),
    +									Header:        http.Header{"foo": []string{"bar"}},
    +								},
    +							)),
    +						eventFromEventPusher(
    +							session.NewUserCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								"userID", "org1", testNow, &language.Afrikaans),
    +						),
    +						eventFromEventPusher(
    +							session.NewPasswordCheckedEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								testNow),
    +						),
    +						eventFromEventPusherWithCreationDateNow(
    +							session.NewLifetimeSetEvent(mockCtx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								2*time.Minute),
    +						),
    +					),
    +					expectPush(
    +						authrequest.NewSessionLinkedEvent(mockCtx, &authrequest.NewAggregate("V2_id", "instanceID").Aggregate,
    +							"sessionID",
    +							"userID",
    +							testNow,
    +							[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
    +						),
    +					),
    +				),
    +				tokenVerifier: newMockTokenVerifierValid(),
    +			},
    +			args{
    +				ctx:          mockCtx,
    +				id:           "V2_id",
    +				sessionID:    "sessionID",
    +				sessionToken: "token",
    +			},
    +			res{
    +				details: &domain.ObjectDetails{ResourceOwner: "instanceID"},
    +				authReq: &CurrentAuthRequest{
    +					AuthRequest: &AuthRequest{
    +						ID:             "V2_id",
    +						LoginClient:    "loginClient",
    +						ClientID:       "clientID",
    +						RedirectURI:    "redirectURI",
    +						State:          "state",
    +						Nonce:          "nonce",
    +						Scope:          []string{"openid"},
    +						Audience:       []string{"audience"},
    +						ResponseType:   domain.OIDCResponseTypeCode,
    +						ResponseMode:   domain.OIDCResponseModeQuery,
    +						Issuer:         "issuer",
    +						OrganizationID: "org1",
    +					},
    +					SessionID:   "sessionID",
    +					UserID:      "userID",
    +					AuthMethods: []domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
    +				},
    +			},
    +		},
     		{
     			"linked with login client check",
     			fields{
    @@ -569,6 +736,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -660,6 +828,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -752,6 +921,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -845,6 +1015,7 @@ func TestCommands_LinkSessionToAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -970,6 +1141,7 @@ func TestCommands_FailAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -1009,6 +1181,7 @@ func TestCommands_FailAuthRequest(t *testing.T) {
     								nil,
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -1113,6 +1286,7 @@ func TestCommands_AddAuthRequestCode(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								true,
     								"issuer",
    +								"",
     							),
     						),
     					),
    @@ -1152,6 +1326,7 @@ func TestCommands_AddAuthRequestCode(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								true,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    
  • internal/command/device_auth.go+8 1 modified
    @@ -15,7 +15,7 @@ import (
     	"github.com/zitadel/zitadel/internal/zerrors"
     )
     
    -func (c *Commands) AddDeviceAuth(ctx context.Context, clientID, deviceCode, userCode string, expires time.Time, scopes, audience []string, needRefreshToken bool) (*domain.ObjectDetails, error) {
    +func (c *Commands) AddDeviceAuth(ctx context.Context, clientID, deviceCode, userCode, orgID string, expires time.Time, scopes, audience []string, needRefreshToken bool) (*domain.ObjectDetails, error) {
     	aggr := deviceauth.NewAggregate(deviceCode, authz.GetInstance(ctx).InstanceID())
     	model := NewDeviceAuthWriteModel(deviceCode, aggr.ResourceOwner)
     
    @@ -29,6 +29,7 @@ func (c *Commands) AddDeviceAuth(ctx context.Context, clientID, deviceCode, user
     		scopes,
     		audience,
     		needRefreshToken,
    +		orgID,
     	))
     	if err != nil {
     		return nil, err
    @@ -62,6 +63,9 @@ func (c *Commands) ApproveDeviceAuth(
     	if model.State != domain.DeviceAuthStateInitiated {
     		return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-GEJL3", "Errors.DeviceAuth.AlreadyHandled")
     	}
    +	if model.OrganizationID != "" && model.OrganizationID != userOrgID {
    +		return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-3tgws", "Errors.User.NotAllowedOrg")
    +	}
     	pushedEvents, err := c.eventstore.Push(ctx, deviceauth.NewApprovedEvent(ctx, model.aggregate, userID, userOrgID, authMethods, authTime, preferredLanguage, userAgent, sessionID))
     	if err != nil {
     		return nil, err
    @@ -105,6 +109,9 @@ func (c *Commands) ApproveDeviceAuthWithSession(
     	if err := c.sessionTokenVerifier(ctx, sessionToken, sessionWriteModel.AggregateID, sessionWriteModel.TokenID); err != nil {
     		return nil, err
     	}
    +	if model.OrganizationID != "" && model.OrganizationID != sessionWriteModel.UserResourceOwner {
    +		return nil, zerrors.ThrowPreconditionFailed(nil, "COMMAND-D2j34", "Errors.User.NotAllowedOrg")
    +	}
     
     	pushedEvents, err := c.eventstore.Push(ctx, deviceauth.NewApprovedEvent(
     		ctx,
    
  • internal/command/device_auth_model.go+2 0 modified
    @@ -29,6 +29,7 @@ type DeviceAuthWriteModel struct {
     	UserAgent         *domain.UserAgent
     	NeedRefreshToken  bool
     	SessionID         string
    +	OrganizationID    string
     }
     
     func NewDeviceAuthWriteModel(deviceCode, resourceOwner string) *DeviceAuthWriteModel {
    @@ -53,6 +54,7 @@ func (m *DeviceAuthWriteModel) Reduce() error {
     			m.Audience = e.Audience
     			m.State = e.State
     			m.NeedRefreshToken = e.NeedRefreshToken
    +			m.OrganizationID = e.OrganizationID
     		case *deviceauth.ApprovedEvent:
     			m.State = domain.DeviceAuthStateApproved
     			m.UserID = e.UserID
    
  • internal/command/device_auth_test.go+227 24 modified
    @@ -49,6 +49,7 @@ func TestCommands_AddDeviceAuth(t *testing.T) {
     		scopes           []string
     		audience         []string
     		needRefreshToken bool
    +		organizationID   string
     	}
     	tests := []struct {
     		name        string
    @@ -66,7 +67,7 @@ func TestCommands_AddDeviceAuth(t *testing.T) {
     						deviceauth.NewAggregate("123", "instance1"),
     						"client_id", "123", "456", now,
     						[]string{"a", "b", "c"},
    -						[]string{"projectID", "clientID"}, true,
    +						[]string{"projectID", "clientID"}, true, "orgID",
     					),
     				)),
     			},
    @@ -79,6 +80,7 @@ func TestCommands_AddDeviceAuth(t *testing.T) {
     				scopes:           []string{"a", "b", "c"},
     				audience:         []string{"projectID", "clientID"},
     				needRefreshToken: true,
    +				organizationID:   "orgID",
     			},
     			wantDetails: &domain.ObjectDetails{
     				ResourceOwner: "instance1",
    @@ -93,7 +95,7 @@ func TestCommands_AddDeviceAuth(t *testing.T) {
     						deviceauth.NewAggregate("123", "instance1"),
     						"client_id", "123", "456", now,
     						[]string{"a", "b", "c"},
    -						[]string{"projectID", "clientID"}, false,
    +						[]string{"projectID", "clientID"}, false, "orgID",
     					)),
     				),
     			},
    @@ -106,6 +108,7 @@ func TestCommands_AddDeviceAuth(t *testing.T) {
     				scopes:           []string{"a", "b", "c"},
     				audience:         []string{"projectID", "clientID"},
     				needRefreshToken: false,
    +				organizationID:   "orgID",
     			},
     			wantErr: pushErr,
     		},
    @@ -115,7 +118,17 @@ func TestCommands_AddDeviceAuth(t *testing.T) {
     			c := &Commands{
     				eventstore: tt.fields.eventstore(t),
     			}
    -			gotDetails, err := c.AddDeviceAuth(tt.args.ctx, tt.args.clientID, tt.args.deviceCode, tt.args.userCode, tt.args.expires, tt.args.scopes, tt.args.audience, tt.args.needRefreshToken)
    +			gotDetails, err := c.AddDeviceAuth(
    +				tt.args.ctx,
    +				tt.args.clientID,
    +				tt.args.deviceCode,
    +				tt.args.userCode,
    +				tt.args.organizationID,
    +				tt.args.expires,
    +				tt.args.scopes,
    +				tt.args.audience,
    +				tt.args.needRefreshToken,
    +			)
     			require.ErrorIs(t, err, tt.wantErr)
     			assertObjectDetails(t, tt.wantDetails, gotDetails)
     		})
    @@ -168,6 +181,35 @@ func TestCommands_ApproveDeviceAuth(t *testing.T) {
     			},
     			wantErr: zerrors.ThrowNotFound(nil, "COMMAND-Hief9", "Errors.DeviceAuth.NotFound"),
     		},
    +		{
    +			name: "invalid org",
    +			fields: fields{
    +				eventstore: expectEventstore(
    +					expectFilter(eventFromEventPusherWithInstanceID(
    +						"instance1",
    +						deviceauth.NewAddedEvent(
    +							ctx,
    +							deviceauth.NewAggregate("123", "instance1"),
    +							"client_id", "123", "456", now,
    +							[]string{"a", "b", "c"},
    +							[]string{"projectID", "clientID"}, true, "orgID2",
    +						),
    +					)),
    +				),
    +			},
    +			args: args{
    +				ctx, "123", "subj", "orgID",
    +				[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
    +				time.Unix(123, 456), &language.Afrikaans, &domain.UserAgent{
    +					FingerprintID: gu.Ptr("fp1"),
    +					IP:            net.ParseIP("1.2.3.4"),
    +					Description:   gu.Ptr("firefox"),
    +					Header:        http.Header{"foo": []string{"bar"}},
    +				},
    +				"sessionID",
    +			},
    +			wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-3tgws", "Errors.User.NotAllowedOrg"),
    +		},
     		{
     			name: "push error",
     			fields: fields{
    @@ -179,7 +221,7 @@ func TestCommands_ApproveDeviceAuth(t *testing.T) {
     							deviceauth.NewAggregate("123", "instance1"),
     							"client_id", "123", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     					expectPushFailed(pushErr,
    @@ -221,7 +263,51 @@ func TestCommands_ApproveDeviceAuth(t *testing.T) {
     							deviceauth.NewAggregate("123", "instance1"),
     							"client_id", "123", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
    +						),
    +					)),
    +					expectPush(
    +						deviceauth.NewApprovedEvent(
    +							ctx, deviceauth.NewAggregate("123", "instance1"), "subj", "orgID",
    +							[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
    +							time.Unix(123, 456), &language.Afrikaans, &domain.UserAgent{
    +								FingerprintID: gu.Ptr("fp1"),
    +								IP:            net.ParseIP("1.2.3.4"),
    +								Description:   gu.Ptr("firefox"),
    +								Header:        http.Header{"foo": []string{"bar"}},
    +							},
    +							"sessionID",
    +						),
    +					),
    +				),
    +			},
    +			args: args{
    +				ctx, "123", "subj", "orgID",
    +				[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
    +				time.Unix(123, 456), &language.Afrikaans, &domain.UserAgent{
    +					FingerprintID: gu.Ptr("fp1"),
    +					IP:            net.ParseIP("1.2.3.4"),
    +					Description:   gu.Ptr("firefox"),
    +					Header:        http.Header{"foo": []string{"bar"}},
    +				},
    +				"sessionID",
    +			},
    +			wantDetails: &domain.ObjectDetails{
    +				ResourceOwner: "instance1",
    +			},
    +		},
    +		{
    +			name: "success with organizationID in device auth",
    +			fields: fields{
    +				eventstore: expectEventstore(
    +					expectFilter(eventFromEventPusherWithInstanceID(
    +						"instance1",
    +						deviceauth.NewAddedEvent(
    +							ctx,
    +							deviceauth.NewAggregate("123", "instance1"),
    +							"client_id", "123", "456", now,
    +							[]string{"a", "b", "c"},
    +							[]string{"projectID", "clientID"}, true, "orgID",
     						),
     					)),
     					expectPush(
    @@ -317,7 +403,7 @@ func TestCommands_ApproveDeviceAuthFromSession(t *testing.T) {
     								deviceauth.NewAggregate("deviceCode", "instance1"),
     								"client_id", "deviceCode", "456", now,
     								[]string{"a", "b", "c"},
    -								[]string{"projectID", "clientID"}, true,
    +								[]string{"projectID", "clientID"}, true, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    @@ -349,7 +435,7 @@ func TestCommands_ApproveDeviceAuthFromSession(t *testing.T) {
     							deviceauth.NewAggregate("deviceCode", "instance1"),
     							"client_id", "deviceCode", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     				),
    @@ -374,7 +460,7 @@ func TestCommands_ApproveDeviceAuthFromSession(t *testing.T) {
     							deviceauth.NewAggregate("deviceCode", "instance1"),
     							"client_id", "deviceCode", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     					expectFilter(),
    @@ -400,7 +486,7 @@ func TestCommands_ApproveDeviceAuthFromSession(t *testing.T) {
     							deviceauth.NewAggregate("deviceCode", "instance1"),
     							"client_id", "deviceCode", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     					expectFilter(eventFromEventPusherWithInstanceID(
    @@ -426,6 +512,57 @@ func TestCommands_ApproveDeviceAuthFromSession(t *testing.T) {
     			},
     			wantErr: zerrors.ThrowPermissionDenied(nil, "COMMAND-sGr42", "Errors.Session.Token.Invalid"),
     		},
    +		{
    +			name: "invalid organization, error",
    +			fields: fields{
    +				eventstore: expectEventstore(
    +					expectFilter(eventFromEventPusherWithInstanceID(
    +						"instance1",
    +						deviceauth.NewAddedEvent(
    +							ctx,
    +							deviceauth.NewAggregate("deviceCode", "instance1"),
    +							"client_id", "deviceCode", "456", now,
    +							[]string{"a", "b", "c"},
    +							[]string{"projectID", "clientID"}, true, "orgID2",
    +						),
    +					)),
    +					expectFilter(
    +						eventFromEventPusherWithInstanceID(
    +							"instance1",
    +							session.NewAddedEvent(ctx,
    +								&session.NewAggregate("sessionID", "instance1").Aggregate,
    +								&domain.UserAgent{
    +									FingerprintID: gu.Ptr("fp1"),
    +									IP:            net.ParseIP("1.2.3.4"),
    +									Description:   gu.Ptr("firefox"),
    +									Header:        http.Header{"foo": []string{"bar"}},
    +								},
    +							)),
    +						eventFromEventPusher(
    +							session.NewUserCheckedEvent(ctx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								"userID", "orgID", testNow, &language.Afrikaans),
    +						),
    +						eventFromEventPusher(
    +							session.NewPasswordCheckedEvent(ctx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								testNow),
    +						),
    +						eventFromEventPusherWithCreationDateNow(
    +							session.NewLifetimeSetEvent(ctx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								2*time.Minute),
    +						),
    +					),
    +				),
    +				tokenVerifier:   newMockTokenVerifierValid(),
    +				checkPermission: newMockPermissionCheckAllowed(),
    +			},
    +			args: args{
    +				ctx,
    +				"deviceCode",
    +				"sessionID",
    +				"sessionToken",
    +			},
    +			wantErr: zerrors.ThrowPreconditionFailed(nil, "COMMAND-D2j34", "Errors.User.NotAllowedOrg"),
    +		},
     		{
     			name: "push error",
     			fields: fields{
    @@ -437,7 +574,7 @@ func TestCommands_ApproveDeviceAuthFromSession(t *testing.T) {
     							deviceauth.NewAggregate("deviceCode", "instance1"),
     							"client_id", "deviceCode", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     					expectFilter(
    @@ -501,7 +638,73 @@ func TestCommands_ApproveDeviceAuthFromSession(t *testing.T) {
     							deviceauth.NewAggregate("deviceCode", "instance1"),
     							"client_id", "deviceCode", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
    +						),
    +					)),
    +					expectFilter(
    +						eventFromEventPusher(
    +							session.NewAddedEvent(ctx,
    +								&session.NewAggregate("sessionID", "instance1").Aggregate,
    +								&domain.UserAgent{
    +									FingerprintID: gu.Ptr("fp1"),
    +									IP:            net.ParseIP("1.2.3.4"),
    +									Description:   gu.Ptr("firefox"),
    +									Header:        http.Header{"foo": []string{"bar"}},
    +								},
    +							),
    +						),
    +						eventFromEventPusher(
    +							session.NewUserCheckedEvent(ctx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								"userID", "orgID", testNow, &language.Afrikaans),
    +						),
    +						eventFromEventPusher(
    +							session.NewPasswordCheckedEvent(ctx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								testNow),
    +						),
    +						eventFromEventPusherWithCreationDateNow(
    +							session.NewLifetimeSetEvent(ctx, &session.NewAggregate("sessionID", "instance1").Aggregate,
    +								2*time.Minute),
    +						),
    +					),
    +					expectPush(
    +						deviceauth.NewApprovedEvent(
    +							ctx, deviceauth.NewAggregate("deviceCode", "instance1"), "userID", "orgID",
    +							[]domain.UserAuthMethodType{domain.UserAuthMethodTypePassword},
    +							testNow, &language.Afrikaans, &domain.UserAgent{
    +								FingerprintID: gu.Ptr("fp1"),
    +								IP:            net.ParseIP("1.2.3.4"),
    +								Description:   gu.Ptr("firefox"),
    +								Header:        http.Header{"foo": []string{"bar"}},
    +							},
    +							"sessionID",
    +						),
    +					),
    +				),
    +				tokenVerifier:   newMockTokenVerifierValid(),
    +				checkPermission: newMockPermissionCheckAllowed(),
    +			},
    +			args: args{
    +				ctx,
    +				"deviceCode",
    +				"sessionID",
    +				"sessionToken",
    +			},
    +			wantDetails: &domain.ObjectDetails{
    +				ResourceOwner: "instance1",
    +			},
    +		},
    +		{
    +			name: "authorized with organizationID in device auth",
    +			fields: fields{
    +				eventstore: expectEventstore(
    +					expectFilter(eventFromEventPusherWithInstanceID(
    +						"instance1",
    +						deviceauth.NewAddedEvent(
    +							ctx,
    +							deviceauth.NewAggregate("deviceCode", "instance1"),
    +							"client_id", "deviceCode", "456", now,
    +							[]string{"a", "b", "c"},
    +							[]string{"projectID", "clientID"}, true, "orgID",
     						),
     					)),
     					expectFilter(
    @@ -613,7 +816,7 @@ func TestCommands_CancelDeviceAuth(t *testing.T) {
     							deviceauth.NewAggregate("123", "instance1"),
     							"client_id", "123", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     				),
    @@ -633,7 +836,7 @@ func TestCommands_CancelDeviceAuth(t *testing.T) {
     							deviceauth.NewAggregate("123", "instance1"),
     							"client_id", "123", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     					expectPushFailed(pushErr,
    @@ -659,7 +862,7 @@ func TestCommands_CancelDeviceAuth(t *testing.T) {
     							deviceauth.NewAggregate("123", "instance1"),
     							"client_id", "123", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     					expectPush(
    @@ -687,7 +890,7 @@ func TestCommands_CancelDeviceAuth(t *testing.T) {
     							deviceauth.NewAggregate("123", "instance1"),
     							"client_id", "123", "456", now,
     							[]string{"a", "b", "c"},
    -							[]string{"projectID", "clientID"}, true,
    +							[]string{"projectID", "clientID"}, true, "",
     						),
     					)),
     					expectPush(
    @@ -767,7 +970,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     					),
    @@ -806,7 +1009,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     					),
    @@ -835,7 +1038,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    @@ -867,7 +1070,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    @@ -899,7 +1102,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    @@ -937,7 +1140,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    @@ -1001,7 +1204,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    @@ -1098,7 +1301,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, false,
    +								[]string{"audience"}, false, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    @@ -1202,7 +1405,7 @@ func TestCommands_CreateOIDCSessionFromDeviceAuth(t *testing.T) {
     								deviceauth.NewAggregate("123", "instance1"),
     								"clientID", "123", "456", time.Now().Add(-time.Minute),
     								[]string{"openid", "offline_access"},
    -								[]string{"audience"}, true,
    +								[]string{"audience"}, true, "",
     							),
     						),
     						eventFromEventPusherWithInstanceID(
    
  • internal/command/oidc_session_test.go+6 0 modified
    @@ -138,6 +138,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								true,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    @@ -183,6 +184,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								true,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    @@ -236,6 +238,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								true,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    @@ -334,6 +337,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								true,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    @@ -468,6 +472,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								true,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    @@ -611,6 +616,7 @@ func TestCommands_CreateOIDCSessionFromAuthRequest(t *testing.T) {
     								gu.Ptr("hintUserID"),
     								false,
     								"issuer",
    +								"",
     							),
     						),
     						eventFromEventPusher(
    
  • internal/domain/auth_request.go+6 12 modified
    @@ -230,24 +230,18 @@ func (a *AuthRequest) AppendAudIfNotExisting(aud string) {
     }
     
     func (a *AuthRequest) GetScopeOrgPrimaryDomain() string {
    -	switch request := a.Request.(type) {
    -	case *AuthRequestOIDC:
    -		for _, scope := range request.Scopes {
    -			if strings.HasPrefix(scope, OrgDomainPrimaryScope) {
    -				return strings.TrimPrefix(scope, OrgDomainPrimaryScope)
    -			}
    +	for _, scope := range a.Request.GetScopes() {
    +		if strings.HasPrefix(scope, OrgDomainPrimaryScope) {
    +			return strings.TrimPrefix(scope, OrgDomainPrimaryScope)
     		}
     	}
     	return ""
     }
     
     func (a *AuthRequest) GetScopeOrgID() string {
    -	switch request := a.Request.(type) {
    -	case *AuthRequestOIDC:
    -		for _, scope := range request.Scopes {
    -			if strings.HasPrefix(scope, OrgIDScope) {
    -				return strings.TrimPrefix(scope, OrgIDScope)
    -			}
    +	for _, scope := range a.Request.GetScopes() {
    +		if strings.HasPrefix(scope, OrgIDScope) {
    +			return strings.TrimPrefix(scope, OrgIDScope)
     		}
     	}
     	return ""
    
  • internal/domain/request.go+39 0 modified
    @@ -17,6 +17,7 @@ const (
     type Request interface {
     	Type() AuthRequestType
     	IsValid() bool
    +	GetScopes() []string
     }
     
     type AuthRequestType int32
    @@ -35,6 +36,18 @@ type AuthRequestOIDC struct {
     	CodeChallenge *OIDCCodeChallenge
     }
     
    +func NewAuthRequestOIDC(
    +	scopes []string,
    +	responseType OIDCResponseType,
    +	responseMode OIDCResponseMode,
    +	nonce string,
    +	codeChallenge *OIDCCodeChallenge,
    +) *AuthRequestOIDC {
    +	return &AuthRequestOIDC{
    +		scopes, responseType, responseMode, nonce, codeChallenge,
    +	}
    +}
    +
     func (a *AuthRequestOIDC) Type() AuthRequestType {
     	return AuthRequestTypeOIDC
     }
    @@ -44,6 +57,10 @@ func (a *AuthRequestOIDC) IsValid() bool {
     		a.CodeChallenge == nil || a.CodeChallenge != nil && a.CodeChallenge.IsValid()
     }
     
    +func (a *AuthRequestOIDC) GetScopes() []string {
    +	return a.Scopes
    +}
    +
     type AuthRequestSAML struct {
     	ID          string
     	BindingType string
    @@ -61,6 +78,10 @@ func (a *AuthRequestSAML) IsValid() bool {
     	return true
     }
     
    +func (*AuthRequestSAML) GetScopes() []string {
    +	return nil
    +}
    +
     type AuthRequestDevice struct {
     	ClientID    string
     	DeviceCode  string
    @@ -71,10 +92,28 @@ type AuthRequestDevice struct {
     	ProjectName string
     }
     
    +func NewAuthRequestDevice(
    +	clientID string,
    +	deviceCode string,
    +	userCode string,
    +	scopes []string,
    +	audience []string,
    +	appName string,
    +	projectName string,
    +) *AuthRequestDevice {
    +	return &AuthRequestDevice{
    +		clientID, deviceCode, userCode, scopes, audience, appName, projectName,
    +	}
    +}
    +
     func (*AuthRequestDevice) Type() AuthRequestType {
     	return AuthRequestTypeDevice
     }
     
     func (a *AuthRequestDevice) IsValid() bool {
     	return a.DeviceCode != "" && a.UserCode != ""
     }
    +
    +func (a *AuthRequestDevice) GetScopes() []string {
    +	return a.Scopes
    +}
    
  • internal/query/device_auth.go+7 10 modified
    @@ -98,18 +98,20 @@ func prepareDeviceAuthQuery() (sq.SelectBuilder, func(*sql.Row) (*domain.AuthReq
     			LeftJoin(join(ProjectColumnID, AppColumnProjectID)).
     			PlaceholderFormat(sq.Dollar),
     		func(row *sql.Row) (*domain.AuthRequestDevice, error) {
    -			dst := new(domain.AuthRequestDevice)
     			var (
    +				clientID    string
    +				deviceCode  string
    +				userCode    string
     				scopes      database.TextArray[string]
     				audience    database.TextArray[string]
     				appName     sql.NullString
     				projectName sql.NullString
     			)
     
     			err := row.Scan(
    -				&dst.ClientID,
    -				&dst.DeviceCode,
    -				&dst.UserCode,
    +				&clientID,
    +				&deviceCode,
    +				&userCode,
     				&scopes,
     				&audience,
     				&appName,
    @@ -121,11 +123,6 @@ func prepareDeviceAuthQuery() (sq.SelectBuilder, func(*sql.Row) (*domain.AuthReq
     			if err != nil {
     				return nil, zerrors.ThrowInternal(err, "QUERY-Voo3o", "Errors.Internal")
     			}
    -			dst.Scopes = scopes
    -			dst.Audience = audience
    -			dst.AppName = appName.String
    -			dst.ProjectName = projectName.String
    -
    -			return dst, nil
    +			return domain.NewAuthRequestDevice(clientID, deviceCode, userCode, scopes, audience, appName.String, projectName.String), nil
     		}
     }
    
  • internal/query/device_auth_test.go+9 9 modified
    @@ -52,15 +52,15 @@ var (
     		"appName",
     		"projectName",
     	}
    -	expectedDeviceAuth = &domain.AuthRequestDevice{
    -		ClientID:    "client-id",
    -		DeviceCode:  "device1",
    -		UserCode:    "user-code",
    -		Scopes:      []string{"a", "b", "c"},
    -		Audience:    []string{"projectID", "clientID"},
    -		AppName:     "appName",
    -		ProjectName: "projectName",
    -	}
    +	expectedDeviceAuth = domain.NewAuthRequestDevice(
    +		"client-id",
    +		"device1",
    +		"user-code",
    +		[]string{"a", "b", "c"},
    +		[]string{"projectID", "clientID"},
    +		"appName",
    +		"projectName",
    +	)
     )
     
     func TestQueries_DeviceAuthRequestByUserCode(t *testing.T) {
    
  • internal/repository/authrequest/auth_request.go+4 1 modified
    @@ -39,6 +39,7 @@ type AddedEvent struct {
     	HintUserID       *string                   `json:"hint_user_id,omitempty"`
     	NeedRefreshToken bool                      `json:"need_refresh_token,omitempty"`
     	Issuer           string                    `json:"issuer,omitempty"`
    +	OrganizationID   string                    `json:"organization_id,omitempty"`
     }
     
     func (e *AddedEvent) Payload() interface{} {
    @@ -67,7 +68,8 @@ func NewAddedEvent(ctx context.Context,
     	loginHint,
     	hintUserID *string,
     	needRefreshToken bool,
    -	issuer string,
    +	issuer,
    +	organizationID string,
     ) *AddedEvent {
     	return &AddedEvent{
     		BaseEvent: *eventstore.NewBaseEventForPush(
    @@ -92,6 +94,7 @@ func NewAddedEvent(ctx context.Context,
     		HintUserID:       hintUserID,
     		NeedRefreshToken: needRefreshToken,
     		Issuer:           issuer,
    +		OrganizationID:   organizationID,
     	}
     }
     
    
  • internal/repository/deviceauth/device_auth.go+3 0 modified
    @@ -29,6 +29,7 @@ type AddedEvent struct {
     	Audience         []string
     	State            domain.DeviceAuthState
     	NeedRefreshToken bool
    +	OrganizationID   string
     }
     
     func (e *AddedEvent) SetBaseEvent(b *eventstore.BaseEvent) {
    @@ -53,13 +54,15 @@ func NewAddedEvent(
     	scopes []string,
     	audience []string,
     	needRefreshToken bool,
    +	organizationID string,
     ) *AddedEvent {
     	return &AddedEvent{
     		eventstore.NewBaseEventForPush(
     			ctx, aggregate, AddedEventType,
     		),
     		clientID, deviceCode, userCode, expires, scopes, audience,
     		domain.DeviceAuthStateInitiated, needRefreshToken,
    +		organizationID,
     	}
     }
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.