SiamCafe.net Blog
Technology

OpenID Connect Interview Preparation

openid connect interview preparation
OpenID Connect Interview Preparation | SiamCafe Blog
2025-09-19· อ. บอม — SiamCafe.net· 8,412 คำ

OpenID Connect

OpenID Connect OIDC OAuth 2.0 Authentication ID Token JWT Authorization Code Flow PKCE SSO Login Google Apple Auth0 Okta Keycloak Interview Preparation

ProtocolPurposeTokenStandardUse Case
OpenID ConnectAuthenticationID Token (JWT)OIDC 1.0Login SSO
OAuth 2.0AuthorizationAccess TokenRFC 6749API Access
SAML 2.0Auth + AuthZSAML AssertionOASISEnterprise SSO
JWTToken FormatSigned JSONRFC 7519Stateless Token
PKCESecurityCode VerifierRFC 7636SPA Mobile

Authorization Code Flow

# === OIDC Authorization Code Flow ===

# Flow Diagram:
# 1. User clicks "Login"
# 2. Browser → Authorization Server (GET /authorize)
#    ?response_type=code
#    &client_id=my-app
#    &redirect_uri=https://app.example.com/callback
#    &scope=openid profile email
#    &state=random-csrf-token
#    &code_challenge=SHA256(verifier)  # PKCE
#    &code_challenge_method=S256
#
# 3. User logs in + consents
# 4. Authorization Server → Browser (302 Redirect)
#    https://app.example.com/callback?code=AUTH_CODE&state=random-csrf-token
#
# 5. Backend → Token Endpoint (POST /token)
#    grant_type=authorization_code
#    code=AUTH_CODE
#    redirect_uri=https://app.example.com/callback
#    client_id=my-app
#    client_secret=secret  # or code_verifier for PKCE
#
# 6. Token Endpoint Response:
#    {
#      "access_token": "eyJhbG...",
#      "id_token": "eyJhbG...",
#      "refresh_token": "dGhpcyBpcyBh...",
#      "token_type": "Bearer",
#      "expires_in": 3600
#    }

# ID Token (JWT) Structure:
# Header: {"alg": "RS256", "kid": "key-id"}
# Payload: {
#   "iss": "https://auth.example.com",
#   "sub": "user-123",
#   "aud": "my-app",
#   "exp": 1706000000,
#   "iat": 1705996400,
#   "nonce": "random-nonce",
#   "name": "John Doe",
#   "email": "john@example.com",
#   "email_verified": true,
#   "picture": "https://example.com/photo.jpg"
# }

# Python — Verify ID Token
# pip install PyJWT cryptography requests

# import jwt
# import requests
#
# def verify_id_token(id_token, client_id, issuer):
#     # Get JWKS from discovery
#     jwks_url = f"{issuer}/.well-known/jwks.json"
#     jwks = requests.get(jwks_url).json()
#     
#     # Decode and verify
#     header = jwt.get_unverified_header(id_token)
#     key = next(k for k in jwks['keys'] if k['kid'] == header['kid'])
#     public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key)
#     
#     payload = jwt.decode(
#         id_token,
#         public_key,
#         algorithms=['RS256'],
#         audience=client_id,
#         issuer=issuer,
#     )
#     return payload

from dataclasses import dataclass

@dataclass
class OIDCEndpoint:
    endpoint: str
    method: str
    purpose: str
    returns: str

endpoints = [
    OIDCEndpoint("/authorize", "GET", "Start authentication", "Authorization Code"),
    OIDCEndpoint("/token", "POST", "Exchange code for tokens", "Access + ID Token"),
    OIDCEndpoint("/userinfo", "GET", "Get user profile", "User Claims"),
    OIDCEndpoint("/revoke", "POST", "Revoke token", "Success/Error"),
    OIDCEndpoint("/logout", "GET", "End session", "Redirect"),
    OIDCEndpoint("/.well-known/openid-configuration", "GET", "Discovery", "Server Metadata"),
]

print("=== OIDC Endpoints ===")
for e in endpoints:
    print(f"  [{e.method}] {e.endpoint}")
    print(f"    Purpose: {e.purpose} | Returns: {e.returns}")

Interview Questions

# === OIDC Interview Questions ===

@dataclass
class InterviewQ:
    question: str
    difficulty: str
    key_points: str
    category: str

