jojo/models/auth
Mathieu Fenniak 70f7260e66 feat: add CLI command 'admin user create-authorized-integration' (#12299)
Allows the creation of an authorized integration as a Forgejo administrator, either for development testing or to support server-automation.  Clipping out the CLI config options, looks like:

```
NAME:
   forgejo admin user create-authorized-integration - Create an authorized integration for a specific user

USAGE:
   forgejo admin user create-authorized-integration [options]

OPTIONS:
   --username string, -u string                               Username
   --issuer string                                            JWT issuer ('iss' claim), example: https://forgejo.example.org/api/actions
   --claim-eq string=string [ --claim-eq string=string ]      Zero-or-more claim equality checks, formatted as claim=value, example: "actor=someuser"
   --claim-glob string=string [ --claim-glob string=string ]  Zero-or-more claim glob checks, formatted as claim=value, example: "sub=repo:forgejo/*:pull_request"
   --scope string [ --scope string ]                          One-or-more scopes to apply to access token, examples: "all", "read:issue", "write:repository" (default: "all")
   --repo string [ --repo string ]                            Zero-or-more specific repositories that can be accessed, or "all" to allow access to all repositories, example: "owner1/repo1" (default: "all")
```

As an example, this will create an authorized integration that will permit Codeberg's Forgejo Actions to generate trusted JWTs that can access the local user `mfenniak`:
```bash
$ ./forgejo admin user create-authorized-integration \
    --username mfenniak \
    --issuer https://codeberg.org/api/actions \
    --claim-eq sub=repo:mfenniak/forgejo-runner-testrepo:pull_request \
    --scope read:user

{
  "message": "Authorized integration was successfully created.",
  "issuer": "https://codeberg.org/api/actions",
  "audience": "u:1:c97d83bc-fa4e-4db3-b898-414cd5b6ce33",
  "claim_rules": [
    {
      "description": "\"sub\" = \"repo:mfenniak/forgejo-runner-testrepo:pull_request\"",
      "claim": "sub",
      "compare": "eq",
      "value": "repo:mfenniak/forgejo-runner-testrepo:pull_request"
    }
  ]
}
```

The output is a JSON document to aid in use in automation.  The `audience` field is the audience generated by Forgejo that must be used by the remote to generate the JWT.  Continuing this example to the client-side, a matching Forgejo Action like this in the `mfenniak/forgejo-runner-testrepo` repo, for a `pull_request` event, then it will be able to access the Forgejo server that the authorized integration was created on like this:

```yaml
on:
  pull_request:

enable-openid-connect: true

jobs:
  job1:
    runs-on: docker
    steps:
      - name: Fetch JWT
        id: jwt
        run: |
          set -eux -o pipefail
          set +x
          jwt=$(curl --fail \
            -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=u:1:c97d83bc-fa4e-4db3-b898-414cd5b6ce33" \
            | jq -r ".value")
          echo "::add-mask::$jwt"
          set -x
          echo "jwt=$jwt" >> $FORGEJO_OUTPUT

      - name: API call to Forgejo
        run: |
          curl \
            -v --fail \
            -H "Authorization: bearer ${{ steps.jwt.outputs.jwt }}" \
            "https://example.org/api/v1/user" | jq
```

CLI command is tested manually.  Supporting functions have associated unit tests.

## Checklist

The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. All work and communication must conform to Forgejo's [AI Agreement](https://codeberg.org/forgejo/governance/src/branch/main/AIAgreement.md). There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).

### Tests for Go changes

- I added test coverage for Go changes...
  - [x] in their respective `*_test.go` for unit tests.
  - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
- I ran...
  - [x] `make pr-go` before pushing

### Documentation

- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
- [x] I did not document these changes and I do not expect someone else to do it.
    - CLI update should be automatic in docs -- more detailed Authorized Integration documentation is on my project plan.

### Release notes

- [x] This change will be noticed by a Forgejo user or admin (feature, bug fix, performance, etc.). I suggest to include a release note for this change.
- [ ] This change is not visible to a Forgejo user or admin (refactor, dependency upgrade, etc.). I think there is no need to add a release note for this change.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/12299
Reviewed-by: Andreas Ahlenstorf <aahlenst@noreply.codeberg.org>
2026-04-28 21:32:45 +02:00
..
TestGetRepositoriesAccessibleWithIntegration feat: add repo-specific & public-only authz reducers to authorized integrations (#12267) 2026-04-26 23:54:41 +02:00
TestGetRepositoriesAccessibleWithToken feat: backend DB model for fine-grained repo access tokens 2026-02-27 17:17:29 +01:00
TestGetRepositoriesAccessibleWithTokens feat: read, create, & delete repo-specific access tokens via API (#11504) 2026-03-07 21:55:08 +01:00
TestOrphanedOAuth2Applications test: Global OAuth should not be deleted 2024-11-23 19:49:55 +01:00
access_token.go feat: read, create, & delete repo-specific access tokens via API (#11504) 2026-03-07 21:55:08 +01:00
access_token_resource.go feat: add repo-specific & public-only authz reducers to authorized integrations (#12267) 2026-04-26 23:54:41 +02:00
access_token_resource_test.go feat: read, create, & delete repo-specific access tokens via API (#11504) 2026-03-07 21:55:08 +01:00
access_token_scope.go chore: add modernizer linter (#11936) 2026-04-02 03:29:37 +02:00
access_token_scope_test.go [GITEA] silently ignore obsolete sudo scope 2024-02-05 16:05:50 +01:00
access_token_test.go feat: avoid updating all columns (#9572) 2025-10-09 13:22:29 +02:00
auth_token.go feat: add foreign keys to forgejo_auth_token (#9886) 2025-10-29 01:09:06 +01:00
authorized_integration.go feat: add CLI command 'admin user create-authorized-integration' (#12299) 2026-04-28 21:32:45 +02:00
authorized_integration_resource_repo.go feat: add CLI command 'admin user create-authorized-integration' (#12299) 2026-04-28 21:32:45 +02:00
authorized_integration_resource_repo_test.go feat: add CLI command 'admin user create-authorized-integration' (#12299) 2026-04-28 21:32:45 +02:00
authorized_integration_test.go feat: add CLI command 'admin user create-authorized-integration' (#12299) 2026-04-28 21:32:45 +02:00
main_test.go chore: move all test blank imports in a single package (#10662) 2026-01-02 05:32:32 +01:00
oauth2.go chore: add modernizer linter (#11936) 2026-04-02 03:29:37 +02:00
oauth2_list.go chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00
oauth2_test.go chore: merge tests.AddFixtures and unittest.OverrideFixtures (#7648) 2025-04-25 09:14:33 +00:00
session.go chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00
session_test.go Update module github.com/golangci/golangci-lint/cmd/golangci-lint to v2 (forgejo) (#7367) 2025-03-28 22:22:21 +00:00
source.go chore: add modernizer linter (#11936) 2026-04-02 03:29:37 +02:00
source_test.go chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00
two_factor.go feat: consider WebAuthn & SSH for instance signing (#7693) 2025-04-29 10:34:07 +00:00
two_factor_test.go chore: add SQL fault injector testing (#9314) 2025-09-18 00:39:06 +02:00
twofactor.go feat: cache derived keys for faster keying (#10114) 2025-11-16 14:29:14 +01:00
webauthn.go chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00
webauthn_test.go chore: branding import path (#7337) 2025-03-27 19:40:14 +00:00