Building Type-Safe APIs with Nuxt 3 and Prisma
Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.
Demystify OAuth 2.0 flows, tokens, and OpenID Connect. Learn which flow to use for your app and how to implement it securely.
Mbeah Essilfie
May 28, 2026 at 06:03 AM
OAuth 2.0 answers: "How can App A access User's data on Service B, without User giving App A their password?"
The analogy: a hotel key card (token) grants access to specific rooms (scopes) for a limited time, without giving away the master key (password).
For server-rendered apps and SPAs with a backend:
1. User clicks "Login with Google"
2. App redirects to Google's auth endpoint
3. User logs in and consents
4. Google redirects back with an authorization CODE
5. App's backend exchanges code for tokens (server-to-server)
6. App receives access_token + refresh_token + id_token
// Step 2: Redirect to auth server
const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth')
authUrl.searchParams.set('client_id', CLIENT_ID)
authUrl.searchParams.set('redirect_uri', 'https://myapp.com/callback')
authUrl.searchParams.set('response_type', 'code')
authUrl.searchParams.set('scope', 'openid email profile')
authUrl.searchParams.set('state', generateRandomState()) // CSRF protection
// Step 5: Exchange code for tokens (backend)
const tokens = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
body: new URLSearchParams({
code: authorizationCode,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: 'https://myapp.com/callback',
grant_type: 'authorization_code',
}),
})
client_secret to the browser. The code-to-token exchange MUST happen server-side. For SPAs without a backend, use PKCE.// Generate a code verifier and challenge
const codeVerifier = generateRandomString(64)
const codeChallenge = base64url(sha256(codeVerifier))
// Include in auth request
authUrl.searchParams.set('code_challenge', codeChallenge)
authUrl.searchParams.set('code_challenge_method', 'S256')
// Include verifier in token exchange (proves you started the flow)
tokenRequest.set('code_verifier', codeVerifier)
OAuth 2.0 = Authorization (access to resources) OIDC = Authentication (who is the user?)
OIDC adds:
id_token — JWT with user identity claims/userinfo endpoint — Additional user dataopenid, email, profile// Decode the id_token (after verification!)
{
"sub": "110169484474386276334", // Unique user ID
"email": "mbeah@example.com",
"name": "Mbeah Essilfie",
"picture": "https://...",
"iss": "https://accounts.google.com",
"exp": 1700000000
}
| Token | Store Where | Lifetime |
|---|---|---|
| Access Token | Memory / httpOnly cookie | 5-60 min |
| Refresh Token | httpOnly cookie | Days-weeks |
| ID Token | Memory (for display only) | Same as access |
Never use the Implicit flow — it's deprecated for security reasons.
Fullstack Software Developer
Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.
Go beyond basic utility classes and learn how to build cohesive, maintainable design systems with Tailwind CSS.
Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.
