content-block-manager: 0008-allow-non-signon-users-to-access-fact-check-view-via-a-jwt
Date: 2025-11-27
Status: Accepted
Context
In the previous ADR, we proposed adding a fact check view as a Rails engine to allow users who do not have access to signon to preview content securely.
We needed to determine how to authenticate these external users without requiring signon credentials.
Decision
We will use JSON Web Tokens (JWTs) for authentication, following the existing pattern used for draft content access in the draft stack.
How it works
-
Token generation: Each Edition will have a method to generate a JWT containing:
- The content ID
- A new autogenerated UUID field on the edition (identifying the specific edition) - if a new token needs to be generated for any reason, this UUID will change, effectively expiring the old token.
- A timestamp indicating when the token expires
-
Token validation: When a user visits the fact check view URL with a JWT query parameter:
- The JWT is decoded and validated
- If valid and hasn't expired/been revoked, the request bypasses signon authentication
- The user can view the specific content block edition
-
Session management: The JWT will be stored as a browser cookie, allowing users to navigate between pages without re-authenticating.
Implementation reference
This approach mirrors the existing pattern in the authenticating-proxy app, which handles draft content access by:
- Decoding JWTs from request URLs
- Proxying authenticated requests to the draft stack
- Scoping access to specific content items and editions
We did consider using the authentication proxy to authenticate requests to our fact check application, but as the it only handles requests to frontend apps, we can't use it for fact check views.
Consequences
Positive
- External users (e.g., fact checkers) can securely access content without signon accounts
- Follows established GOV.UK patterns for draft content authentication
- JWTs are scoped to specific editions, preventing unauthorized access to other content
- Cookie-based session management provides a smooth user experience
Negative
- Additional complexity in authentication logic (two authentication paths: signon and JWT)
- Need to manage JWT lifecycle (generation, expiration, revocation)
- Requires careful handling of the
JWT_AUTH_SECRETin all environments
Implementation requirements
- Add
JWT_AUTH_SECRETenvironment variable for token generation and validation - Add UUID field to Edition model for edition-specific tokens
- Implement JWT generation method on Edition
- Implement JWT validation/expiration logic for fact check routes