JWT Audience and Issuer Validation — Restricting Token Scope to Specific Services
In this tutorial, you will learn about JWT Audience and Issuer Validation. We cover key concepts, practical examples, and best practices to help you master this topic.
JWT audience (aud) and issuer (iss) claims define which service issued the token and which service should accept it, preventing token reuse across different services.
What You'll Learn
How aud and iss claims work, why they are essential in multi-service architectures, and how to validate them correctly.
Why It Matters
Without audience validation, a token issued for the payments API can be used against the user management API. Without issuer validation, tokens from any provider are accepted. These claims are the foundation of JWT trust boundaries.
Real-World Use
Google's OAuth2 tokens include aud matching the client ID. Auth0 tokens include iss set to the tenant domain. Firebase tokens include both. AWS Cognito requires audience validation. Durga Antivirus Pro uses aud to separate its threat intelligence API from its device management API.
flowchart LR
A["Auth Server\niss: auth.dodatech.com"] -->|"Issues token"| B["Client"]
B -->|"Token\niss + aud"| C["Threat API\nverifies aud: threat-api"]
B -->|"Same token"| D["Device API\nrejects — wrong aud"]
style A fill:#dbeafe,stroke:#2563eb
style B fill:#fef3c7,stroke:#d97706
style C fill:#dcfce7,stroke:#16a34a
style D fill:#fecaca,stroke:#dc2626
The iss (Issuer) Claim
The iss claim identifies the party that issued the token.
{
"iss": "https://auth.dodatech.com",
"sub": "user-123"
}
Validation: Check that iss matches a trusted issuer. In a multi-tenant system, different tenants may have different issuers.
The aud (Audience) Claim
The aud claim identifies the intended recipient of the token. It can be a string or an array of strings.
{
"iss": "https://auth.dodatech.com",
"aud": "https://api.dodatech.com/threat",
"sub": "user-123"
}
Validation: Check that aud includes or matches your service identifier.
Code Example: Audience and Issuer Validation
import jwt
from flask import Flask, request, jsonify
app = Flask(__name__)
# Configuration
SECRET = "your-secret"
TRUSTED_ISSUERS = [
"https://auth.dodatech.com",
"https://accounts.google.com"
]
API_AUDIENCE = "https://api.dodatech.com/threat"
def require_valid_token(f):
def wrapper(*args, **kwargs):
auth = request.headers.get("Authorization", "")
token = auth[7:] if auth.startswith("Bearer ") else None
if not token:
return jsonify({"error": "Missing token"}), 401
try:
payload = jwt.decode(
token,
SECRET,
algorithms=["HS256"],
options={
"require": ["iss", "aud", "exp"],
"verify_exp": True
},
issuer=TRUSTED_ISSUERS, # Can be a list
audience=API_AUDIENCE # Must match exactly
)
g.user = payload
except jwt.InvalidIssuerError:
return jsonify({"error": "Untrusted issuer"}), 401
except jwt.InvalidAudienceError:
return jsonify({"error": "Wrong audience"}), 401
except jwt.ExpiredSignatureError:
return jsonify({"error": "Token expired"}), 401
except jwt.InvalidTokenError:
return jsonify({"error": "Invalid token"}), 401
return f(*args, **kwargs)
return wrapper
@app.route("/api/threats")
@require_valid_token
def get_threats():
return jsonify({"user": g.user["sub"]})
Code Example: Multi-Service Audience Validation
# Different services validate different audiences
class PaymentService:
AUDIENCE = "https://api.dodatech.com/payments"
def verify_token(self, token):
return jwt.decode(
token,
self.public_key,
algorithms=["RS256"],
audience=self.AUDIENCE,
issuer="https://auth.dodatech.com"
)
class UserService:
AUDIENCE = "https://api.dodatech.com/users"
def verify_token(self, token):
return jwt.decode(
token,
self.public_key, # Same public key source
algorithms=["RS256"],
audience=self.AUDIENCE, # Different audience
issuer="https://auth.dodatech.com"
)
Common Mistakes
1. Not Validating aud
Without audience validation, a token from any client or service can be used against any API.
2. Not Validating iss
Without issuer validation, an attacker can set up their own auth server and issue tokens your API will accept.
3. Using Wrong Audience Comparison
The aud claim might be a string or array. Use audience parameter (handles both) rather than manual string comparison.
4. Hardcoding Audience Values
Audience values should be configurable per environment (dev, staging, production). Hardcoding causes deployment issues.
5. Confusing aud with Client ID
The audience is the resource server, not the client. The client ID goes in a different claim (azp — authorized party).
Practice Questions
- What does the
audclaim represent in a JWT? - Why is audience validation important in Microservices?
- What happens if you validate
issbut notaud? - Can
audbe an array? - How does issuer validation differ in multi-tenant systems?
Answers:
- The
aud(audience) claim identifies the intended recipient of the token — typically the resource server URL. - Without audience validation, a token issued for one microservice can access another. Audience scopes the token to a specific service.
- An attacker can use a token from a trusted issuer but intended for a different service. The
issis valid, but the token should not work for your API. - Yes —
audcan be an array of strings when the token is valid for multiple services. The verifier checks if its audience is in the array. - Each tenant may have a different issuer (e.g.,
https://tenant1.auth.com). Validate against a list of allowed issuers per tenant.
Challenge: Design a multi-service JWT system where a single auth server issues tokens for three APIs (users, orders, payments). Each API validates its own audience. Show that an orders token cannot access the payments API.
FAQ
Mini Project
Build a multi-service JWT authentication system with an auth server that issues tokens with specific audiences, and two API services (users and reports) that each validate the audience claim and reject tokens intended for the other service.
What's Next
Now learn about JWT Claims — the standard and custom claims that carry user identity and authorization data.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro