...
- If all valid → Proceed to Step 4
- If any invalid → Return error (401 Unauthorized)
...
Step 4: Azure AD Issues Access Token
What happens:
- Azure AD generates an access token
- Token valid for 1 hour
- Token contains app identity (not user identity)
- Token returned to ServiceTokenHandler
Who's involved:
- Microsoft Entra ID
- ServiceTokenHandler
What's in the token:
- Issuer: Microsoft Entra ID
- Audience: IntegrationServiceAPI (who the token is for)
- App Identity: ApiService's application ID
- Permissions: What ApiService can do
- Expiration: 1 hour from now
- Signature: Cryptographic proof of authenticity
Result:
- ServiceTokenHandler receives access token
- Token cached for future requests (1 hour)
...
Step 5: Token Attached to Request
What happens:
- ServiceTokenHandler attaches token to the original request
- Token added as Authorization header:
Bearer {token} - Request continues to IntegrationServiceAPI
Who's involved:
- ServiceTokenHandler
- ApiService
Result:
- Request sent to IntegrationServiceAPI with authentication proof
...
Step 6: IntegrationServiceAPI Validates Token
What happens:
- IntegrationServiceAPI receives request with token
- Authentication middleware examines the token
- Validates token is authentic and valid (using cached Azure AD public keys - no Azure AD call needed)
Who's involved:
- IntegrationServiceAPI
- JWT Authentication Middleware
- Azure AD public keys (cached locally, refreshed every 30 minutes)
What's validated:
- Signature: Proves token came from Azure AD
- Issuer: Confirms it's from the correct Azure AD tenant
- Audience: Ensures it's for IntegrationServiceAPI
- Expiration: Checks it hasn't expired (1-hour lifetime)
- App Permissions: Verifies ApiService has permission
Result:
- ✅ Valid token → Request proceeds to controller
- ❌ Invalid token → Return 401 Unauthorized
...
Step 7: API Processes Request
What happens:
- Request validated successfully
- IntegrationServiceAPI processes the request
- Executes the requested operation
- Returns response to ApiService
Who's involved:
- IntegrationServiceAPI
- ApiService
Result:
- Operation completed
- Response returned to ApiService
- ApiService continues its workflow
...
Token Caching & Reuse
Token Caching
ServiceTokenHandler caches tokens to improve performance:
First request:
- No cached token available
- Request token from Azure AD (takes ~100-200ms)
- Cache token for 1 hour
- Use token for request
Subsequent requests (within 1 hour):
- Check cache for valid token
- Use cached token (takes ~1-5ms)
- No Azure AD call needed
After 1 hour:
- Cached token expired
- Request new token from Azure AD
- Update cache with new token
Benefits:
- ⚡ Fast (no Azure AD call for most requests)
- 📈 Scalable (no rate limits on cached tokens)
- 🔒 Secure (token automatically refreshed)
...
Security Details
Client Secret
What it is:
- A secret key that proves ApiService's identity
- Like a password for the application (not a user)
- Created in Azure AD app registration
- Must be kept secure
Where it's stored:
- Development: User secrets or
secrets.json(not in git) - Production: Azure Key Vault or environment variables
- Never: Committed to source control
How it's used:
- ServiceTokenHandler reads it from configuration
- Sends it to Azure AD with client ID
- Azure AD validates it matches the registered secret
- If valid, token is issued
Security best practices:
- ✅ Store in Azure Key Vault (production)
- ✅ Use environment variables
- ✅ Rotate periodically (every 6-12 months)
- ❌ Never commit to git
- ❌ Never hardcode in source files