Identity · OpenID Connect

Single sign-on, built in.

CodeB ships with its own OpenID Connect identity provider. Sign-in lives on every page: a button on the landing form gives joiners a verified-in-call badge, the same button on the SoftPhone PWA auto-registers their SIP identity, and admin + third-party apps (Nextcloud, custom RPs) all federate against the same per-tenant user database. Cookie-free, PKCE-only public clients or confidential clients with a secret — pick what fits.

OIDC is on by default. Discovery URL: https://<your-host>/.well-known/openid-configuration

Adding it to your own site? → Read the integration how-to · See the data flow

Platform integration guides
Nextcloud user_oidc · Social Login WordPress OpenID Connect Generic

What you get

Standards-based

OpenID Connect Core 1.0, Authorization Code flow with PKCE (S256), RS256-signed JWTs. Discovery per RFC 8414, JWKS per RFC 7517. Any RP that speaks OIDC will work.

OIDC Core 1.0

Cookie-free, honestly

No cookies anywhere — not session, not tracking. Sign-in across multiple RPs uses a signed, 30-minute, same-origin assertion in localStorage at the IdP origin: never sent to other sites, never used for cross-site tracking, cleared on logout. Per-tab access & refresh tokens live in sessionStorage and vanish when the tab closes. Full design on the data-flow page.

Privacy

One credential store

Sign-in reuses the same HA1 password hash your SIP softphones use. No plaintext password ever reaches the server — the browser hashes it before posting. One user record drives both voice and identity.

No duplicate users

Per-tenant keys

Each tenant gets its own 2048-bit RSA signing key, generated on first need and persisted to App_Data/<tenant>/oidc/. Tokens minted for tenant A never verify against tenant B.

Multi-tenant

Roles, not just identities

Four roles out of the box: admin, user, siponly, guest. The role travels in the JWT as a custom claim and as a standard groups entry. Per-user custom groups can be set in the admin UI to feed Nextcloud / RP membership directly into the token. Admin pages enforce role === "admin" server-side on every request.

RBAC

Verified-in-call badge

Sign in on the landing page before joining and your conference tile shows the amber CodeB shield to every participant. Anti-impersonation for free, no third-party identity provider, no Zoom-style verified-name extension required.

Anti-impersonation

Authentication factor in the token

Every id_token + access_token carries amr (RFC 8176) and acr. RPs see the actual factor — ["pwd"] for password, ["hwk","mfa"] for smart card via CP V2 — and can require step-up auth where it matters.

RFC 8176

Hot key rotation

Two signing keys can be active at once. Rename private-key.xmlprivate-key-previous.xml; the next request generates a fresh active key. JWKS publishes both, the kid in each token pins it to the right one. No IIS recycle, no dropped sessions.

Zero-downtime

Token revocation (RFC 7009)

POST a refresh token to /oidc.ashx?action=revoke to end a session immediately on the IdP side. Confidential clients authenticate with their secret; public clients revoke without auth. Always returns 200 to prevent token-validity enumeration.

Operator

CP V2 smart-card sign-on

Operators running Aloaha’s Credential Provider V2 can drop a trust key at App_Data/<tenant>/oidc/cp-v2-trust.xml and pass a signed assertion to /authorize — users skip the login form entirely and the issued tokens carry amr: ["hwk","mfa"].

Hardware factor

Integration guide

Adding CodeB sign-on to your own app takes a config block. The OIDC how-to walks through discovery, PKCE, token validation and refresh, with copy-paste samples in vanilla JS and Node/Express.

Developer

The endpoints

Standard OIDC URLs. RPs typically only need the discovery URL — everything else is auto-discovered.

EndpointPurpose
/.well-known/openid-configuration Discovery document. RFC 8414. Lists every other endpoint and the supported algorithms.
/.well-known/jwks.json JSON Web Key Set. RFC 7517. The tenant’s RSA public key, so any RP can verify signatures.
/oidc.ashx?action=authorize Authorization endpoint. Redirects to the login form, then back to the RP with an auth code.
/oidc.ashx?action=token Token endpoint. Exchanges the auth code (with PKCE verifier) for an access token, ID token, and refresh token.
/oidc.ashx?action=userinfo UserInfo endpoint. Returns the signed-in user’s sub, role, profile claims.
/oidc.ashx?action=end_session RP-initiated logout. Clears tokens client-side, redirects to post_logout_redirect_uri.

Wire up an RP in three lines

Any OIDC-compliant relying party works. Point it at the discovery URL, use the public client ID codeb-admin, and you’re done.

Issuer https://phone.codeb.io Client ID codeb-admin Client type public (PKCE-only, no secret) Redirect URI https://<your-rp>/oidc-callback Scope openid profile email PKCE method S256

The discovery document fills in authorization_endpoint, token_endpoint, jwks_uri, id_token_signing_alg_values_supported and the rest automatically.

What the ID token looks like

RS256-signed JWT. Standard OIDC claims plus a tenant-scoped role and any profile fields the admin filled in for that user.

{ "iss": "https://phone.codeb.io", "sub": "alice", "aud": "codeb-admin", "exp": 1748467200, "iat": 1748463600, "auth_time": 1748463600, "name": "Alice Walker", "preferred_username": "alice", "email": "alice@example.com", "email_verified": true, "role": "admin", "groups": ["admin"] }

Cookie-free, by design

OIDC implementations typically lean on a session cookie at the IdP to keep the user "signed in" across /authorize calls. CodeB doesn’t. The login form parses the original authorize URL, validates the PKCE challenge and redirect URI server-side, mints the auth code directly, and posts it back as JSON. The browser navigates to the RP’s callback without ever bouncing through a cookie-bearing redirect.

That keeps the privacy posture honest: no cookies anywhere on the CodeB site, OIDC included. If you advertise cookie-free, you stay cookie-free.

Multi-tenant from day one

Tenant identity is the request domain — same as the rest of CodeB. A user signing in at phone.acme.com hits the Acme RSA key and the Acme SIP credential file; a user at phone.contoso.com hits the Contoso key and the Contoso credentials. The two tenants share no state.

Adding a new tenant means adding a hostname. The first request to /oidc.ashx generates that tenant’s RSA key and persists it at App_Data/<tenant-domain>/oidc/private-key.xml. No schema migration, no restart, no downtime for the other tenants.

Operator notes

QuestionAnswer
How are passwords stored? As HA1 digests: MD5(user:realm:password). The plaintext password never reaches the server — the login form hashes it in the browser. Same HA1 your SIP softphones already use.
Where do user accounts live? App_Data/<tenant>/sip-credentials/<tenant-slug>.json. Manage them from the Register admin page.
Where does the private key live? App_Data/<tenant>/oidc/private-key.xml. Plain XML, not committed to source. Back it up with the rest of App_Data.
How do I rotate the key? Delete the file and recycle the IIS app pool. The next request regenerates a fresh key with a new kid. RPs re-fetch JWKS automatically.
Is there an audit log? Yes — App_Data/<tenant>/logs/codeb-oidc-YYYY-MM-DD.log (JSONL), and a parallel feed into the Windows Event Log under source CodeBOIDC.
How long do tokens live? Access tokens 1 hour. Refresh tokens 7 days. ID tokens 1 hour. Auth codes 60 seconds, single use.

Want the rest? All features →