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.