questions = [
    InterviewQ(
        "OIDC ต่างจาก OAuth 2.0 อย่างไร",
        "Easy",
        "OAuth=Authorization, OIDC=Authentication, ID Token vs Access Token",
        "Fundamentals"
    ),
    InterviewQ(
        "ID Token มี Claims อะไรบ้าง",
        "Easy",
        "iss sub aud exp iat nonce name email picture",
        "Token"
    ),
    InterviewQ(
        "Authorization Code Flow ทำงานอย่างไร",
        "Medium",
        "Redirect → Login → Code → Exchange → Tokens",
        "Flow"
    ),
    InterviewQ(
        "PKCE คืออะไร ทำไมต้องใช้",
        "Medium",
        "Code Verifier + Challenge, ป้องกัน Code Interception, SPA/Mobile",
        "Security"
    ),
    InterviewQ(
        "Access Token กับ ID Token ต่างกันอย่างไร",
        "Medium",
        "Access=API Authorization, ID=User Identity, ใช้ต่างกัน",
        "Token"
    ),
    InterviewQ(
        "Token เก็บที่ไหนปลอดภัย",
        "Hard",
        "HttpOnly Cookie (best), Memory (SPA), ไม่เก็บ localStorage",
        "Security"
    ),
    InterviewQ(
        "Refresh Token Rotation คืออะไร",
        "Hard",
        "ออก Refresh Token ใหม่ทุกครั้ง, Revoke Token เก่า, Detect Reuse",
        "Security"
    ),
    InterviewQ(
        "Token Validation ต้องตรวจอะไรบ้าง",
        "Hard",
        "Signature iss aud exp iat nonce, JWKS Verification",
        "Security"
    ),
]

print("=== Interview Questions ===")
for q in questions:
    print(f"  [{q.difficulty}] [{q.category}] {q.question}")
    print(f"    Key Points: {q.key_points}")

# Common Mistakes
mistakes = [
    "ใช้ Implicit Flow แทน Authorization Code + PKCE",
    "เก็บ Token ใน localStorage (XSS vulnerable)",
    "ไม่ Validate ID Token signature",
    "ไม่ตรวจ iss aud exp claims",
    "ส่ง Access Token ไปยัง Third-party API โดยไม่จำเป็น",
    "ไม่ใช้ state parameter (CSRF)",
    "ใช้ ID Token เป็น Access Token",
]

print(f"\n\nCommon Mistakes:")
for i, m in enumerate(mistakes, 1):
    print(f"  {i}. {m}")

Implementation

# === OIDC Implementation ===

# Node.js — Express + Passport
# npm install passport passport-openidconnect express-session
#
# const passport = require('passport');
# const { Strategy } = require('passport-openidconnect');
#
# passport.use(new Strategy({
#   issuer: 'https://auth.example.com',
#   authorizationURL: 'https://auth.example.com/authorize',
#   tokenURL: 'https://auth.example.com/token',
#   userInfoURL: 'https://auth.example.com/userinfo',
#   clientID: process.env.CLIENT_ID,
#   clientSecret: process.env.CLIENT_SECRET,
#   callbackURL: 'https://app.example.com/callback',
#   scope: 'openid profile email',
# }, (issuer, profile, done) => {
#   return done(null, profile);
# }));
#
# app.get('/login', passport.authenticate('openidconnect'));
# app.get('/callback', passport.authenticate('openidconnect', {
#   successRedirect: '/dashboard',
#   failureRedirect: '/login',
# }));

# Security Checklist
security_checklist = {
    "PKCE": "ใช้ PKCE สำหรับ SPA และ Mobile App",
    "State Parameter": "สร้าง Random State ป้องกัน CSRF",
    "Nonce": "ใช้ Nonce ใน ID Token ป้องกัน Replay",
    "Token Storage": "HttpOnly Secure SameSite Cookie",
    "Token Validation": "Verify Signature + Claims ทุกครั้ง",
    "HTTPS": "ใช้ HTTPS เท่านั้น ทุก Endpoint",
    "Refresh Rotation": "Rotate Refresh Token ทุกครั้งที่ใช้",
    "Scope Minimization": "Request เฉพาะ Scope ที่จำเป็น",
    "Logout": "Implement Front-channel + Back-channel Logout",
    "CORS": "กำหนด Allowed Origins อย่างเข้มงวด",
}

print("Security Checklist:")
for item, desc in security_checklist.items():
    print(f"  [{item}]: {desc}")

เคล็ดลับ

OpenID Connect คืออะไร

Identity Layer บน OAuth 2.0 Authentication ID Token JWT SSO Login Google Apple Auth0 Okta Keycloak Authorization Token UserInfo Discovery

OAuth 2.0 กับ OpenID Connect ต่างกันอย่างไร

OAuth Authorization Access Token สิทธิ์เข้าถึง OIDC Authentication ID Token ระบุตัวตน สิทธิ์ vs ตัวตน ใช้ร่วมกัน OIDC บน OAuth

Authorization Code Flow ทำงานอย่างไร

Login Redirect Authorization Server Code Consent Redirect Callback Exchange Token Access ID Refresh PKCE Code Verifier

คำถามสัมภาษณ์ OIDC ที่พบบ่อย

OIDC vs OAuth ID Token Claims Flow PKCE Access vs ID Token Storage Refresh Token CSRF Scope Discovery Validation

สรุป

OpenID Connect OIDC OAuth 2.0 Authentication ID Token JWT Authorization Code Flow PKCE SSO Security Token Validation Interview Preparation Production

📖 บทความที่เกี่ยวข้อง

Java Micronaut Interview Preparationอ่านบทความ → DNS over TLS Interview Preparationอ่านบทความ → OpenID Connect Troubleshooting แก้ปัญหาอ่านบทความ → Stencil.js Interview Preparationอ่านบทความ → Vue Nuxt Server Interview Preparationอ่านบทความ →

📚 ดูบทความทั้งหมด →