jojo/tests
steven.guiheux ba1c3e0288 feat(api): add admin routes to manage user access tokens (#12323)
# Feature Request: Admin API route to manage access tokens for any user
## Problem
The existing API route to create access tokens (POST /api/v1/users/{username}/tokens) requires Basic authentication (username + password) via the reqBasicOrRevProxyAuth() middleware. This is by design: a token should not be created from another token.

However, this creates a blocker for environments where Basic authentication is disabled (ENABLE_BASIC_AUTHENTICATION = false), typically when authentication is delegated to an external SSO provider (e.g., OpenID Connect).

In such setups, bot/service accounts are provisioned by an external system that needs to:

Create a user via POST /api/v1/admin/users (works fine with an admin token)
Create an access token for that user (currently impossible without Basic auth or direct CLI/DB access)
The only workaround today is to SSH into the Forgejo server and run:

This is not suitable when the provisioning system has no direct access to the Forgejo host.

## Proposed solution
Add new admin-only API routes under the existing /api/v1/admin/users/{username} group to manage access tokens:

| Method |	Route |	Description |
|:-------- |:--------:| --------:|
| GET	| /api/v1/admin/users/{username}/tokens |	List access tokens for a user|
|POST	| /api/v1/admin/users/{username}/tokens |	Create an access token for a user|
|DELETE |	/api/v1/admin/users/{username}/tokens/{id} |	Delete an access token for a user|

These routes would:

Require a site admin token (reqToken() + reqSiteAdmin()) — no Basic auth needed
Use the AccessTokenScopeCategoryAdmin token scope
Reuse the existing handler logic from user.CreateAccessToken / user.ListAccessTokens / user.DeleteAccessToken
Accept the same request/response payloads as the existing user-facing routes

### Why this belongs in the admin API
It follows the existing pattern: admins can already create users, repos, orgs, SSH keys, and emails for any user via the admin API
It does not weaken security: only site administrators can call it, and it requires a valid admin-scoped token
It fills a gap: the admin CLI command forgejo admin user generate-access-token already provides this capability, but only locally

<!--start release-notes-assistant-->

## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Features
  - [PR](https://codeberg.org/forgejo/forgejo/pulls/12323): <!--number 12323 --><!--line 0 --><!--description ZmVhdChhcGkpOiBhZGQgYWRtaW4gcm91dGVzIHRvIG1hbmFnZSB1c2VyIGFjY2VzcyB0b2tlbnM=-->feat(api): add admin routes to manage user access tokens<!--description-->
<!--end release-notes-assistant-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12323
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
2026-05-11 16:55:22 +02:00
..
e2e fix(e2e): Flaky tests on Toggle WIP + Dependency dropdown (#12473) 2026-05-11 04:31:13 +02:00
fuzz chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00
gitea-lfs-meta Test views of LFS files (#22196) 2022-12-23 07:41:56 +08:00
gitea-repositories-meta fix(web): org projects assignment in issue view (#7999) 2026-05-02 01:29:40 +02:00
integration feat(api): add admin routes to manage user access tokens (#12323) 2026-05-11 16:55:22 +02:00
testdata/data add model viewer for .glb (GLTF) model in file view (#8111) 2025-06-21 14:42:35 +02:00
install.ini.tmpl feat: replace repo based server-side hooks with centralised hooks (#10397) 2026-04-27 22:34:46 +02:00
mysql.ini.tmpl feat: match on compound filename extensions (#11439) 2026-03-19 01:25:51 +01:00
pgsql.ini.tmpl feat: match on compound filename extensions (#11439) 2026-03-19 01:25:51 +01:00
sqlite.ini.tmpl feat: match on compound filename extensions (#11439) 2026-03-19 01:25:51 +01:00
test_utils.go chore: add modernizer linter (#11936) 2026-04-02 03:29:37 +02:00
unittest.ini.tmpl feat: replace repo based server-side hooks with centralised hooks (#10397) 2026-04-27 22:34:46 +02:00