> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bbrands.io/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth & Identity (IdP)

> Centralized OAuth 2.1 / OpenID Connect identity provider for the B Brands holding. Authenticates users and machines across every platform from a single source of truth.

<Info>
  This section documents the **B Brands IdP** — the centralized authentication
  platform exposed through `auth.bbrands.io`. It is the single place where the
  holding proves **who a user is** and **whether they are enabled** for a given
  platform (ERP, CRM, analytics, future SaaS, partners).
</Info>

## What this is

The B Brands IdP is the holding's standard identity provider. Any platform —
existing or future — authenticates its users via **OAuth 2.1 / OpenID Connect**
against B Brands, instead of maintaining its own user database.

The protocol is handled by a **managed OAuth 2.1 / OIDC engine**, wrapped
entirely behind the per-environment `auth.*` origin. Clients never see the
underlying engine: client registration, identity lifecycle, audit and every
public endpoint live in the B Brands identity layer. The engine is a
replaceable implementation detail.

```mermaid theme={null}
flowchart LR
    subgraph clients["OAuth clients"]
        erp["ERP platform"]
        crm["CRM platform"]
        more["Future platforms"]
    end
    subgraph authorigin["auth.bbrands.io (identity origin)"]
        oauth["/api/v3/oauth/*"]
        wellknown["/.well-known/*"]
        consent["/oauth/consent (UI)"]
    end
    subgraph gateway["api.bbrands.io (API backend)"]
        impl["OAuth implementation"]
        exchange["/api/v3/oauth/exchange"]
        resource["Resource APIs (RBAC)"]
    end
    subgraph identity["Identity & governance"]
        am["Identity admin console<br/>(source of truth)"]
        supa["Managed OIDC engine<br/>(OAuth 2.1)"]
    end

    clients -->|OIDC| oauth
    clients -->|OIDC| wellknown
    oauth --> impl
    wellknown --> impl
    impl --> supa
    exchange --> am
    resource --> am
    supa --> am
```

## The golden rule: the IdP authenticates, it does not authorize

This is the single most important concept for every team integrating with the
IdP. Keep it in mind while reading the rest of the section.

<CardGroup cols={2}>
  <Card title="What the IdP does" icon="circle-check">
    Proves a user's **identity** (`sub`, `email`, profile), delivers their
    **business-account context** (`https://bbrands.io/profile`: primary
    account and its external system id) and whether they are **enabled** for a
    platform (`active` / `suspended` / `revoked`).
  </Card>

  <Card title="What the IdP does NOT do" icon="circle-xmark">
    It does not manage application permissions. Each client application decides
    what a user can do **inside it**. There is no central permission catalogue.
  </Card>
</CardGroup>

There are **two directions** of calls, treated differently:

<Steps>
  <Step title="A user signs into a client app via B Brands">
    The IdP only authenticates. The client app authorizes its own users with its
    own roles/groups.
  </Step>

  <Step title="A client app consumes the B Brands APIs">
    B Brands protects its own data with the existing internal RBAC. The client
    acts with an **internal B Brands JWT** obtained through the
    [token exchange](/oauth/token-exchange) (user context) or with an existing
    **API key** (machine-to-machine, no user).
  </Step>
</Steps>

<Warning>
  The OAuth ES256 token **never** reaches the B Brands business APIs. Those APIs
  keep validating the internal HS256 JWT exactly as they do today. The Resource
  Server does not change.
</Warning>

## Two token formats coexist

| Token                       | Algorithm                 | Issued by               | Consumed by                        | Carries                    |
| --------------------------- | ------------------------- | ----------------------- | ---------------------------------- | -------------------------- |
| **OAuth access / ID token** | ES256 (asymmetric, P-256) | IdP (engine + hook)     | The client app, validated via JWKS | Identity + account profile |
| **Internal B Brands JWT**   | HS256 (symmetric)         | Token exchange endpoint | B Brands Resource APIs             | User context for RBAC      |

The two never mix: **ES256 for identity towards clients**, **HS256 for consuming
the B Brands APIs**. See [Security](/oauth/security) for the full token model.

## Who should read what

<CardGroup cols={2}>
  <Card title="Integrators (new platform)" icon="plug" href="/oauth/client-integration">
    Configure your OAuth client, discovery, redirect URIs and (optionally) the
    token exchange to call B Brands APIs.
  </Card>

  <Card title="Backend / architects" icon="sitemap" href="/oauth/architecture">
    Component layers, the engine facade, ADRs and the access-token hook.
  </Card>

  <Card title="Backend / integrators" icon="code" href="/oauth/endpoints">
    The OAuth / OIDC endpoint contract: discovery, authorize, token, userinfo,
    revoke.
  </Card>

  <Card title="Security / compliance" icon="shield-halved" href="/oauth/security">
    Token model, secret management, threat model, revocation levels and audit.
  </Card>

  <Card title="Data / lifecycle" icon="database" href="/oauth/data-model">
    The identity entities, enablement lifecycle and the kill switch.
  </Card>

  <Card title="Frontend teams" icon="users" href="/oauth/social-login">
    The separate end-user social login through the managed engine.
  </Card>
</CardGroup>

## Environments

The IdP runs in multiple environments. Each has its own isolated engine, its own
issuer and its own registered OAuth clients. A token minted in one environment is
**never** valid in another, because clients validate the `iss` of their own
environment.

| Environment   | Canonical issuer (`iss`)                | Discovery URL                                                            |
| ------------- | --------------------------------------- | ------------------------------------------------------------------------ |
| Development   | `https://development.auth.bbrands.io`   | `https://development.auth.bbrands.io/.well-known/openid-configuration`   |
| Certification | `https://certification.auth.bbrands.io` | `https://certification.auth.bbrands.io/.well-known/openid-configuration` |
| Production    | `https://auth.bbrands.io`               | `https://auth.bbrands.io/.well-known/openid-configuration`               |

Every OAuth/OIDC surface — discovery, JWKS, authorize, token, userinfo, revoke
**and** the interactive consent/login UI — lives under the same per-environment
`auth.*` origin. That origin is the canonical issuer embedded in every issued
token.

<Note>
  A single user-facing identity origin, on purpose: **`auth.*`** is the
  canonical issuer and serves every protocol endpoint plus the consent UI
  (same shape as `accounts.google.com`). The `api.*` domain hosts the
  underlying implementation and the B Brands business APIs, but it is **not**
  the advertised issuer — clients only ever configure `auth.*`. See
  [Architecture](/oauth/architecture) for the decision record.
</Note>

## Client naming convention

OAuth client identifiers follow the `<platform>-<environment>` pattern, e.g.
`erp-prod`, `erp-cert`, `erp-dev`. Always register a distinct client per
environment.
