# Sign in with GitCafe

GitCafe is an OpenID Connect provider. Your service can add a **Sign in with
GitCafe** button that tells you who the person is, and, in the same approval,
ask for access to their repositories. Any standard OpenID Connect client
library works; this guide shows the settings it needs.

## What you get

| You ask for                                    | The person approves                         | You receive                                                       |
| ---------------------------------------------- | ------------------------------------------- | ----------------------------------------------------------------- |
| `openid` (with `profile`, `email` as you need) | Who they are, nothing else                  | An ID token, and an access token that reads only userinfo         |
| `openid` plus repository permissions           | Who they are and the repositories they pick | An ID token, and an access token for the API, MCP or Git          |
| Repository permissions alone                   | The repositories they pick                  | An access token, as for [MCP apps](https://mn.staging.git.cafe/docs/account/mcp-connections.md) |

A sign-in alone never shows a repository picker: the consent screen lists only
what you learn about the person, and says you cannot read their repositories.

## Discovery

Point your library at the issuer `https://git.cafe`. It reads
`https://git.cafe/.well-known/openid-configuration`, which names:

| Field                    | Value                                     |
| ------------------------ | ----------------------------------------- |
| `authorization_endpoint` | `https://git.cafe/api/oauth/authorize`    |
| `token_endpoint`         | `https://git.cafe/api/oauth/token`        |
| `userinfo_endpoint`      | `https://git.cafe/api/oauth/userinfo`     |
| `jwks_uri`               | `https://git.cafe/api/oauth/jwks`         |
| `registration_endpoint`  | `https://git.cafe/api/oauth/register`     |
| ID token signature       | `RS256`                                   |
| Client authentication    | `none`: public clients with PKCE (`S256`) |

## Register your client

Clients are public: there is no client secret, and every authorization uses
PKCE with `S256`. Register once and keep the `client_id`:

```sh
curl -X POST https://git.cafe/api/oauth/register \
  -H 'content-type: application/json' \
  -d '{"client_name":"Tripwire","redirect_uris":["https://tripwire.sh/auth/callback/gitcafe"]}'
```

The redirect URI must match exactly on every request. A registered
[app](https://mn.staging.git.cafe/docs/integrations/apps.md) can instead use the client its publisher registers in the app's
settings, which names the app and its publisher on the consent screen; an
unregistered client is shown as unverified.

## Scopes

| Scope     | Claims in the ID token and userinfo                         |
| --------- | ----------------------------------------------------------- |
| `openid`  | `sub`: the person's GitCafe account ID, which never changes |
| `profile` | `preferred_username`, `name`, `picture`, `profile`          |
| `email`   | `email`, `email_verified`                                   |

Use `sub` as the account key. Usernames can change; the ID cannot, and is never
given to anyone else.

To ask for repository access in the same approval, add permission scopes
(`repo:contents:read`, `issue:contents:write` and the others in
`scopes_supported`) and a `resource` naming where the token is used:
`https://git.cafe/api`, `https://git.cafe/mcp` or, for an app, `https://git.cafe/git`.
A sign-in alone needs no `resource`.

## Tokens

The token response carries `id_token` whenever the approval included
`openid`. The ID token is valid for 10 minutes and carries `iss`, `aud` (your
client ID), `exp`, `iat`, your `nonce` and `at_hash`; verify it against the
JWKS. Access tokens last at most 15 minutes. A refresh returns a new ID token
for the same person, without a `nonce`.

`GET` or `POST` to userinfo with `Authorization: Bearer <access token>`
returns the claims the person approved. Any live access token from the
connection works there; a sign-in's token works nowhere else.

The connection lasts until the person removes it in
[Authorized apps](https://mn.staging.git.cafe/docs/account/mcp-connections.md#review-or-revoke-access) or leaves
it unused for 90 days.

## Library settings

Auth.js (NextAuth):

```ts
{
  id: "gitcafe",
  name: "GitCafe",
  type: "oidc",
  issuer: "https://git.cafe",
  clientId: process.env.GITCAFE_CLIENT_ID,
  client: { token_endpoint_auth_method: "none" },
  checks: ["pkce", "state", "nonce"],
  authorization: { params: { scope: "openid profile email" } },
}
```

`openid-client` (Node):

```ts
const config = await client.discovery(
  new URL("https://git.cafe"),
  process.env.GITCAFE_CLIENT_ID,
  undefined,
  client.None(),
);
```

Other libraries need the same four things: the issuer, the client ID, no
client secret (`token_endpoint_auth_method` `none`) and PKCE.

## Brand

Label the button **Sign in with GitCafe**, with the GitCafe name and its square
mark. In monochrome the mark is a plain filled square.
