Enterprise Login, Teams, OAuth, and OIDC
Turn an enterprise sign-in into a current organization-and-team context, then distinguish platform login from machine and human connector delegation.
The enterprise problem and today’s slice
Enterprise problem: A valid enterprise login can carry stale memberships or be confused with permission to use an external connector, causing a transferred or deprovisioned employee to retain team or downstream access.
Whole-course context: Day 04 produced a typed identity context and intersection rule; today supplies the authenticated human, current active-team membership, and separately governed OAuth (the standard delegated-authorization protocol) grants that later runs will consume.
Today’s slice: We design OpenID Connect (OIDC) or Security Assertion Markup Language (SAML) login, just-in-time (JIT) or System for Cross-domain Identity Management (SCIM) lifecycle input, organization and active-team resolution, explicit generated-app tenant and role mapping, admin-provisioned machine access, and optional user-delegated OAuth across all authorization boundaries.
End-of-day evidence: A reviewer receives positive and negative login traces, a team-switch and cross-tenant proof, and separate machine-grant and user-consent records with issuer, audience, scope, revision, environment, timestamp, and immutable trace IDs.
Still unsolved: Run authorization, per-tool argument policy, high-risk approval, production connector execution, and continuous revocation are deliberately deferred.
Customer use cases
Treating a signed token as the complete authorization state lets stale or wrongly addressed claims cross customer boundaries, so the platform must authenticate the subject and then resolve current authority independently.
OpenID Connect (OIDC) adds authentication to OAuth 2.0 and gives the client an ID token describing who signed in. OAuth 2.0 delegates limited access to a resource server; its access token describes what a client may do, not a reusable proof of platform identity.
| Use case ID | Actor | Customer job | Success outcome | Denial or recovery evidence |
|---|---|---|---|---|
| D05-UC-01 | Enterprise identity administrator and employee | Configure OIDC or SAML, provision a person through JIT or SCIM, and sign in | Exact provider metadata and callbacks validate, one protocol subject resolves to one enterprise principal, and authentication and provisioning remain separately auditable | Bad issuer, audience, signature, nonce, state, replay, disabled SCIM record, or duplicate protocol subject produces a specific denial trace and no session |
| D05-UC-02 | Multi-team generated-app employee | Select one provider team and receive the intended application tenant and role | Current provider membership resolves through an explicit subject binding to one app-owned subject, tenant, membership, and role | Cross-organization team selection, unbound principal, synthetic preview fixture, or same-local-ID cross-tenant request is denied while the employee's valid tenant remains allowed |
| D05-UC-03 | Integration administrator and hosted runtime | Provision and use stable non-human connector authority | A workload grant pins workload, application, environment, connector version, operations, audience, and tenant without acquiring any human session | Substituting a project role, app session, or human token for workload identity is denied and the valid workload path remains allowed |
| D05-UC-04 | Data-authorized employee | Optionally link the employee's external account for one on-behalf-of operation | A distinct delegated grant binds user, app tenant, connector, source account, operation, audience, consent version, and bounded lifetime | Wrong user, tenant, source, audience, scope, expired consent, or revocation denies delegation without disabling SSO, app membership, or workload access |
Organization roles and team roles answer different questions:
| Scope | Example roles | Appropriate decisions |
|---|---|---|
| Organization | org_admin, it_admin, security_admin, ai_studio_admin, billing_admin, member | Configure enterprise identity, manage organization policy, provision teams, inspect organization audit |
| Team | team_admin, agent_builder, agent_operator, member, viewer | Build, run, review, or administer resources inside one team |
The platform selects one primary team per operation. It must not create an accidental permission union such as Marketing plus Finance plus Legal merely because one employee belongs to all three.
Actor-centred user stories
When identity, team choice, and connector consent are expressed as one vague “logged in” state, customers cannot revoke the correct authority without disrupting unrelated work.
| Story ID | Use case IDs | User story | Observable acceptance conditions |
|---|---|---|---|
| D05-US-01 | D05-UC-01 | As a customer identity administrator, I want OIDC or SAML sign-in and JIT or SCIM lifecycle control configured independently, so that login and provisioning failures can be diagnosed and revoked separately | Console shows verified issuer or entity ID, exact redirect or assertion-consumer-service endpoint, signing metadata, stable subject mapping, provisioning status, and distinct authentication and lifecycle traces |
| D05-US-02 | D05-UC-02 | As a multi-team generated-app employee, I want my verified principal mapped to the intended provider team and app-owned tenant role, so that signing in never grants another tenant's data | Alpha membership allows only Alpha resources; a Beta resource with the same local ID fails; evidence links principal, active team, subject binding, app subject, tenant, membership, role, and policy version |
| D05-US-03 | D05-UC-03 | As a connector administrator, I want a team workload grant separated from every human identity, so that scheduled automation remains durable without inheriting a builder or employee session | Workload grant is provisioned and tested first; connector call succeeds only for its pinned identity, version, operation, audience, and tenant; human-token substitution is denied |
| D05-US-04 | D05-UC-04 | As a data-authorized employee, I want optional on-behalf-of connector access scoped to my consent, so that revoking delegation stops source use without disabling my application account | Valid exchange returns a short-lived audience-restricted credential; consent revocation or tenant mismatch denies the next exchange while sign-in, app membership, provisioning, and workload probes stay healthy |
The modern interactive login flow is Authorization Code with PKCE. PKCE means Proof Key for Code Exchange: the client generates a secret verifier, sends only its derived challenge before login, and must present the verifier when exchanging the one-time code. An intercepted code is therefore not enough to obtain tokens.
OIDC ID token -> client learns authenticated user identity
OAuth access token -> resource server evaluates delegated API access
OAuth refresh token -> client obtains new access tokens; highly sensitive
Tokens are encoded claims, not automatic truth. If a token is a JSON Web Token (JWT), the receiver validates signature, allowed algorithm, issuer, audience, expiry, not-before time, and authorized client before using its claims. Its readable payload is signed, not encrypted; secrets must never be placed in it.
For enterprise connectors, provision machine authority first:
- An administrator creates a team-owned workload or service-account grant.
- The downstream administrator limits its scopes and resource access-control lists.
- The platform limits which team, connector, and operations may select it.
- A positive and negative probe records observed behavior.
- Only then may an employee add optional on-behalf-of access to their personal account through a separate consent flow.
Neither grant inherits the other. Client Credentials is suitable for a confidential backend acting as itself; Authorization Code with PKCE is suitable when a human delegates access. A public browser client cannot safely hold a client secret.
SAML, or Security Assertion Markup Language, is a common enterprise authentication alternative to OIDC. The relying party validates the assertion signature, exact issuer, audience restriction, recipient, time conditions, request correlation, and replay state. Both protocols normalize to a stable key such as (identity_provider_id, protocol_subject); an email address is mutable profile data, never an identity join.
SCIM, the System for Cross-domain Identity Management, provisions and deactivates users and groups. Just-in-time (JIT) provisioning creates or updates a principal during a successful login. Neither mechanism creates a login session, active provider team, app tenant membership, app role, workload grant, or connector delegation by itself.
End-to-end product flows
Login and delegation failures are dangerous when redirects obscure the terminal result, so each path must end in a visible session, denial, revocation, or independently verified downstream probe.
| Flow ID | Use case IDs | Path | Trigger | Numbered steps | Terminal evidence |
|---|---|---|---|---|---|
| D05-FLOW-01 | D05-UC-01 | Happy | Administrator saves an OIDC or SAML configuration, provisions Alice, and Alice signs in | 1. Validate issuer or entity ID, signing keys, exact callback or assertion-consumer-service endpoint, audience, and subject claim.<br>2. Apply the JIT or idempotent SCIM event to one Principal.<br>3. For OIDC, complete code plus PKCE and validate state, nonce, signature, issuer, audience, expiry, and authorized client; for SAML, validate conditions, correlation, and replay state.<br>4. Create a short platform session. | Evidence records Alice, provider configuration resource, authentication scope, precondition active provisioned principal, expected one admitted principal, observed session, environment, timestamp, configuration revision, provisioning event, trace, and immutable authentication-event ID |
| D05-FLOW-02 | D05-UC-02 | Denied | Alice selects Alpha and requests Beta board:42, which shares Alpha's local identifier | 1. Resolve current provider team membership rather than token groups.<br>2. Follow explicit Principal-to-AppSubject binding.<br>3. Derive app tenant and active membership server-side.<br>4. Apply tenant predicate at API and data layers.<br>5. Deny Beta and repeat Alpha as a positive control. | Evidence records Alice, requested board resource, Beta tenant scope, Alpha membership precondition, expected Beta deny and Alpha allow, observed results, environment, timestamp, subject-binding and membership IDs, policy version, and decision ID |
| D05-FLOW-03 | D05-UC-03 | Happy | Integration administrator provisions Marketing automation and the hosted runtime reads an approved source | 1. Register confidential workload and pin generated app, environment, and deployment.<br>2. Downstream authorization server issues minimal service grant.<br>3. Vault stores credential behind an opaque reference.<br>4. Bind connector version, operations, audience, and tenant to workload grant.<br>5. Run approved read, forbidden-resource probe, and human-token substitution probe. | Evidence records workload actor, connector and downstream resource, machine scopes, approved-grant precondition, expected read allow and two denies, observed results, environment, timestamp, workload-grant ID, and immutable probe-run ID |
| D05-FLOW-04 | D05-UC-04 | Recovery | Employee revokes an optional personal OAuth connection | 1. App reauthorizes current tenant, role, resource, and action.<br>2. Broker revokes provider consent and platform delegated grant.<br>3. Invalidate refresh-token family.<br>4. Attempt next user exchange and observe reauthorization required.<br>5. Probe app sign-in, app membership, SCIM state, and separate workload grant unchanged. | Evidence records employee, source resource, app-tenant and delegated scopes, precondition delegated grant active, expected delegation deny plus four unaffected controls, observed results, environment, timestamp, revocation version, and immutable trace ID |
The edge gateway should terminate Transport Layer Security (TLS), reject caller-supplied identity headers, validate stable token properties, rate-limit abuse, and call external authorization for business decisions. It should not decide access to a particular team or agent from a broad JWT role.
An illustrative normalized session token is short-lived and audience-bound:
{
"iss": "https://identity.platform.example",
"aud": "agent-control-plane",
"sub": "user_8472",
"org": "org_acme",
"membership_version": 39182,
"session_id": "session_3a40",
"auth_time": 1785527200,
"amr": ["pwd", "mfa"],
"exp": 1785527500
}
amr lists authentication methods, such as password and multi-factor authentication. The membership version is a staleness signal, not a membership grant; sensitive requests still resolve current state.
System design derived from the flows
If the gateway, membership service, and credential broker share one undifferentiated trust domain, a login token compromise can become an external-system compromise with no separately revocable boundary.
| Use case ID | Entry point | Responsible services | Authoritative store | Failure evidence |
|---|---|---|---|---|
| D05-UC-01 | Identity-provider configuration console, OIDC callback or SAML assertion-consumer endpoint, and SCIM endpoint | IdP Configuration Service validates metadata; Auth Broker verifies OIDC or SAML; JIT/SCIM Provisioner updates Principal; Session Service issues bounded platform session | Customer identity provider owns authentication; Identity Configuration and Principal stores owned by Enterprise Identity Service; platform Session Store owned by Session Service | oidc_state_mismatch, pkce_failed, saml_replay, invalid_issuer, duplicate_protocol_subject, provisioning_disabled, or account_inactive, with configuration, provisioning, and auth-event IDs |
| D05-UC-02 | Active-team selector and generated-app protected route | Membership Service resolves current org/team roles; Subject Binding Service maps Principal to app subject; generated-app Policy Enforcement Point and Policy Decision Point enforce tenant, role, resource, and action | Provider Membership Store owned by Membership Service; generated-app subject, tenant, membership, role, session, and domain stores owned by that generated application | team_not_in_organization, unbound_principal, synthetic_fixture_rejected, inactive_app_membership, or tenant_mismatch, with stable IDs and positive-control result |
| D05-UC-03 | Integration administration and connector broker workload endpoint | Connector Control Plane registers grant; Workload Verifier attests runtime; OAuth Broker obtains machine token; Vault stores secrets; Probe Runner tests downstream behavior | Connector Catalog and Workload Grant Store owned by Integration Control Plane; secret material owned by Vault; service grant and resource ACLs owned by downstream provider | invalid_workload_audience, missing_workload_grant, connector_version_mismatch, human_token_substitution, or failed negative probe, with grant and trace IDs |
| D05-UC-04 | Generated-app “Connect my account” and delegated token-exchange endpoints | App Session Verifier checks current app authority; Delegation Broker binds state and PKCE; OAuth Broker narrows user grant; Credential Proxy calls source without returning secret | Delegated Grant and Revocation stores owned by Integration Control Plane; consent, external subject, and resource ACLs owned by downstream provider | user_consent_missing, wrong_tenant, wrong_audience, wrong_source, refresh_reuse_detected, or credential_revoked, with delegated-grant and trace IDs |
Machine and human authority remain separate all the way down:
| Property | Team workload grant | User-delegated grant |
|---|---|---|
| Principal | Service account or confidential workload | Human external account plus current app subject |
| Typical flow | Client Credentials or administrative provider grant | Authorization Code with PKCE |
| Consent owner | Enterprise administrator and downstream administrator | Individual user plus enterprise policy |
| Scheduling | Durable when policy permits | Unsafe by default if tied to a departing user |
| Downstream audit | Service-account identity; platform must preserve initiating actor | Human external identity |
| Revocation | Team or organization administrator | User, provider, or organization administrator |
Generated applications own their authorization vocabulary. A Workboard may use Viewer, Editor, and Owner; a revenue dashboard may use RevenueReader and ForecastApprover; a public intake app may allow anonymous submission creation while denying anonymous read and mutation. Shared platform invariants are explicit tenant derivation, server-side policy, and negative tests—not one universal role catalogue.
Every generated-app query and mutation includes the server-derived tenant. A second data-layer predicate, such as row-level security or a constrained tenant-aware repository, independently limits rows. Tenant keys also scope caches, object prefixes, search filters, queues, subscriptions, idempotency keys, and background leases; matching local identifiers across tenants must not collide.
Data model and ownership
Copying identity-provider groups, OAuth tokens, and active-team choice into one mutable profile makes staleness invisible and causes deletion in one system to leave live authority in another.
Generated-application database: Required in this slice — the generated application owns app subjects, tenants, memberships, roles, sessions, and tenant-scoped domain predicates, while enterprise principals and connector grants remain in separately revocable stores.
| Record or entity | Store and owner | Primary key | Foreign key or opaque reference | Tenant key | Material constraint | Lifecycle and deletion | Use case IDs |
|---|---|---|---|---|---|---|---|
| IdentityProvider | Identity Configuration Store; Enterprise Identity Service | identity_provider_id | Opaque customer-organization reference | organization_id | Protocol, exact issuer or entity ID, audience, callback or assertion-consumer URI, subject claim, signing metadata, and issuer aliases require verified revisions | Disabled immediately; redacted revisions retained; secrets purged after policy window | D05-UC-01 |
| ExternalIdentity | Principal Store; Enterprise Identity Service | external_identity_id | Local foreign keys to IdentityProvider and Principal | organization_id | Unique on (identity_provider_id, protocol_subject) even with issuer aliases; email is never an identity key | Tombstoned on deprovision; stable subject hash and conflict audit retained; profile attributes deleted under policy | D05-UC-01 |
| Principal | Principal Store; Enterprise Identity Service | principal_id | Opaque organization reference | organization_id | One enterprise person or service principal per record; preview fixtures never auto-promote | Disabled on lifecycle removal; denial references retained; personal profile data later purged | D05-UC-01, D05-UC-02 |
| ProvisioningEvent | Provisioning Ledger; JIT/SCIM Provisioner | provisioning_event_id | Local references to IdentityProvider and Principal | organization_id | Idempotency key and source version prevent replay; provisioning success never implies login or app authority | Immutable outcome retained; payload attributes redacted or deleted by policy | D05-UC-01 |
| PlatformSession | Provider Session Store; Session Service | session_id | Local foreign key to Principal; opaque authentication-event reference | organization_id | Short expiry, bound client and authentication strength; contains no generated-app role | Created after validated exchange; rotated; revoked on logout/deprovision/risk event; expires and is deleted | D05-UC-01, D05-UC-02 |
| TeamMembership | Membership Store; Membership Service | (team_id, principal_id) | Local team reference; opaque Principal and SCIM source references | organization_id | One status and monotonic version per pair; principal and team must share organization | Provisioned and updated by admin or SCIM; revoke invalidates caches; audit tombstone retained before deletion | D05-UC-02 |
| ActiveTeamContext | Session Store; Session Service | (session_id, context_revision) | Local foreign key to PlatformSession; opaque team reference validated by Membership Service | organization_id | Exactly one selected primary team per protected operation; selection never unions roles | Created or revised by explicit selection; invalidated on membership change; expires with session | D05-UC-02 |
| AppSubjectBinding | Identity Binding Store; Subject Binding Service | subject_binding_id | Local Principal reference; opaque generated-app app_subject_id reference | organization_id plus app_id | Unique active (principal_id, app_id) binding; synthetic preview subjects cannot silently promote | Revoked independently; stable IDs tombstoned for audit; optional labels later purged | D05-UC-02 |
| AppSubject | Generated-app identity store; generated application | app_subject_id | Opaque subject_binding_id resolved by binding service | app_tenant_id | Tenant-bearing identity and fixture provenance mandatory | Disabled or deleted by app policy; tombstone retained while evidence depends on it | D05-UC-02 |
| AppTenant | Generated-app tenant store; generated application | app_tenant_id | Opaque customer-organization reference | app_tenant_id | Every role, domain resource, cache key, object prefix, job, and subscription carries tenant | Archived before deletion; export and retention complete before data and encryption-key destruction | D05-UC-02 |
| AppMembershipAndRoleBinding | Generated-app authorization store; generated application | membership_id and role_binding_id | Local references to AppSubject, AppTenant, and AppRole | app_tenant_id | Unique active subject-tenant membership; role and resource predicates cannot be satisfied by provider project roles | Revoked immediately; versioned policy history retained; archived or deleted by tenant policy | D05-UC-02 |
| AppSession | Generated-app session store; generated application | app_session_id | Opaque Principal and subject-binding references; local AppSubject and membership references | app_tenant_id | Hashed token material only; audience, policy version, expiry, and server-derived tenant mandatory | Expires or revokes on binding change; token hash purged after evidence retention | D05-UC-02, D05-UC-04 |
| ConnectorInstance | Connector Registry; Integration Control Plane | connector_instance_id | Opaque downstream provider and MCP server references | organization_id | Authentication mode and ownership scope immutable while active; team access explicit | Created by admin; disabled before deletion; bindings revoked; metadata retained for audit | D05-UC-03 |
| WorkloadGrant | Connector Grant Store; Integration Control Plane | workload_grant_id | Local ConnectorInstance and pinned connector-version references; opaque runtime workload reference | organization_id plus app_tenant_id | Non-human subject, app, environment, deployment, audience, operation, connector version, and expiry mandatory | Revoked independently; tombstoned grant and traces retained; secret destroyed and metadata later deleted | D05-UC-03 |
| DelegatedGrant | Delegation Store; Delegation Broker | delegated_grant_id | Local ConnectorInstance reference; opaque Principal, AppSubjectBinding, source-account, and Vault references | organization_id plus app_tenant_id | User, tenant, source, operation, audience, consent version, and bounded expiry mandatory | Expires or revokes independently; credential material destroyed immediately; tombstone retained for audit | D05-UC-04 |
| RevocationEvent | Append-only evidence store; Security Operations | revocation_event_id | Opaque target reference to session, binding, workload grant, or delegated grant | organization_id plus optional app_tenant_id | Monotonic target version and idempotency key prevent stale reactivation | Immutable redacted evidence retained and later archived or deleted under policy | D05-UC-02, D05-UC-03, D05-UC-04 |
| AuthenticationAndGrantEvent | Append-only evidence store; Audit Service | event_id | Opaque references to provider configuration, provisioning event, session, membership version, app binding, workload grant, delegated grant, probe run, and provider event | organization_id plus optional app_tenant_id | Allow, deny, revoke, and probe outcomes are immutable and carry actor, resource, scope, precondition, expected, observed, environment, timestamp, and immutable trace | Appended at decision time; sealed and retained; legal-hold aware archival and deletion | D05-UC-01, D05-UC-02, D05-UC-03, D05-UC-04 |
Secret material and metadata have different owners: Vault stores encrypted refresh tokens or client credentials, the OAuth Broker owns lifecycle and rotation state, and the downstream provider owns actual consent and resource permissions. Deleting metadata without revoking provider authority is incomplete recovery.
The evidence suite must falsify every tempting bridge: project member without app membership, app owner without provider-project membership, workload acting as a person, app session used as connector authority, wrong source or audience, same local resource ID in another tenant, and post-revocation reuse. Each denial is paired with an unaffected positive control so a broken environment cannot masquerade as correct isolation.
Implementation reviews should use the governing specifications: OpenID Connect Core 1.0 for ID-token and relying-party validation, RFC 9700 for current OAuth security practice, RFC 8693 for token exchange subject/actor/audience semantics, RFC 7644 for SCIM lifecycle operations, and SAML 2.0 Core for assertion conditions and protocol messages.