Raw .md
Core Protocols & SSO RFC Standard Updated Sep 23, 2026

Detailed specification of OAuth 2.0 authorization flows, PKCE, OpenID Connect 1.0 identity claims, and scopes.

OAuth 2.0 & OpenID Connect (OIDC)

Ternis Auth is a certified OAuth 2.0 (RFC 6749) and OpenID Connect 1.0 (OIDC) identity provider. It supports secure, token-based authorization for web applications, mobile apps, single-page applications (SPAs), and machine-to-machine services.


1. Supported Grant Types

Grant Type RFC Primary Use Case Requires Secret?
Authorization Code with PKCE RFC 7636 Web Apps (SSR), SPAs (React, Vue), and Mobile Apps. No (PKCE recommended)
Client Credentials RFC 6749 §4.4 Backend daemons, cron jobs, microservices. Yes
Refresh Token RFC 6749 §6 Renewing expired access tokens without user re-prompt. Depending on client type

2. Authorization Code Flow with PKCE

Proof Key for Code Exchange (PKCE, RFC 7636) prevents authorization code interception attacks and is strongly recommended for all clients.

Flow Diagram

[ User Browser ]         [ Client Application ]       [ Ternis Auth Server ]
       │                          │                             │
       │ ── 1. Click "Sign In" ─> │                             │
       │                          │ ── 2. Generate PKCE ──────> │
       │                          │    (code_verifier &         │
       │                          │     code_challenge)         │
       │ <── 3. Redirect to ───── │                             │
       │     /oauth/authorize     │                             │
       │                          │                             │
       │ ── 4. Prompt for Login & Consent ────────────────────> │
       │ <── 5. Redirect to client with auth ?code=... ──────── │
       │                          │                             │
       │ ── 6. Deliver Code ────> │                             │
       │                          │ ── 7. POST /oauth/token ──> │
       │                          │       (code + code_verifier)│
       │                          │ <── 8. Access & ID Token ── │

Step 1: Generate PKCE Parameters

In your application, generate a high-entropy cryptographically random string (code_verifier), then compute its URL-safe Base64-encoded SHA-256 hash (code_challenge):

// JavaScript (Web Crypto API)
function generateRandomString(length = 64) {
  const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
  const array = new Uint8Array(length);
  crypto.getRandomValues(array);
  return Array.from(array, byte => charset[byte % charset.length]).join('');
}

async function generateChallenge(verifier) {
  const data = new TextEncoder().encode(verifier);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return btoa(String.fromCharCode(...new Uint8Array(digest)))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

Step 2: Redirect User to Authorization Endpoint

GET /oauth/authorize?
  response_type=code
  &client_id=9dc6e84a-714c-4e89-9a29-bc828cf99874
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
  &scope=openid%20profile%20email%20ternis%3Asso
  &state=c3ab8ff13720e8ad9047dd39466b3c89
  &code_challenge=E9Melhoa2OwvFrGMTJguCH5rtG64DTb3Ag60-BIvJYA
  &code_challenge_method=S256
HTTP/1.1
Host: auth.ternis.net

Step 3: Exchange Code for Tokens

Once the user approves access, Ternis Auth redirects back to your redirect_uri with ?code=AUTHORIZATION_CODE&state=.... Your backend sends a POST request to the token endpoint:

POST /oauth/token HTTP/1.1
Host: auth.ternis.net
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=9dc6e84a-714c-4e89-9a29-bc828cf99874
&client_secret=CLIENT_SECRET_IF_CONFIDENTIAL
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&code=DEF_AUTHORIZATION_CODE
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Success Response:

{
  "token_type": "Bearer",
  "expires_in": 31536000,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...",
  "refresh_token": "def502008f1b6a378873ad8299a9a3b6...",
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

3. Scopes & Permissions Matrix

Scopes define the exact data and actions your application can access on behalf of the user:

Scope Category Description
openid OIDC Core Required for OpenID Connect identity assertion; returns sub (user UUID).
profile OIDC Core User's full name, username, avatar picture URL, and company affiliation.
email OIDC Core Verified primary email address.
ternis:sso Ecosystem SSO Allows cross-domain seamless single sign-on without secondary authentication.
ternis:member Membership Core team affiliation, organization badges, and internal workspace entitlements.
ternis:customer Billing Subscription status (starter, pro, enterprise), quotas, and SLA support tier.
ternis:partner Commercial B2B developer status, self-service OAuth client registration, and webhooks.
ternis:admin Administrative Full platform administrative management (restricted to internal Ternis staff).

4. OpenID Connect UserInfo (/oauth/userinfo)

Send the access token in the Authorization: Bearer <token> header to receive verified identity claims:

GET /oauth/userinfo HTTP/1.1
Host: auth.ternis.net
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...
Accept: application/json

Response Payload:

{
  "sub": "b2f6b897-4001-460d-8386-db93f1d8c1c4",
  "name": "Elena Rostova",
  "preferred_username": "elena.rostova",
  "email": "elena.rostova@ternis.org",
  "email_verified": true,
  "picture": "https://user.t-cdn.de/b2f6b897-4001-460d-8386-db93f1d8c1c4.png",
  "user_type": "ternis_member",
  "is_admin": false,
  "organization_ids": [
    "c8a7f920-5d61-41b3-a1f4-3d078be12884"
  ],
  "subscription_tier": "enterprise",
  "updated_at": "2026-09-17T18:00:00Z"
}

5. Refreshing Expired Tokens

When an access token expires, use the refresh_token grant to retrieve a fresh token without user interruption:

POST /oauth/token HTTP/1.1
Host: auth.ternis.net
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=9dc6e84a-714c-4e89-9a29-bc828cf99874
&client_secret=CLIENT_SECRET
&refresh_token=def502008f1b6a378873ad8299a9a3b6...