OIDC Client Types — Web, Mobile, and SPA Application Considerations
In this tutorial, you will learn about OIDC Client Types. We cover key concepts, practical examples, and best practices to help you master this topic.
OpenID Connect supports three client types: web applications (confidential clients), single-page applications (public clients), and native/mobile applications (public clients), each with distinct security considerations for authentication flows.
What You'll Learn
- The difference between confidential and public clients
- How to choose the right client type for your application
- Security best practices for each client type
Why It Matters
Choosing the wrong client type leads to security vulnerabilities. A SPA storing a client_secret in JavaScript exposes it to every user. A mobile app using the implicit grant without PKCE risks token interception. Understanding client type requirements prevents these issues.
Real-World Use
DodaBrowser (web app) uses the authorization code flow with PKCE as a public client. DodaAdmin (server-side web app) uses the authorization code flow with a client_secret as a confidential client. DodaMobile (iOS/Android) uses the authorization code flow with PKCE and uses the system browser for authentication.
flowchart TD
subgraph Confidential
C1["Web Server App\nclient_secret stored securely"]
end
subgraph Public
C2["SPA (JavaScript)\nNo client_secret, PKCE required"]
C3["Mobile App\nNo client_secret, PKCE required"]
end
C1 -->|"Authorization Code + Secret"| P["OIDC Provider"]
C2 -->|"Authorization Code + PKCE"| P
C3 -->|"Authorization Code + PKCE"| P
style C1 fill:#dbeafe,stroke:#2563eb
style C2 fill:#fef3c7,stroke:#d97706
style C3 fill:#bbf7d0,stroke:#16a34a
style P fill:#fecaca,stroke:#dc2626
Confidential Clients (Web Server Apps)
Confidential clients can securely store a client_secret because the code runs on a server:
import requests
from requests.auth import HTTPBasicAuth
# Token exchange with client_secret
token_response = requests.post(
"https://accounts.example.com/token",
auth=HTTPBasicAuth("client_id", "client_secret"),
data={
"grant_type": "authorization_code",
"code": "auth_code_here",
"redirect_uri": "https://doda.example.com/callback"
}
)
Public Clients (SPAs and Mobile Apps)
Public clients cannot securely store secrets. They must use PKCE (Proof Key for Code Exchange):
// SPA: Generate PKCE challenge
async function generatePKCE() {
const verifier = generateRandomString(64);
const challenge = await sha256(verifier);
const challengeB64 = btoa(String.fromCharCode(...new Uint8Array(challenge)))
.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
// Store verifier in session storage
sessionStorage.setItem('pkce_verifier', verifier);
return challengeB64;
}
function generateRandomString(length) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
Redirect URI Validation
Each client type has different redirect URI requirements:
# Web app: exact match
redirect_uris_web = [
"https://doda.example.com/callback",
"https://doda.example.com/auth/callback"
]
# Mobile app: custom scheme or loopback
redirect_uris_mobile = [
"com.doda.browser:/callback", # Custom scheme
"http://localhost:8080/callback" # Loopback
]
# SPA: HTTP scheme only, no fragment
redirect_uris_spa = [
"https://doda.example.com/callback",
"https://doda.example.com/auth"
]
Common Mistakes
1. Using client_secret in SPAs
A client_secret in JavaScript source code is visible to every user. Never embed secrets in client-side code. Use PKCE instead.
2. Using Implicit Grant for New Applications
The implicit grant is deprecated. All client types should use the authorization code flow with PKCE.
3. Not Registering Custom Scheme URIs for Mobile
Mobile apps using custom scheme redirect URIs must register them with the OS to prevent other apps from intercepting the callback.
4. Using HTTP Redirect URIs in Production
SPAs must use HTTPS redirect URIs. HTTP is only acceptable for local development with loopback addresses.
5. Forgetting Universal Link Support on iOS
For production iOS apps, use universal links instead of custom schemes for more secure redirects that cannot be intercepted.
Practice Questions
- What is the difference between confidential and public clients?
- Why do mobile apps need PKCE?
- What redirect URI scheme should a mobile app use?
- Can a SPA securely store a client_secret?
- Which flow should all client types use?
Answers
- Confidential clients can store secrets server-side; public clients cannot. 2. Mobile apps cannot securely store secrets, so PKCE prevents authorization code interception. 3. Custom scheme or loopback localhost URI. 4. No, it is visible to all users. 5. Authorization code flow with PKCE.
Challenge
Build a client type detector that analyzes a configuration file and recommends the appropriate OIDC client type, redirect URI format, token storage Strategy, and authentication flow based on the application platform and architecture.
FAQ
Mini Project
Create a configuration generator that accepts application type (web, mobile, SPA) and returns a complete OIDC client registration JSON with the correct metadata, redirect URIs, token endpoint auth method, and flow type for each platform.
What's Next
- Learn about OIDC security best practices for production deployments
- Explore popular OIDC providers and how they differ
- Continue to OIDC testing strategies for reliable authentication
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro