JWT (JSON Web Token) in Banking Applications
JWT (JSON Web Token) is a compact, URL-safe token format defined by RFC 7519 that enables secure transmission of claims between parties.
Why JWT is Used
JWT is commonly used for:
- Authentication
- Authorization
- Identity Propagation Between Microservices
- API Security
- Single Sign-On (SSO)
In banking systems, JWT is commonly used between:
- Internet Banking โ API Gateway
- Mobile Banking โ Backend APIs
- Microservice โ Microservice Communication
- OAuth2 / OpenID Connect Integrations
JWT Structure
A JWT contains three parts:
Header.Payload.Signature
Example JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NSIsInJvbGUiOiJDVVNUT01FUiIsImV4cCI6MTcwMDAwMDAwMH0
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Part 1: Header
The header contains metadata about the token.
{
"alg": "RS256",
"typ": "JWT"
}
| Field | Description |
|---|---|
| alg | Signing Algorithm |
| typ | Token Type |
Banking Recommendation
{
"alg": "RS256"
}
RS256 is preferred over HS256 because asymmetric cryptography provides stronger security and better key management.
Part 2: Payload
The payload contains claims.
{
"sub": "123456",
"customerId": "CUST001",
"role": "PREMIUM_CUSTOMER",
"exp": 1700000000
}
Standard JWT Claims
Subject (sub)
{
"sub":"12345"
}
Represents the user identity.
Issuer (iss)
{
"iss":"bank-auth-service"
}
Identifies who issued the token.
Audience (aud)
{
"aud":"payment-service"
}
Specifies who can consume the token.
Expiration (exp)
{
"exp":1700000000
}
Defines token expiry time.
Issued At (iat)
{
"iat":1699999999
}
Creation timestamp.
JWT ID (jti)
{
"jti":"abc123xyz"
}
Unique token identifier used for revocation tracking.
Part 3: Signature
The signature ensures token integrity.
Base64(Header)
+
"."
+
Base64(Payload)
The resulting string is signed.
HMACSHA256(
base64UrlEncode(header)
+
"."
+
base64UrlEncode(payload),
secret
)
JWT Authentication Flow
Step 1: Customer Login
POST /login
{
"username":"naresh",
"password":"******"
}
Step 2: Authentication Service Validation
- Database
- LDAP
- Active Directory
- Identity and Access Management (IAM)
Step 3: JWT Generation
{
"sub":"12345",
"role":"CUSTOMER",
"exp":"..."
}
Step 4: Client Stores JWT
- Mobile App
- Browser
Step 5: Subsequent Requests
GET /accounts
Authorization: Bearer eyJhbGc...
Step 6: API Gateway Validation
No database lookup is required.
Why JWT Became Popular
Traditional Session-Based Authentication
Client
|
Server Session
|
Redis
Every request requires a session lookup.
JWT-Based Authentication
Client
|
JWT
|
Microservices
No session lookup is required. JWT enables stateless and highly scalable systems.
JWT in Banking Microservices
Mobile App
|
API Gateway
|
---------------------------------
| | | |
Account Payment Customer Loan
Service Service Service Service
Gateway validates JWT once and forwards claims downstream.
{
"customerId":"12345",
"role":"PREMIUM"
}
HS256 vs RS256
HS256
- Symmetric Key
- Same Secret Used for Signing and Verification
- Every Service Needs the Secret Key
RS256
- Asymmetric Key Pair
- Private Key โ Sign
- Public Key โ Verify
Typical Banking Architecture
Auth Server
|
Private Key
Microservices
|
Public Key
Microservices can verify tokens but cannot generate forged tokens.
JWT Security Risks
Risk 1: Sensitive Data in Payload
Wrong
{
"accountNumber":"123456789",
"balance":"500000"
}
JWT payloads are not encrypted.
Correct
{
"customerId":"12345"
}
Risk 2: Long Expiration
{
"exp":"30 days"
}
Long-lived tokens increase risk if stolen.
Banking Recommendation:
- Access Token: 10โ15 Minutes
- Refresh Token: 24 Hours
Risk 3: Missing Audience Validation
{
"aud":"payment-service"
}
Prevents token replay attacks.
Risk 4: Algorithm Attack
Never accept:
{
"alg":"none"
}
Always whitelist approved algorithms such as RS256.
JWT vs Opaque Token
JWT
- Self-contained
- Contains Claims
- No Database Lookup
Opaque Token
a8hjsd789asd
- Requires Introspection Endpoint
- Additional Validation Call Required
/introspect
Banking Preference
- External Customers โ Opaque Tokens
- Internal Microservices โ JWT
JWT Revocation Challenges
JWT is stateless and difficult to revoke immediately.
Solution 1: Short Expiry
Access tokens expire within 10โ15 minutes.
Solution 2: Blacklisting
{
"jti":"abc123"
}
Store revoked token identifiers in Redis.
Solution 3: Token Versioning
User Table
token_version = 5
{
"version":5
}
After logout, increment the version and invalidate older tokens.
JWT in OAuth2 Architecture
Customer
|
Identity Provider
(Keycloak / Okta / ForgeRock)
|
JWT
|
API Gateway
|
Microservices
Access Token: JWT
Refresh Token: Opaque Token
This is a common enterprise banking architecture.
Senior-Level Interview Answer
JWT is a stateless, signed token format used to securely transmit identity and authorization claims across distributed systems. In banking microservices, JWTs are typically issued by an OAuth2/OpenID Connect authorization server and validated at the API Gateway and service layers. A JWT consists of a header, payload, and signature. We generally prefer RS256 over HS256 because private keys remain only with the authorization server while microservices verify using public keys. In banking environments, JWT payloads should never contain sensitive customer data, only identifiers and authorization claims. Access tokens are kept short-lived, typically 10โ15 minutes, with refresh tokens used for renewal. Additional controls such as audience validation, key rotation, token revocation strategies, and gateway-level verification are essential for regulatory and security compliance.
JWT (JSON Web Token) in Banking Microservices
JWT (JSON Web Token) is a compact, URL-safe token format defined by RFC 7519 that enables secure transmission of claims between parties.
Common Uses of JWT
- Authentication
- Authorization
- Identity Propagation Between Microservices
- API Security
- Single Sign-On (SSO)
JWT Usage in Banking Systems
- Internet Banking โ API Gateway
- Mobile Banking โ Backend APIs
- Microservice โ Microservice Communication
- OAuth2/OpenID Connect Integrations
JWT Structure
A JWT consists of three parts:
Header.Payload.Signature
Example JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiIxMjM0NSIsInJvbGUiOiJDVVNUT01FUiIsImV4cCI6MTcwMDAwMDAwMH0 . SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Part 1: Header
Contains metadata.
{
"alg": "RS256",
"typ": "JWT"
}
| Field | Description |
|---|---|
| alg | Signing Algorithm |
| typ | Token Type |
Banking Recommendation
Preferred:
{
"alg": "RS256"
}
Instead of:
{
"alg": "HS256"
}
RS256 uses asymmetric cryptography and is considered more secure for enterprise and banking systems.
Part 2: Payload
Contains claims.
{
"sub": "123456",
"customerId": "CUST001",
"role": "PREMIUM_CUSTOMER",
"exp": 1700000000
}
Standard Claims
Subject (sub)
{
"sub":"12345"
}
User identity.
Issuer (iss)
{
"iss":"bank-auth-service"
}
Who issued the token.
Audience (aud)
{
"aud":"payment-service"
}
Who can consume the token.
Expiration (exp)
{
"exp":1700000000
}
Token expiry time.
Issued At (iat)
{
"iat":1699999999
}
Creation timestamp.
JWT ID (jti)
{
"jti":"abc123xyz"
}
Unique token identifier used for revocation and audit purposes.
Part 3: Signature
Generated using:
Base64(Header)
+
"."
+
Base64(Payload)
Then signed.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
JWT Authentication Flow
Step 1 - Customer Login
POST /login
{
"username":"naresh",
"password":"******"
}
Step 2 - Authentication Service Validation
- Database
- LDAP
- Active Directory
- IAM Platform
Step 3 - JWT Generated
{
"sub":"12345",
"role":"CUSTOMER",
"exp":"..."
}
Step 4 - Client Stores JWT
- Mobile Application
- Browser
Step 5 - Subsequent Requests
GET /accounts
Authorization:
Bearer eyJhbGc...
Step 6 - Gateway Validation
API Gateway validates the token without requiring a database lookup.
Why JWT Became Popular
Traditional Session-Based Authentication
Client | Server Session | Redis
Every request requires a session lookup.
JWT Authentication
Client | JWT | Microservices
No session lookup required. Stateless and highly scalable.
JWT in Banking Microservices
Mobile App
|
API Gateway
|
-------------------------------------
| Account | Payment | Customer | Loan |
-------------------------------------
Gateway validates JWT once and forwards claims downstream.
{
"customerId":"12345",
"role":"PREMIUM"
}
Services trust the gateway.
HS256 vs RS256
HS256
- Symmetric Key
- Same Key for Signing and Verification
Problem:
Every microservice needs the secret key. If compromised, fake tokens can be generated.
RS256
- Private Key โ Sign
- Public Key โ Verify
Only the Authorization Server can create JWTs. Microservices can only verify them.
Why Banks Prefer RS256
- Better Key Management
- Zero Trust Architecture
- Private Key Never Shared
- Easier Key Rotation
- Regulatory Compliance
- Ideal for Distributed Systems
JWT Security Risks
Risk 1: Sensitive Data in Payload
Incorrect:
{
"accountNumber":"123456789",
"balance":"500000"
}
JWT payloads are encoded, not encrypted. Anyone possessing the token can decode it.
Correct:
{
"customerId":"12345"
}
Store identifiers only.
Risk 2: Long Expiration Time
{
"exp":"30 days"
}
Not recommended.
Banking Recommendation:
- Access Token: 15 Minutes
- Refresh Token: 24 Hours
Risk 3: No Audience Validation
{
"aud":"payment-service"
}
Always validate the audience claim to prevent replay attacks.
Risk 4: Algorithm Attack
Never allow:
{
"alg":"none"
}
Always whitelist RS256.
JWT vs Opaque Token
JWT
- Self-contained
- Contains Claims
- No Database Lookup
Opaque Token
a8hjsd789asd
- Requires Introspection Endpoint
- Needs Validation Lookup
Banking Preference
- External Customers โ Opaque Tokens
- Internal Microservices โ JWT
JWT Revocation Challenge
JWT is stateless. Once issued, revocation is difficult.
Solution 1: Short Expiry
Access Token = 15 Minutes
Solution 2: Redis Blacklist
{
"jti":"abc123"
}
Store revoked JWT IDs in Redis.
Solution 3: Token Versioning
User Table:
token_version = 5
JWT:
{
"version":5
}
After logout:
token_version = 6
All old tokens become invalid.
JWT in OAuth2 Architecture
Customer
|
Identity Provider
(Keycloak / Okta / ForgeRock)
|
JWT
|
API Gateway
|
Microservices
Access Token = JWT
Refresh Token = Opaque Token
This is the most common enterprise banking pattern.
Architect-Level Summary
JWT is a stateless, signed token format used to securely transmit identity and authorization claims across distributed systems.
Banking organizations typically use OAuth2/OpenID Connect, RS256 signing, API Gateway validation, short-lived access tokens, refresh tokens, token revocation mechanisms, and audience validation to ensure security and compliance.
Senior Java Engineers, Leads, and Architects should be able to explain:
- JWT Generation and Validation
- RS256 Public/Private Key Architecture
- OAuth2 and OpenID Connect
- API Gateway Security
- Refresh Token Flow
- Redis-Based Token Revocation
- JWKS Key Rotation
- Role-Based Authorization
- JWT Propagation Across Kafka Events
Why Banks Prefer RS256 Over HS256 for JWT Authentication
In enterprise banking systems, JWT tokens are typically signed using RS256 (RSA Signature Algorithm) rather than HS256 (HMAC SHA-256).
The primary reason is security, key management, regulatory compliance, and support for distributed microservices architectures.
HS256 Architecture
Auth Service
|
Shared Secret
|
-------------------
| Account Service |
| Payment Service |
| Loan Service |
-------------------
HS256 uses a symmetric key. The same secret key is used to both sign and verify JWT tokens.
How HS256 Works
- Authentication Service generates JWT.
- JWT is signed using a shared secret.
- Every microservice requires the same secret to validate the token.
- The same secret can also generate new tokens.
Problems with HS256
- Every service must store the secret.
- Compromise of one service compromises the entire platform.
- Any service can generate fake JWTs.
- Key rotation becomes difficult.
- Less suitable for large-scale distributed systems.
RS256 Architecture
Private Key
|
Auth Service
|
JWT Token
|
------------------------------------------------
| Account Service Public Key Verify |
| Payment Service Public Key Verify |
| Loan Service Public Key Verify |
------------------------------------------------
RS256 uses asymmetric cryptography.
- Private Key โ Sign JWT
- Public Key โ Verify JWT
Only the Authentication Server has access to the private key. Microservices receive only the public key.
Benefits of RS256
- Only the Authorization Server can create tokens.
- Microservices can only verify tokens.
- Compromised services cannot forge JWTs.
- Supports Zero Trust Architecture.
- Simplifies key rotation.
- Meets banking regulatory requirements.
Comparison: HS256 vs RS256
| Feature | HS256 | RS256 |
|---|---|---|
| Cryptography Type | Symmetric | Asymmetric |
| Signing Key | Shared Secret | Private Key |
| Verification Key | Shared Secret | Public Key |
| Key Exposure Risk | High | Low |
| Microservice Security | Moderate | High |
| Key Rotation | Difficult | Easier |
| Enterprise Adoption | Limited | Preferred |
Typical Banking Authentication Architecture
Customer
|
Mobile Banking
|
API Gateway
|
OAuth2 Authorization Server
(Keycloak / ForgeRock / Okta)
|
RS256 JWT
|
--------------------------------
| Account Service |
| Payment Service |
| Customer Service |
| Loan Service |
--------------------------------
Advantages
- Stateless authentication
- No session replication
- Horizontal scalability
- Public/Private key cryptography
- Gateway-level JWT validation
- OAuth2/OpenID Connect compliance
- Zero Trust microservices security
Architect-Level Interview Answer
In banking environments, RS256 is preferred over HS256 because it separates token generation from token validation. The Authorization Server exclusively owns the private key used for signing JWTs, while downstream services use only public keys for verification. This eliminates the risk of services generating fraudulent tokens, simplifies key rotation, supports zero-trust architectures, and satisfies enterprise security and compliance requirements. For modern banking microservices, RS256 combined with OAuth2 and OpenID Connect is considered the industry-standard approach.
Production-Grade JWT Architecture Using RS256
Problem with HS256
In HS256, every microservice shares the same secret key.
Auth Service
|
Shared Secret
|
-------------------
| Account Service |
| Payment Service |
| Loan Service |
-------------------
Challenges
- Every service has the secret key.
- Any service can generate fake tokens.
- Difficult key management.
Why Banks Prefer RS256
Private Key
|
Auth Service
|
JWT Token
|
------------------------------------------------
| Account Service Public Key Verify |
| Payment Service Public Key Verify |
| Loan Service Public Key Verify |
------------------------------------------------
Advantages
- Only Authorization Server can sign tokens.
- Microservices can only verify tokens.
- Better auditability.
- Easier key rotation.
- Improved regulatory compliance.
Project Structure
com.bank.auth
โโโ controller
โ โโโ AuthController.java
โ
โโโ config
โ โโโ SecurityConfig.java
โ
โโโ security
โ โโโ JwtService.java
โ โโโ JwtAuthenticationFilter.java
โ โโโ KeyLoader.java
โ
โโโ dto
โ โโโ LoginRequest.java
โ โโโ LoginResponse.java
โ
โโโ BankApplication.java
Generate RSA Keys
openssl genrsa -out private.pem 2048
openssl rsa \
-in private.pem \
-pubout \
-out public.pem
Store Keys
src/main/resources/keys
private.pem
public.pem
KeyLoader.java
Loads RSA private and public keys from PEM files.
package com.bank.auth.security;
@Component
public class KeyLoader {
public PrivateKey loadPrivateKey() throws Exception {
...
}
public PublicKey loadPublicKey() throws Exception {
...
}
}
JwtService.java
Responsible for generating and validating RS256 JWT tokens.
@Service
public class JwtService {
public String generateToken(
String username,
String role)
throws Exception {
PrivateKey privateKey =
keyLoader.loadPrivateKey();
return Jwts.builder()
.subject(username)
.claim("role", role)
.issuer("BANK-AUTH")
.issuedAt(new Date())
.expiration(
new Date(
System.currentTimeMillis()
+ 900000))
.signWith(
privateKey,
SignatureAlgorithm.RS256)
.compact();
}
public Claims validateToken(
String token)
throws Exception {
PublicKey publicKey =
keyLoader.loadPublicKey();
return Jwts.parser()
.verifyWith(publicKey)
.build()
.parseSignedClaims(token)
.getPayload();
}
}
JWT Authentication Filter
Intercepts every incoming request and validates JWT before allowing access to protected resources.
@Component
public class JwtAuthenticationFilter
extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain)
throws ServletException, IOException {
...
}
}
Security Configuration
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(
HttpSecurity http)
throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(
session ->
session.sessionCreationPolicy(
SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth
.requestMatchers("/auth/login")
.permitAll()
.anyRequest()
.authenticated())
.addFilterBefore(
filter,
UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Banking Login Controller
@RestController
@RequestMapping("/auth")
public class AuthController {
@PostMapping("/login")
public LoginResponse login(
@RequestBody LoginRequest request)
throws Exception {
if ("naresh".equals(request.getUsername())
&&
"bank123".equals(
request.getPassword())) {
String token =
jwtService.generateToken(
request.getUsername(),
"CUSTOMER");
return new LoginResponse(token);
}
throw new RuntimeException(
"Invalid Credentials");
}
}
JWT Flow in Banking
Customer
|
Mobile Banking
|
Login API
|
Authentication Service
|
Generate JWT (RS256)
|
API Gateway
|
Verify Signature
|
Account Service
Payment Service
Loan Service
Architect-Level Interview Questions
Why Not Store Account Numbers in JWT?
JWT payloads are Base64 encoded, not encrypted. Anyone holding the token can decode the payload.
Incorrect
{
"accountNumber":"12345678"
}
Never Store
- Account Number
- PAN
- Aadhaar
- Card Number
- Balance
Correct Approach
{
"sub":"customer123",
"role":"CUSTOMER",
"scope":"PAYMENT"
}
JWT Revocation
Logout
|
Redis Blacklist
|
Store JTI
|
Every Request
|
Check JWT
Check Redis
|
Reject Revoked Token
Refresh Token Flow
Token Lifetime
- Access Token: 15 Minutes
- Refresh Token: 24 Hours
Token Expired
|
/refresh
|
Validate Refresh Token
|
Issue New JWT
JWT with Kafka
Producer Event
{
"customerId":"123",
"jwt":"eyJ..."
}
Consumer Processing
- Validate Signature
- Validate Expiry
- Process Event
In enterprise banking systems, JWTs are usually propagated through Kafka headers rather than message payloads.
Complete Banking Authentication Architecture
โโโโโโโโโโโโโโโโโโโ
โ Mobile/Web App โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโ
โ API Gateway โ
โ Spring Gateway โ
โโโโโโโโโโฌโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Authorization Server โ
โ OAuth2 / OIDC โ
โ Keycloak / ForgeRock โ
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโดโโโโโโโโโโโ
โ โ
โผ โผ
Access Token Refresh Token
JWT (15 mins) DB/Redis (24 hrs)
โ
โผ
โโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโ
โ Account MS โ Payment MS โ Loan MS โ Customer MS โ
โโโโโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโโดโโโโโโโโโโโโโโ
โ
โผ
Redis
Token Blacklist
Maven Dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Banking JWT Claims Example
{
"sub":"CUST10001",
"jti":"8f1e9f71",
"role":"CUSTOMER",
"scope":"PAYMENT",
"channel":"MOBILE",
"iss":"BANK_AUTH_SERVER",
"aud":"PAYMENT_SERVICE",
"iat":1710000000,
"exp":1710000900
}
Common Banking Interview Questions
Why Use Refresh Tokens?
- Access Token: 15 Minutes
- Refresh Token: 24 Hours
- Reduces risk if access token is stolen.
Why Redis Blacklist?
Without Redis
Logout
โ
Token Still Valid
With Redis
Logout
โ
Blacklist JTI
โ
Reject Future Requests
Why Validate JWT at API Gateway?
- Single validation point.
- Reduced duplication.
- Lower microservice latency.
- Centralized security policy.
- Better audit logging.
Why OAuth2 + OpenID Connect?
OAuth2: Authorization
OpenID Connect: Authentication + Identity
Modern banking systems typically use Keycloak, ForgeRock, or Okta as Identity Providers.
Architect-Level Summary
- OAuth2 Authorization Server
- RS256 JWT Access Tokens
- Refresh Tokens stored in DB/Redis
- API Gateway Validation
- Redis Token Blacklist
- Role-Based Authorization
- JWKS Key Rotation
- Audit Logging and Traceability
- MFA Integration
- Zero-Trust Service-to-Service Security
This is the level of discussion expected for Lead Java Engineers, Solution Architects, and Principal Engineers in large banking organizations.