April 4, 2025

Understanding the Token Lifecycle in OAuth2 & OpenID Connect

In modern authentication systems, especially with Keycloak, OAuth2, and OpenID Connect, understanding the lifecycle of tokens is crucial for building secure and scalable applications.

This blog explores the Token Lifecycle—what it looks like, why it's essential, and how each phase works in practice. Whether you're a backend developer integrating Keycloak or a DevOps engineer managing secure access, this will give you clarity on how tokens behave.


✨ Why the Token Lifecycle Matters

Tokens are the keys to accessing protected resources. Mismanaging them can lead to security vulnerabilities like:

  • Unauthorized access

  • Token reuse attacks

  • Inconsistent session management

Understanding how tokens are issued, validated, refreshed, and revoked can help mitigate these issues and improve user experience.


🌍 The Token Lifecycle: Step-by-Step

+---------------------------+
|  User / Service Logs In   |
+---------------------------+
             |
             v
+---------------------------+
|  Token Endpoint Issues:   |
|  - Access Token           |
|  - ID Token (optional)    |
|  - Refresh Token          |
+---------------------------+
             |
             v
+---------------------------+
|   Access Token Used to    |
|   Call Protected APIs     |
+---------------------------+
             |
             v
+---------------------------+
|   Token Expires OR        |
|   API Returns 401         |
+---------------------------+
             |
             v
+---------------------------+
| Refresh Token Sent to     |
|    /token Endpoint         |
+---------------------------+
             |
             v
+---------------------------+
| New Tokens Issued         |
| (Access + ID)             |
+---------------------------+
             |
             v
+---------------------------+
| Optional: Logout or       |
| Session Revocation        |
+---------------------------+
             |
             v
+---------------------------+
| Tokens Invalidated        |
+---------------------------+

📉 Token Types Overview

Token Type Purpose Validity
Access Token Used for accessing protected resources (APIs) Short-lived
Refresh Token Used to get new access tokens without re-authentication Long-lived
ID Token Provides identity information (for OpenID Connect) Short-lived

⚖️ Introspection and Revocation

  • Introspection: Allows you to verify if a token is still active.

    curl -X POST \
      https://<keycloak>/protocol/openid-connect/token/introspect \
      -d "token=<access_token>" \
      -d "client_id=<client_id>" \
      -d "client_secret=<client_secret>"
    
  • Revocation: Lets the client invalidate refresh tokens explicitly.

    curl -X POST \
      https://<keycloak>/protocol/openid-connect/revoke \
      -d "token=<refresh_token>" \
      -d "client_id=<client_id>" \
      -d "client_secret=<client_secret>"
    

🔍 Best Practices

  • Always use HTTPS for all token operations.

  • Set appropriate token lifespans based on security needs.

  • Regularly introspect tokens if needed for backend validation.

  • Avoid long-lived access tokens; prefer rotating refresh tokens.


🔹 Conclusion

The token lifecycle is more than just issuing a token—it's a continuous process of managing user sessions securely and efficiently. By understanding this lifecycle, you can build systems that are both user-friendly and secure.

Next time you're dealing with token-based authentication, remember: knowing the lifecycle is half the battle.


Happy coding! 🚀

🔐 Complete Guide to Keycloak Tokens: Access, ID, Refresh & Service Accounts

A hands-on walkthrough for developers and architects on working with Keycloak token mechanisms and OpenID Connect endpoints.


🌟 Why Tokens and Introspection Matter – A Developer's Story

Imagine you're building a secure API that handles sensitive data like user profiles, financial transactions, or confidential communications. You want to ensure that only authorized users and systems can access the data—and that they're who they claim to be. Enter tokens and introspection.

Tokens are your security pass. They carry claims about the identity and access rights of whoever is calling your service. But just like real-world passes, they can be stolen, expire, or be misused. This is where introspection becomes your secret security checkpoint—allowing you to double-check if the pass is still valid and what permissions it carries.

Without introspection or validation:

  • You might trust an expired or revoked token.

  • Unauthorized access may go unnoticed.

  • You're blind to token misuse or anomalies.

Choosing whether to introspect or decode JWT locally is an architectural decision:

  • Use local JWT parsing when performance is key and you're okay trusting signed tokens.

  • Use introspection when tokens might be revoked early or when access policies are dynamic.


📘 What Are Tokens in Keycloak?

