---
title: OAuth 2.0 & OpenID Connect (OIDC)
category: Core Protocols & SSO
order: 4
badge: RFC Standard
description: 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`):

```js
// 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

```http
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:

```http
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:
```json
{
  "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:

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

### Response Payload:
```json
{
  "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:

```http
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...
```
