Contents

Tokens and sign-in Enterprise

Every call to a team server needs a token. Give each person and each CI runner its own token, or let people sign in with their company account. The server then knows who sent each report and each audit event.

Kinds of token

TokenMade byCan
Admin tokenYou, at deployment (GITTA_TOKENS)Everything, including making and revoking other tokens. Keep these few and private.
Personal token, persongitta team token create, or gitta loginReport and read for one person. Expires, 365 days by default.
Personal token, runnergitta team token create --runnerThe same, for a CI runner or a cloud agent.

Personal tokens are signed with the servers' signing key. Any server with the same key accepts them, without a database. Nobody can change a token's name, email or expiry without breaking the signature.

Make personal tokens

 Terminal
$ export GITTA_ADMIN_TOKEN=<admin token>
$ gitta team token create --name "Anna Berg" --email [email protected]
Token for Anna Berg (person), id abLPQnzu755H, valid 365 days. Shown once; give it to them privately:

  gt1_eyJpZCI6ImFiTFBRbnp1NzU1SCIsIm5hbWUiOiJBbm5hIEJlcmciLCJlbWFpbCI6ImFubmFAZXhhbXBsZS5jb20i…

They run, in each repository:
  gitta init --server https://gitta-1.example.com --token <token>
$ gitta team token create --name "CI main" --runner --days 90

The person checks their identity:

 Terminal
$ gitta team whoami
Anna Berg (person, [email protected])

List and revoke

 Terminal
$ gitta team token list
0o8_cNUxje1E  runner  CI main                                               valid 89 more days
EeHOPq8J0EVZ  person  Ben Ek                   [email protected]              valid 364 more days
abLPQnzu755H  person  Anna Berg                [email protected]             valid 364 more days
$ gitta team token revoke 0o8_cNUxje1E
gitta: token 0o8_cNUxje1E revoked on 1 server(s)

Revocation works at once and lasts after a restart. With several servers, the command tells every one of them.

SSO

With single sign-on, people get their own token by signing in with the company account. gitta uses the OpenID Connect device flow of your identity provider, such as Okta, Microsoft Entra ID, Google or Keycloak.

 Terminal
$ gitta login --server https://gitta-1.example.com,https://gitta-2.example.com
Sign in with your company account:

  https://login.example.com/activate
  code: ABCD-EFGH

gitta: signed in as Anna Berg ([email protected])
gitta: this repository now reports as you; run `gitta login` in your other repositories, or `gitta init --server URL --token <token>`

The browser opens the sign-in page. The person signs in and confirms the code. gitta never sees the password.

Set it up

  1. At your identity provider, register an application for gitta. Allow the device authorization grant. Allow the scopes openid, email and profile.
  2. Set these values on every server.
    SettingExample
    GITTA_OIDC_ISSUERhttps://login.microsoftonline.com/<tenant>/v2.0, https://example.okta.com, https://accounts.google.com
    GITTA_OIDC_CLIENT_IDThe application's client ID
    GITTA_OIDC_DOMAINSexample.com. Only these email domains can sign in. Empty allows any.
    GITTA_OIDC_TENANTSMicrosoft Entra ID only, and required there. The tenant IDs that can sign in, comma separated. You find the tenant ID on the overview page of Entra ID.
    GITTA_OIDC_CLIENT_SECRETGoogle only, which needs it for the device flow. Google treats it as public for this kind of application.
    GITTA_OIDC_TOKEN_DAYSDays the issued token is valid. Default 30.
    With Helm, use the values sso.issuer, sso.clientId, sso.domains, sso.tenants, sso.clientSecret and sso.tokenDays.
  3. Restart the servers. They print the provider they use.
     Terminal
    gitta server: single sign-on through https://login.microsoftonline.com/<tenant>/v2.0

What the server checks

The server checks every sign-in itself. First it checks the signature against the provider's published keys, then the issuer, the application and the expiry. Then it checks who the person is. That part depends on the provider.

ProviderWhat the server accepts
Okta, Keycloak and other providersThe email claim, and only when email_verified is true. If the provider leaves email_verified out, the sign-in is refused.
GoogleThe same email check. When you set GITTA_OIDC_DOMAINS, the hd claim must also be one of those domains. So only accounts of your Google Workspace can sign in, and personal Gmail accounts can't.
Microsoft Entra IDThe tenant ID (tid) must be in GITTA_OIDC_TENANTS. The person is known by the object ID (oid), which never changes. Entra often sends no email_verified, so the server uses the email only when the xms_edov claim is true. That claim says the tenant has verified the email's domain. When you set GITTA_OIDC_DOMAINS, this verified email must be in one of them.

The server never uses preferred_username, upn or any other name field to decide who someone is. Users or tenant admins can set those to any address. Trusting them would let someone sign in as another person. This kind of attack is known as nOAuth.

Each token is tied to the account at the provider, which is the issuer plus sub, or the tenant plus oid for Entra ID. The email is only shown next to the name. If someone later changes their email to yours, they still sign in as themselves.

With Entra ID, add the optional claim xms_edov to the ID token in the app registration, under Token configuration. Add email too. Without them, people can still sign in, but you can't limit sign-in by email domain.

When the server refuses a sign-in, it says why, and it writes the same reason to its log. The log never holds the token or its claims. The servers' only outbound calls go to your identity provider, to read its published settings and keys.

CI runners and cloud agents

Store a runner token as a secret in the CI system. Set it with environment variables:

GITTA_SERVER=https://gitta-1.example.com,https://gitta-2.example.com
GITTA_SERVER_TOKEN=${{ secrets.GITTA_RUNNER_TOKEN }}
GITTA_MACHINE=ci-${{ github.run_id }}

Next, serve the team server over HTTPS with TLS, and read how several team servers share one signing key.