Token Type Purpose Lifespan
Access Token Authorize access to APIs/resources Short-lived (e.g., 5 mins)
ID Token Carries identity information about the user Same as access token
Refresh Token Get new access token without re-login Long-lived (e.g., 30 mins or more)

🏢 Service Account Clients (Machine-to-Machine)

Use service accounts when no end user is involved. This is ideal for backend-to-backend communication.

🔧 How to Enable Service Accounts

  1. Go to your Keycloak admin console.

  2. Navigate to Clients > Select your client.

  3. Set Access Type to confidential.

  4. Enable Service Accounts Enabled.

  5. Assign roles via the Service Account Roles tab.

✨ Generate Token Using Client Credentials Flow

curl -X POST 'http://localhost:8080/realms/<realm>/protocol/openid-connect/token' \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<client-id>" \
-d "client_secret=<client-secret>"

👤 Access, ID, and Refresh Tokens (User Login Flow)

📄 Get Tokens Using Resource Owner Password Credentials (ROPC) Flow

curl -X POST 'http://localhost:8080/realms/<realm>/protocol/openid-connect/token' \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password" \
-d "client_id=<client-id>" \
-d "client_secret=<client-secret>" \
-d "username=<username>" \
-d "password=<password>"

✅ Example Response:

{
  "access_token": "...",
  "refresh_token": "...",
  "id_token": "...",
  "expires_in": 300,
  "refresh_expires_in": 1800
}

🔄 Refreshing Tokens

Use the refresh token to obtain a new access + ID token without requiring user credentials again.

curl -X POST 'http://localhost:8080/realms/<realm>/protocol/openid-connect/token' \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "client_id=<client-id>" \
-d "client_secret=<client-secret>" \
-d "refresh_token=<refresh-token>"

🚫 Revoking Tokens and Logout

🔐 End User Logout

curl -X POST 'http://localhost:8080/realms/<realm>/protocol/openid-connect/logout' \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=<client-id>" \
-d "client_secret=<client-secret>" \
-d "refresh_token=<refresh-token>"

🛠️ Manual Revocation via Admin Console

  • Go to Realm > Sessions.

  • Revoke all or specific user sessions.


🕵️ Introspecting Tokens

Token introspection helps validate and decode access tokens without relying solely on JWT parsing.

This is crucial when:

  • You're using opaque tokens instead of JWTs.

  • You want to support early revocation of access.

  • You're building a resource server and want dynamic policy enforcement.

📥 How to Introspect a Token (For Bearer Token Validation)

curl -X POST 'http://localhost:8080/realms/<realm>/protocol/openid-connect/token/introspect' \
-u <client-id>:<client-secret> \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=<access-token>"

🧾 Sample Introspection Response

{
  "active": true,
  "exp": 1687891234,
  "iat": 1687887634,
  "client_id": "your-client-id",
  "username": "user@example.com",
  "scope": "profile email",
  "sub": "user-uuid",
  "realm_access": { "roles": ["user"] }
}

You can use Spring Security's OpaqueTokenIntrospector for this, or call the endpoint manually using WebClient.


🧠 Best Practices & Configuration Rules

  • Access Tokens: JWT, sent in the Authorization: Bearer header.

  • ID Tokens: Meant for clients (not APIs). Carry user identity info.

  • Refresh Tokens: Must be stored securely (prefer backend or HTTP-only cookies).

  • Token Lifespans: Configure in Realm Settings > Tokens tab.

  • Public Clients: Use PKCE, do not use client secrets.

  • Confidential Clients: Always use client secret.

  • Avoid hardcoding secrets in client-side apps.

  • Decide on introspection vs. local parsing based on your app's architecture and trust model.


🔢 Testing Flow Summary

Step Token Type Endpoint
Login with credentials access_token, id_token, refresh_token /token
Use access token Authorization header for secured APIs Your protected API
Refresh token New access_token, id_token /token with refresh_token
Logout / Revoke Ends session & invalidates tokens /logout
Introspect token Validate and decode token details /token/introspect

📚 Additional Resources


🚀 Want More?

Let me know if you'd like:

  • Java + Spring Security + Keycloak examples

  • Postman collections

  • React + PKCE front-end tutorial

Follow for more backend & security insights!


Author: Jatin
Tags: #Keycloak #OAuth2 #OpenIDConnect #JWT #BackendSecurity #SpringBoot