security:sso-mobile
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| security:sso-mobile [2026/06/16 05:58] – [PKCE FLOW (COMMON LOGIC)] phong2018 | security:sso-mobile [2026/06/16 07:08] (current) – phong2018 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== | + | ====== OIDC SSO System: Mobile |
| - | ===== System Overview ===== | + | **Version: |
| + | **Date:** 2026-06-16 \\ | ||
| + | **Audience: | ||
| - | We have: | + | ---- |
| - | SPA Client: vue-app.com | + | ===== Table of Contents ===== |
| - | Mobile App: iOS / Android | + | - [[# |
| + | - [[# | ||
| + | - [[# | ||
| + | - [[# | ||
| + | - [[# | ||
| + | - [[# | ||
| + | - [[# | ||
| + | - [[# | ||
| + | - [[# | ||
| - | Server A: crm.company.com | + | ---- |
| - | Server B: orders.company.com | + | ===== Overview ===== {{anchor:overview}} |
| - | SSO / Identity Provider: auth.company.com | + | This document describes a complete **OpenID Connect (OIDC) Single Sign-On (SSO)** system |
| + | designed for a mobile application that communicates with two backend resource servers. | ||
| - | SSO is the central authentication authority. | + | The system uses: |
| + | * **PKCE** (Proof Key for Code Exchange) — prevents authorization code interception on mobile | ||
| + | * **JWT** (JSON Web Token) — compact, self-contained token format | ||
| + | * **JWKS** (JSON Web Key Set) — public key endpoint for token signature verification | ||
| + | * **OIDC** — identity layer on top of OAuth 2.0 | ||
| - | ===== Key Concepts ===== | + | ---- |
| - | SSO responsibilities: | + | ===== Architecture & Components ===== {{anchor:architecture}} |
| - | User authentication (login) | + | ==== Component List ==== |
| - | Authorization code issuance | + | |
| - | JWT token issuance | + | |
| - | Signing tokens with private key | + | |
| - | Applications responsibilities: | + | ^ Component |
| + | | **Mobile App** | End-user client. Initiates auth, holds tokens, calls resource servers. | ||
| + | | **ServerSSO** | ||
| + | | **ServerA** | ||
| + | | **ServerB** | ||
| - | Exchange authorization code (if applicable) | + | ==== Network Overview ==== |
| - | Verify JWT using public key (JWKS) | + | |
| - | Manage local session (optional) | + | |
| - | ===== 🔐 Cryptography Model ===== | + | < |
| + | ┌─────────────┐ | ||
| + | │ Mobile App │ ◄──────────────────────────► │ | ||
| + | └──────┬──────┘ | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | </ | ||
| - | SSO (Identity Provider): | + | > **Note:** ServerA and ServerB never contact ServerSSO during normal request validation. |
| + | > They verify JWT signatures locally using the public keys fetched from the JWKS endpoint. | ||
| - | < | + | ---- |
| - | Applications (Server A / B): | + | ===== Key Concepts ===== {{anchor:key-concepts}} |
| - | < | + | ==== PKCE Flow (Mobile-Specific) ==== |
| - | ===== ========================= ===== | + | PKCE prevents **authorization code interception attacks** that are common on mobile platforms |
| - | ===== CLIENT TYPES (IMPORTANT) ===== | + | (because redirect URIs on mobile can be hijacked by malicious apps). |
| - | ===== ========================= ===== | + | |
| - | There are 3 types of clients: | + | ^ Step ^ PKCE Parameter |
| + | | 1 | ``code_verifier`` | ||
| + | | 2 | ``code_challenge`` | ||
| + | | 3 | Auth request | ||
| + | | 4 | Token exchange | ||
| - | ==== 1. Confidential Client (Server-side Web App) ==== | + | ==== JWT Structure |
| - | Example: | + | A JWT has three parts separated by dots: ``header.payload.signature`` |
| - | Laravel | + | <code json> |
| + | // Header | ||
| + | { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| - | Flow: | + | // Payload (claims) |
| + | { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| - | Backend exchanges code | + | // Signature: RS256(base64url(header) + " |
| - | Backend stores session cookie | + | </ |
| - | ==== 2. Public Client (SPA) ==== | + | ==== JWKS Endpoint |
| - | Example: | + | ServerSSO exposes a public endpoint: |
| - | Vue.js / React.js | + | < |
| + | GET https://sso.example.com/.well-known/ | ||
| + | </ | ||
| - | Flow: | + | Response: |
| - | Browser exchanges | + | <code json> |
| - | Uses PKCE | + | { |
| - | Stores JWT | + | " |
| + | { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | ] | ||
| + | } | ||
| + | </ | ||
| - | ==== 3. Public Client (Mobile App) ==== | + | ServerA and ServerB **cache** this response and use it to verify JWT signatures |
| + | without calling ServerSSO on every request. | ||
| - | Example: | + | ==== OIDC Discovery Document ==== |
| - | iOS / Android apps | + | ServerSSO also exposes: |
| - | Flow: | + | < |
| + | GET https:// | ||
| + | </ | ||
| - | App uses system browser login | + | This returns all endpoint URLs (authorization, |
| - | Uses PKCE | + | |
| - | Stores JWT in secure storage | + | |
| - | ===== ========================= ===== | + | ---- |
| - | ===== PKCE FLOW (Proof Key for Code Exchange) ===== | + | |
| - | ===== ========================= ===== | + | |
| - | Used by SPA + Mobile. | + | ===== Scenario 1 — Not Authenticated (First Login) ===== {{anchor: |
| - | ===== Step 1: Generate PKCE ===== | + | This scenario covers the **complete first-time login flow** from scratch. |
| - | Client generates: | + | ==== Step-by-Step ==== |
| - | < | + | === Step 1: Mobile App — Generate PKCE Parameters === |
| - | Then derives: | + | The app generates cryptographic values **locally**, |
| - | < | + | < |
| + | code_verifier | ||
| + | e.g. " | ||
| - | ===== Step 2: Redirect to SSO ===== | + | code_challenge |
| + | e.g. " | ||
| - | < | + | state = base64url( random_bytes(16) ) // CSRF protection |
| + | nonce = base64url( random_bytes(16) ) // replay protection | ||
| + | </ | ||
| - | Parameters: | + | The app stores ``code_verifier``, |
| - | response_type=code | + | === Step 2: Mobile App → ServerSSO — Authorization Request === |
| - | client_id | + | |
| - | redirect_uri | + | |
| - | code_challenge | + | |
| - | code_challenge_method=S256 | + | |
| - | state | + | |
| - | ===== Step 3: User Login ===== | + | The app opens the system browser (or in-app browser tab) and navigates to: |
| - | User authenticates: | + | < |
| + | GET https:// | ||
| + | ? | ||
| + | & | ||
| + | & | ||
| + | & | ||
| + | & | ||
| + | & | ||
| + | & | ||
| + | & | ||
| + | </ | ||
| - | username/password | + | ^ Parameter |
| - | MFA optional | + | | ``response_type`` |
| + | | ``client_id`` | ||
| + | | ``redirect_uri`` | ||
| + | | ``scope`` | ||
| + | | ``state`` | ||
| + | | ``nonce`` | ||
| + | | ``code_challenge`` | ||
| + | | ``code_challenge_method``| ``S256`` | ||
| - | SSO creates session: | + | === Step 3: ServerSSO — Authenticate the User === |
| - | < | + | ServerSSO presents the **login page** (username/password, MFA, social login, etc.). |
| - | SSO sets cookie | + | The user authenticates successfully. ServerSSO: |
| + | - Validates the PKCE challenge parameters | ||
| + | - Creates a server-side session | ||
| + | - Generates a short-lived **authorization code** | ||
| - | < | + | === Step 4: ServerSSO → Mobile App — Authorization Code Redirect === |
| - | ===== Step 4: Authorization Code Returned ===== | + | ServerSSO redirects the browser to the app's deep link: |
| - | < | + | < |
| + | myapp:// | ||
| + | | ||
| + | | ||
| + | </ | ||
| - | ✔ code is short-lived | + | The app: |
| - | ✔ code is one-time use | + | |
| + | - **Validates** that ``state`` matches what was stored in Step 1 (CSRF check) | ||
| + | - Extracts the ``code`` | ||
| - | ===== Step 5: Code Exchange | + | === Step 5: Mobile App → ServerSSO — Token Exchange |
| - | ==== SPA / Mobile ==== | + | The app makes a **back-channel** (direct HTTPS) POST request: |
| - | < | + | < |
| + | POST https://sso.example.com/token | ||
| + | Content-Type: | ||
| - | Request: | + | grant_type=authorization_code |
| + | & | ||
| + | & | ||
| + | & | ||
| + | & | ||
| + | </ | ||
| - | <code> code=abc | + | > **Critical: |
| + | > ServerSSO recomputes SHA256(code_verifier) and compares it to the stored ``code_challenge``. | ||
| + | > If they match, the exchange is authorized. This **proves** the requester is the same | ||
| + | > entity that started the flow — defeating code interception attacks. | ||
| - | ==== Server-side Web App ==== | + | === Step 6: ServerSSO → Mobile |
| - | < | + | ServerSSO responds with: |
| - | ===== 🔐 PKCE VERIFICATION ===== | + | <code json> |
| + | { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | </ | ||
| - | SSO performs: | + | ^ Token ^ Purpose |
| + | | ``access_token`` | Sent to ServerA / ServerB as Bearer token | Secure memory only | | ||
| + | | ``id_token`` | ||
| + | | ``refresh_token``| Used to get new access_token when expired | ||
| - | < | + | The app **validates the id_token**: |
| + | - Fetch JWKS from ``https:// | ||
| + | - Verify RS256 signature using the public key matching ``kid`` | ||
| + | - Check ``iss``, ``aud``, ``exp``, and ``nonce`` | ||
| - | Compare: | + | === Step 7: Mobile App → ServerA — API Request with JWT === |
| - | < | + | < |
| + | GET https:// | ||
| + | Authorization: | ||
| + | </ | ||
| - | ✔ match → valid | + | === Step 8: ServerA — JWT Validation (Local, No SSO Call) === |
| - | ❌ mismatch → reject | + | |
| - | ===== ========================= ===== | + | ServerA validates the JWT **entirely locally**: |
| - | ===== JWT ISSUANCE ===== | + | |
| - | ===== ========================= ===== | + | |
| - | SSO returns: | + | < |
| + | 1. Parse JWT header → extract " | ||
| + | 2. Look up public key in local JWKS cache by kid | ||
| + | (If not cached: fetch https:// | ||
| + | 3. Verify RS256 signature using the RSA public key | ||
| + | 4. Validate claims: | ||
| + | - exp > now() → not expired | ||
| + | - iss == " | ||
| + | - aud contains " | ||
| + | 5. Extract sub, roles, email from payload | ||
| + | 6. Apply authorization rules | ||
| + | 7. Return API response | ||
| + | </ | ||
| - | < | + | === Step 9: Mobile App → ServerB — API Request with Same JWT === |
| - | ===== 🔐 JWT SIGNING (SSO SIDE) ===== | + | The **same access_token** is reused for ServerB: |
| - | < | + | < |
| + | GET https:// | ||
| + | Authorization: | ||
| + | </ | ||
| - | ✔ only SSO has private key | + | ServerB performs identical JWT validation (Steps 8.1–8.6) — this is the **SSO benefit**: one |
| - | ✔ tokens cannot be forged | + | authentication, |
| - | ===== ========================= ===== | + | ==== Scenario 1 — Summary Flow ==== |
| - | ===== JWT VERIFICATION ===== | + | |
| - | ===== ========================= ===== | + | |
| - | Servers | + | < |
| + | Mobile App ServerSSO | ||
| + | │ | ||
| + | │─ Generate PKCE ──►│ | ||
| + | │ code_verifier | ||
| + | │ code_challenge | ||
| + | │ | ||
| + | │── GET /authorize ─►│ | ||
| + | │ (code_challenge) │ │ │ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | │◄── redirect ──────│ | ||
| + | │ ? | ||
| + | │ & | ||
| + | │ | ||
| + | │── POST /token ────►│ | ||
| + | │ | ||
| + | │ │ verify: SHA256( | ||
| + | │ | ||
| + | │ │ == code_challenge | ||
| + | │ | ||
| + | │◄── access_token ──│ | ||
| + | │ id_token | ||
| + | │ refresh_token | ||
| + | │ | ||
| + | │── GET /api/data ──────────────────────►│ | ||
| + | │ | ||
| + | │ | ||
| + | │◄── 200 response ──────────────────────►│ | ||
| + | │ | ||
| + | │── GET /api/res ────────────────────────────────────────►│ | ||
| + | │ | ||
| + | │◄── 200 response ────────────────────────────────────────│ (JWKS cache) | ||
| + | │ | ||
| + | </ | ||
| - | ==== Step 1: Fetch JWKS ==== | + | ---- |
| - | < | + | ===== Scenario 2 — Already Authenticated (SSO Token Reuse) ===== {{anchor:scenario2}} |
| - | ==== Step 2: Verify signature ==== | + | This scenario covers the case where the user **already has a valid session** or |
| + | the app has a **cached refresh_token** and needs a new access_token. | ||
| - | < | + | ==== Sub-Scenario 2a: Valid Access Token Still in Memory ==== |
| - | ==== Step 3: Validate claims ==== | + | The simplest case: the app already holds a non-expired ``access_token``. |
| - | exp (expiration) | + | === Step 1: Mobile App — Check Token Expiry === |
| - | iss (issuer) | + | |
| - | aud (audience) | + | |
| - | sub (user id) | + | |
| - | ✔ valid → allow request | + | Before making any API call, the app checks locally: |
| - | ❌ invalid → reject | + | |
| - | ===== ========================= ===== | + | < |
| - | ===== SPA FLOW ===== | + | decoded |
| - | ===== ========================= ===== | + | now = current_unix_timestamp() |
| - | ==== Step 1 ==== | + | if decoded.exp > now + 30: // 30-second buffer |
| + | // Token is still valid — use it directly | ||
| + | proceed_to_step_2() | ||
| + | else: | ||
| + | // Token expired or about to expire — refresh it (Sub-Scenario 2b) | ||
| + | refresh_access_token() | ||
| + | </ | ||
| - | User opens SPA: | + | === Step 2: Mobile App → ServerA / ServerB — API Request === |
| - | < | + | Identical to Scenario 1 Steps 7–9. The app reuses the cached ``access_token``: |
| - | ==== Step 2 ==== | + | < |
| + | GET https:// | ||
| + | Authorization: | ||
| + | </ | ||
| - | Generate PKCE → redirect to SSO | + | No interaction with ServerSSO is needed. ✓ |
| - | ==== Step 3 ==== | + | ---- |
| - | Receive code → exchange via browser JS | + | ==== Sub-Scenario 2b: Access Token Expired — Refresh Flow ==== |
| - | ==== Step 4 ==== | + | The ``access_token`` has expired, but the app holds a valid ``refresh_token``. |
| - | Store access_token | + | === Step 1: Mobile App → ServerSSO — Refresh Token Request === |
| - | ==== Step 5 ==== | + | < |
| + | POST https:// | ||
| + | Content-Type: | ||
| - | Call APIs: | + | grant_type=refresh_token |
| + | & | ||
| + | & | ||
| + | </ | ||
| - | <code> Authorization: Bearer JWT </code> | + | > **Note:** No PKCE is required for the refresh grant — PKCE was only needed |
| + | > for the initial authorization | ||
| - | ===== ========================= ===== | + | === Step 2: ServerSSO — Validate Refresh Token === |
| - | ===== MOBILE FLOW ===== | + | |
| - | ===== ========================= ===== | + | |
| - | ==== Step 1 ==== | + | ServerSSO checks: |
| + | - Refresh token exists in its database and is not revoked | ||
| + | - Refresh token has not expired (typically 30 days for mobile apps) | ||
| + | - ``client_id`` matches | ||
| - | App opens system browser: | + | If valid, ServerSSO **rotates** the refresh token (issues a new one, invalidates the old one). |
| - | < | + | === Step 3: ServerSSO → Mobile App — New Tokens === |
| - | ==== Step 2 ==== | + | <code json> |
| + | { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | </ | ||
| - | Login → SSO session created | + | The app stores the **new** ``refresh_token`` and **new** ``access_token``. |
| - | ==== Step 3 ==== | + | === Step 4: Mobile App → ServerA / ServerB — API Request |
| - | Redirect via deep link: | + | The app proceeds with the freshly issued ``access_token``. |
| - | < | + | < |
| + | GET https://serverA.example.com/ | ||
| + | Authorization: | ||
| + | </ | ||
| - | ==== Step 4 ==== | + | ---- |
| - | App exchanges code using PKCE | + | ==== Sub-Scenario 2c: Both Tokens Expired — Re-Authentication ==== |
| - | ==== Step 5 ==== | + | If the ``refresh_token`` has also expired (e.g., user was inactive for 30+ days): |
| - | Store token in: | + | === Step 1: Mobile App — Detect Expired Refresh Token === |
| - | iOS Keychain | + | The token endpoint returns: |
| - | Android Keystore | + | |
| - | ===== ========================= ===== | + | <code json> |
| - | ===== SERVER-SIDE WEB FLOW ===== | + | HTTP 400 Bad Request |
| - | ===== ========================= ===== | + | { |
| + | " | ||
| + | " | ||
| + | } | ||
| + | </ | ||
| - | ==== Step 1 ==== | + | === Step 2: Check for Existing SSO Session (Silent Auth) === |
| - | Browser → Server A | + | Before forcing a full re-login, the app attempts **silent authentication**: |
| - | ==== Step 2 ==== | + | < |
| + | GET https:// | ||
| + | ? | ||
| + | & | ||
| + | & | ||
| + | &scope=openid profile email offline_access | ||
| + | &prompt=none ← key parameter: no UI shown | ||
| + | & | ||
| + | & | ||
| + | &state=< | ||
| + | </ | ||
| - | Server A redirects to SSO | + | * If ServerSSO has a **valid browser/SSO session** (cookie): it returns a new ``code`` immediately — no login prompt → proceed with token exchange (Scenario 1, Steps 5–6) |
| + | * If no session exists: ServerSSO returns ``error=login_required`` → app must show login UI → full Scenario 1 from Step 2 | ||
| - | ==== Step 3 ==== | + | ==== Scenario 2b — Summary Flow ==== |
| - | Server A exchanges | + | <code> |
| + | Mobile App ServerSSO | ||
| + | │ | ||
| + | │ [access_token expired, refresh_token valid] | ||
| + | │ | ||
| + | │── POST /token ────►│ | ||
| + | │ | ||
| + | │ | ||
| + | │ │ validate RT | ||
| + | │ │ rotate RT | ||
| + | │◄── new tokens ────│ | ||
| + | │ access_token | ||
| + | │ refresh_token | ||
| + | │ (rotated) | ||
| + | │ | ||
| + | │── GET /api/data ──────────────────────►│ | ||
| + | │ | ||
| + | │◄── 200 OK ─────────────────────────────│ | ||
| + | │ | ||
| + | │── GET /api/res ────────────────────────────────────────►│ | ||
| + | │ | ||
| + | │◄── 200 OK ──────────────────────────────────────────────│ | ||
| + | </ | ||
| - | ==== Step 4 ==== | + | ---- |
| - | Server A creates session: | + | ===== Token Validation with JWKS (ServerA & ServerB Detail) ===== {{anchor:token-validation}} |
| - | < | + | ==== JWKS Caching Strategy ==== |
| - | ===== ========================= ===== | + | Resource servers should **not** fetch JWKS on every request. Recommended strategy: |
| - | ===== KEY SECURITY MODEL ===== | + | |
| - | ===== ========================= ===== | + | |
| - | SSO: | + | ^ Condition |
| + | | Startup | ||
| + | | JWT ``kid`` found in cache | Use cached key — no network call | | ||
| + | | JWT ``kid`` **not** found in cache | Fetch JWKS again (key rotation may have occurred) | ||
| + | | Cache age > 1 hour | Refresh JWKS in background | ||
| + | | JWKS fetch fails | Use stale cache; log warning; retry with backoff | ||
| - | issues authorization code | + | ==== JWT Validation Algorithm (Pseudocode) ==== |
| - | signs JWT with PRIVATE KEY | + | |
| - | Clients: | + | < |
| + | function validateJWT(token, | ||
| - | SPA/Mobile generate PKCE | + | |
| - | Server-side exchanges code | + | |
| + | header | ||
| + | payload | ||
| + | |||
| + | // 2. Look up the signing key | ||
| + | kid = header.kid | ||
| + | key = jwksCache.get(kid) | ||
| + | if key is null: | ||
| + | jwksCache.refresh() | ||
| + | key = jwksCache.get(kid) | ||
| + | if key is null: | ||
| + | throw InvalidTokenError(" | ||
| - | Servers: | + | // 3. Verify signature |
| + | message | ||
| + | if NOT RSA_SHA256_verify(message, | ||
| + | throw InvalidTokenError(" | ||
| - | verify JWT using PUBLIC KEY (JWKS) | + | // 4. Validate standard claims |
| - | remain stateless | + | if payload.exp < now(): |
| + | throw InvalidTokenError(" | ||
| + | if payload.iss != " | ||
| + | throw InvalidTokenError(" | ||
| + | if audience NOT IN payload.aud: | ||
| + | throw InvalidTokenError(" | ||
| + | if payload.nbf is set AND payload.nbf > now(): | ||
| + | throw InvalidTokenError(" | ||
| - | ===== ========================= ===== | + | // 5. Extract and return user context |
| - | ===== KEY INSIGHT ===== | + | |
| - | ===== ========================= ===== | + | </ |
| - | PKCE protects authorization code interception | + | ==== Key Rotation ==== |
| - | JWT ensures stateless authentication | + | |
| - | JWKS enables distributed verification | + | |
| - | SSO is single source of identity | + | |
| - | ===== ========================= ===== | + | When ServerSSO rotates its signing key: |
| - | ===== FINAL INTERVIEW SUMMARY ===== | + | |
| - | ===== ========================= ===== | + | |
| - | OAuth2/ | + | - New JWTs are signed |
| + | - Old JWTs remain valid until they expire (old key stays in JWKS temporarily) | ||
| + | - ServerA/ | ||
| + | - No downtime or coordination required | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Security Notes ===== {{anchor: | ||
| + | |||
| + | ==== Token Storage on Mobile ==== | ||
| + | |||
| + | ^ Token ^ Recommended Storage | ||
| + | | access_token | ||
| + | | refresh_token | ||
| + | | id_token | ||
| + | |||
| + | ==== PKCE Requirements ==== | ||
| + | |||
| + | * ``code_verifier``: | ||
| + | * Always use ``S256`` | ||
| + | * Generate a **new** ``code_verifier`` for every authorization request | ||
| + | * Never reuse or persist ``code_verifier`` across sessions | ||
| + | |||
| + | ==== Redirect URI Security ==== | ||
| + | |||
| + | * Register **exact** redirect URIs in ServerSSO (no wildcards) | ||
| + | * Use **private-use URI schemes** (e.g., ``com.example.myapp:// | ||
| + | * Always validate ``state`` parameter | ||
| + | |||
| + | ==== Access Token Lifetime Recommendations ==== | ||
| + | |||
| + | ^ Token ^ Recommended Lifetime ^ Notes ^ | ||
| + | | access_token | ||
| + | | refresh_token | ||
| + | | id_token | ||
| + | |||
| + | ==== HTTPS Enforcement ==== | ||
| + | |||
| + | All endpoints (authorization, | ||
| + | Certificate pinning is recommended for the mobile app in high-security environments. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Glossary ===== {{anchor: | ||
| + | |||
| + | ^ Term ^ Definition | ||
| + | | OIDC | OpenID Connect — identity layer on top of OAuth 2.0 | | ||
| + | | OAuth 2.0 | Authorization framework; OIDC extends it with identity (id_token) | | ||
| + | | PKCE | Proof Key for Code Exchange — RFC 7636; prevents code interception on mobile | ||
| + | | JWT | JSON Web Token — RFC 7519; compact, URL-safe token format | ||
| + | | JWKS | JSON Web Key Set — RFC 7517; public key set exposed by the auth server | ||
| + | | access_token | ||
| + | | id_token | ||
| + | | refresh_token | ||
| + | | code_verifier | ||
| + | | code_challenge | ||
| + | | authorization code | Short-lived, | ||
| + | | kid | Key ID — identifies which key in the JWKS was used to sign a JWT | | ||
| + | | SSO | Single Sign-On — one authentication | ||
| + | | Bearer token | HTTP authentication scheme; token is presented as-is in the Authorization header | | ||
| + | | RS256 | RSA Signature with SHA-256; asymmetric signing algorithm for JWTs | | ||
| + | |||
| + | ---- | ||
| + | |||
| + | //Document maintained by the Platform Security Team. Last updated: 2026-06-16// | ||
security/sso-mobile.1781589528.txt.gz · Last modified: by phong2018
