This is an old revision of the document!
Table of Contents
SSO Flow Example: Mobile App, Server A, Server B, and SSO (OIDC + JWT + JWKS)
System Overview
We have 3 systems:
Mobile App (iOS / Android) Server A: crm.company.com Server B: orders.company.com SSO / Identity Provider: auth.company.com
Initial state:
Mobile App Token Storage = {}
(No cookies used in mobile flow)
Scenario 1: Login via Mobile App
Step 1: User opens Mobile App
User โ Mobile App No access_token yet
App detects user not logged in.
Step 2: App opens SSO login (system browser)
App โ opens browser โ https://auth.company.com/authorize
Includes:
client_id redirect_uri (deep link) response_type=code PKCE challenge
Step 3: User logs in
User enters:
username password MFA (optional)
SSO creates session:
SSO_SESSION=123
SSO sets cookie (browser only):
Set-Cookie: SSO_SESSION=123 Domain=auth.company.com
Step 4: Redirect back to Mobile App (Deep Link)
myapp://callback?code=abc
Browser closes โ control returns to app.
Step 5: Mobile App exchanges code
POST https://auth.company.com/token
Request includes:
code=abc code_verifier (PKCE) client_id
SSO returns:
access_token (JWT) id_token (JWT) refresh_token
๐ JWT SIGNING (SSO - PRIVATE KEY)
Inside SSO:
PRIVATE KEY โ signs JWT tokens (RS256)
SSO:
creates ID token creates Access token signs both with PRIVATE KEY
โ Only SSO has PRIVATE KEY โ Never exposed to apps or servers
๐ JWT VERIFICATION (Server A / Server B - PUBLIC KEY)
Server A / B validate token:
1. Fetch JWKS
GET https://auth.company.com/.well-known/jwks.json
2. Verify signature
SSO PUBLIC KEY โ verifies JWT
3. Validate claims
exp (expiration) iss (issuer) aud (audience)
If valid โ accept request
Step 6: Store tokens in Mobile App
access_token = eyJ... refresh_token = eyJ...
Stored in:
iOS Keychain Android Keystore
Scenario 2: Mobile App calls Server A
Step 7: Call Server A
Mobile App โ crm.company.com/api Authorization: Bearer access_token
Server A:
verifies JWT via JWKS checks signature + claims returns data
Scenario 3: Mobile App calls Server B
Step 8: Call Server B
Mobile App โ orders.company.com/api Authorization: Bearer access_token
Server B:
verifies JWT via JWKS trusts SSO identity returns data
๐ Token Refresh Flow
When access_token expires:
POST https://auth.company.com/token grant_type=refresh_token
SSO returns new access_token.
(No user login required again)
๐ JWT SIGNING (SSO - PRIVATE KEY)
Same as login:
PRIVATE KEY โ signs new access tokens
โ Central signing authority (SSO)
๐ JWT VERIFICATION (SERVERS - PUBLIC KEY)
Server A / B:
fetch JWKS verify JWT signature validate claims
No call to SSO per request
Final State
Mobile App stores:
access_token (JWT) refresh_token
Servers do NOT store sessions.
Key Architecture Insight
SSO is the ONLY system that: uses PRIVATE KEY signs JWT tokens
Applications: use PUBLIC KEY (JWKS) verify JWT signatures do NOT maintain server session per user
Mobile app: stores tokens securely (Keychain/Keystore) calls APIs directly
Cookies: NOT used in mobile flow
Final Interview One-liner
In mobile SSO (OIDC with PKCE), the app authenticates via system browser, receives an authorization code, exchanges it for JWT tokens via backend call, and then uses those tokens to directly call Server A and Server B. Each server independently verifies the JWT using JWKS without maintaining sessions or involving SSO per request.
