oicd_audience removal
This commit is contained in:
+3
-1
@@ -2,8 +2,10 @@
|
|||||||
OLLAMA_API_KEY=your_ollama_api_key_here
|
OLLAMA_API_KEY=your_ollama_api_key_here
|
||||||
|
|
||||||
# OIDC settings
|
# OIDC settings
|
||||||
|
# `OIDC_AUDIENCE` is optional. If set, the backend will validate the token's `aud` claim.
|
||||||
|
# If you prefer to skip audience validation (not recommended in production), leave
|
||||||
|
# `OIDC_AUDIENCE` unset.
|
||||||
OIDC_ISSUER=https://your-issuer.example.com
|
OIDC_ISSUER=https://your-issuer.example.com
|
||||||
OIDC_AUDIENCE=your-api-audience
|
|
||||||
OIDC_CLIENT_ID=your-client-id
|
OIDC_CLIENT_ID=your-client-id
|
||||||
OIDC_CLIENT_SECRET=your-client-secret
|
OIDC_CLIENT_SECRET=your-client-secret
|
||||||
OIDC_VERIFY_ISS=true
|
OIDC_VERIFY_ISS=true
|
||||||
|
|||||||
+16
-8
@@ -11,8 +11,11 @@ from pydantic import BaseModel, BaseSettings, Field, HttpUrl
|
|||||||
security = HTTPBearer(auto_error=False)
|
security = HTTPBearer(auto_error=False)
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
|
# OIDC issuer (discovery URL root)
|
||||||
oidc_issuer: HttpUrl = Field(..., env="OIDC_ISSUER")
|
oidc_issuer: HttpUrl = Field(..., env="OIDC_ISSUER")
|
||||||
oidc_audience: str = Field(..., env="OIDC_AUDIENCE")
|
# Optional audience: if set the backend will validate the token 'aud' claim.
|
||||||
|
# If omitted, audience validation is skipped (use with caution).
|
||||||
|
oidc_audience: Optional[str] = Field(None, env="OIDC_AUDIENCE")
|
||||||
oidc_client_id: str = Field(..., env="OIDC_CLIENT_ID")
|
oidc_client_id: str = Field(..., env="OIDC_CLIENT_ID")
|
||||||
oidc_client_secret: Optional[str] = Field(None, env="OIDC_CLIENT_SECRET")
|
oidc_client_secret: Optional[str] = Field(None, env="OIDC_CLIENT_SECRET")
|
||||||
oidc_verify_iss: bool = Field(True, env="OIDC_VERIFY_ISS")
|
oidc_verify_iss: bool = Field(True, env="OIDC_VERIFY_ISS")
|
||||||
@@ -79,13 +82,18 @@ async def validate_token(credentials: HTTPAuthorizationCredentials = Security(se
|
|||||||
key = get_signing_key(token)
|
key = get_signing_key(token)
|
||||||
public_key = jwk.construct(key)
|
public_key = jwk.construct(key)
|
||||||
try:
|
try:
|
||||||
verified = jwt.decode(
|
# Only pass `audience` to the decoder if configured. Some providers
|
||||||
token,
|
# (or local development setups) may not include the aud claim in a
|
||||||
public_key,
|
# way that matches your API identifier; in that case leave
|
||||||
algorithms=[key.get("alg", "RS256")],
|
# `OIDC_AUDIENCE` unset and the audience check will be skipped.
|
||||||
audience=settings.oidc_audience,
|
jwt_kwargs = {
|
||||||
issuer=str(settings.oidc_issuer) if settings.oidc_verify_iss else None,
|
"algorithms": [key.get("alg", "RS256")],
|
||||||
)
|
"issuer": str(settings.oidc_issuer) if settings.oidc_verify_iss else None,
|
||||||
|
}
|
||||||
|
if settings.oidc_audience:
|
||||||
|
jwt_kwargs["audience"] = settings.oidc_audience
|
||||||
|
|
||||||
|
verified = jwt.decode(token, public_key, **jwt_kwargs)
|
||||||
except JWTError as exc:
|
except JWTError as exc:
|
||||||
raise HTTPException(status_code=401, detail="Invalid or expired token") from exc
|
raise HTTPException(status_code=401, detail="Invalid or expired token") from exc
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# OIDC Audience (`aud`) — explanation and guidance
|
||||||
|
|
||||||
|
Why `aud` matters
|
||||||
|
|
||||||
|
- The `aud` (audience) claim in a JWT indicates the intended recipient(s) of the token.
|
||||||
|
- Your API should verify `aud` to ensure the token was issued for this service, preventing tokens meant for other services from being used against your backend.
|
||||||
|
|
||||||
|
How this project handles `aud`
|
||||||
|
|
||||||
|
- `OIDC_AUDIENCE` is optional in this scaffold.
|
||||||
|
- If `OIDC_AUDIENCE` is set in the environment, the backend will validate that the token's `aud` claim matches that value.
|
||||||
|
- If `OIDC_AUDIENCE` is not set, the backend will skip audience validation (the token still must be valid and optionally matched to `iss`).
|
||||||
|
|
||||||
|
Security guidance
|
||||||
|
|
||||||
|
- Production: set `OIDC_AUDIENCE` to the identifier your provider includes in access tokens for this API. This is typically:
|
||||||
|
- The API identifier or Resource URI you configured in Auth0
|
||||||
|
- The client ID (or `api://<client-id>`) in Azure AD when you configured an app registration
|
||||||
|
- The audience or client for Keycloak realm resources
|
||||||
|
|
||||||
|
- Local dev: it can be convenient to omit `OIDC_AUDIENCE` when using non-standard tokens or test setups, but avoid this in production.
|
||||||
|
|
||||||
|
Provider-specific notes
|
||||||
|
|
||||||
|
- Auth0: configure an API and use its Identifier as the `audience` when requesting tokens. The access token will contain that audience.
|
||||||
|
- Keycloak: check the client/realm settings; the `aud` may be the client id or an array of client ids.
|
||||||
|
- Azure AD: access tokens may use `aud` = `api://<client-id>` or your Application (client) ID URI.
|
||||||
|
|
||||||
|
How to discover the correct value
|
||||||
|
|
||||||
|
1. Request a token from your provider (or use the issuer's test token).
|
||||||
|
2. Decode the JWT (jwt.io or `python-jose`) and inspect the `aud` claim.
|
||||||
|
3. Set `OIDC_AUDIENCE` to that value in your `.env`.
|
||||||
|
|
||||||
|
If you want, paste an example decoded token (redact sensitive fields) and I can tell you the exact value to use for `OIDC_AUDIENCE`.
|
||||||
Reference in New Issue
Block a user