Module: StandardId::AudienceVerification
- Extended by:
- ActiveSupport::Concern
- Defined in:
- app/controllers/concerns/standard_id/audience_verification.rb
Overview
Per-controller audience verification for API endpoints.
StandardId enforces audience in three layers:
1. At encode time (`Oauth::TokenGrantFlow#validate_audience!`):
rejects issuance of tokens with an audience outside the global
`StandardId.config.oauth.allowed_audiences` list.
2. At decode time (`JwtService.decode(..., allowed_audiences:)`):
rejects tokens whose `aud` claim does not match the caller-supplied
list, raising `StandardId::InvalidAudienceError`. The engine's
`Api::TokenManager#verify_jwt_token` wires this automatically when
`StandardId.config.oauth.allowed_audiences` is non-empty — a
mismatch there is normalised to the same 401 "invalid token"
response as a bad signature. Call sites that pass no arguments
to `decode` directly still skip aud checks by design.
3. At the controller, via this concern: layers on top as
per-endpoint defense-in-depth. Required when a controller serves
a strict subset of the global allowed audiences (e.g., the global
list is `%w[web api admin]` but `AdminController` must only
accept `admin`).
With the global decode-time check now automatic, this concern is primarily useful for tightening the allowed audience per controller, not for plugging the “controller forgot to verify aud” gap (which is closed globally when ‘config.oauth.allowed_audiences` is set).
In addition, when ‘StandardId.config.oauth.audience_profile_types` is set, this concern enforces the audience → profile-type binding: after the allowed-audience check, it resolves the current account’s profile for the matched audience and rejects requests whose profile type does not match.
Requires StandardId::ApiAuthentication to be included before this concern (provides ‘verify_access_token!` and `current_session`). An error is raised at include time if ApiAuthentication is missing.
The caller is responsible for registering ‘before_action :verify_access_token!` (typically via ApiAuthentication or a base controller). This concern only adds the `verify_audience!` callback, which must run after token verification so that `current_session` is populated. This is consistent with how `require_scopes!` works in ApiAuthentication.