Forgejo: Least‑Privilege Authentication vs. Expired Credentials – Interoperability with External Auth Providers
0 reputation · 09 Feb 2023, 11:43 UTC
0 reputation · 09 Feb 2023, 11:43 UTC
The goal is to integrate an external OAuth2 provider with Forgejo while ensuring that user access remains strictly scoped and that revoked or expired tokens do not continue to grant access. Forgejo accepts OAuth2 access tokens but does not automatically detect token expiration on subsequent API calls; the client must handle 401 responses and re‑authenticate. Additionally, Forgejo’s internal password policy only allows a global expiration window, without per‑user or automatic revocation mechanisms.
Key constraints include:
Unresolved questions:
32775 reputation · 09 Feb 2023, 19:50 UTC
Forgejo does not automatically invalidate sessions when an external OAuth2 token is revoked or expires. The client application must detect 401 Unauthorized responses and handle re-authentication. This behavior is by design—Forgejo treats each API request independently and relies on the provider to signal token validity.
Admin → Authentication → OAuth2 and configure your provider's endpoints.repo:read, repo:write, org:read, and org:write. Forgejo will honor these when mapping to repository and organization permissions.401, confirming the token is no longer valid.To enforce least privilege, configure your OAuth2 provider to issue tokens with only the scopes required for specific actions. For example:
repo:read – allows reading repository content and issues.repo:write – grants push and issue creation rights.org:read – permits reading organization membership and teams.org:write – enables managing teams and invitations.Forgejo does not currently support automatic scope down-leveling or dynamic permission adjustment beyond what the provider enforces.
Forgejo's password policy supports only a global expiration window configured in app.ini under [security]. There is no per-user expiration setting in the current release. To enforce rotation, administrators must manually reset passwords or use external authentication flows that do not rely on native passwords.
401 responses.Verification Required: Confirm your Forgejo version's OAuth2 behavior by testing token revocation and checking the admin console for available scope mappings. Future releases may improve automatic session handling.
Use comments to ask for clarification. Post a solution as an answer.
32,775 reputation · 09 Feb 2023, 17:52 UTC
One clarification that reframes the first question: after the OAuth2 authorization-code flow completes, Forgejo creates its own internal session cookie. Subsequent web requests authenticate against that session, not the external token — so there is nothing for a 401-driven client flow to catch on the web side, and provider-side revocation cannot propagate on its own. This is inherited Gitea-lineage behavior, so verify against your deployed Forgejo version.
A practical mitigation is an out-of-band job: poll the provider's introspection or user-status endpoint (or consume its revocation webhook), then call Forgejo's admin API to delete the affected user's sessions or disable the account. Shortening the session lifetime in app.ini bounds the exposure window but is a blunt instrument.
Also worth separating two concerns the discussion mixes: OAuth2 login scopes govern sign-in, while least privilege for automation is better enforced with Forgejo access tokens using narrow scopes (e.g. read:repository), plus group-to-team mapping so repository permissions live in Forgejo's team model rather than in token scope alone.