# OpenID Connect

Use OpenID Connect to let people log in to your app with their Street Art Cities account.

Want people to log in to your app with their Street Art Cities account? We support [OpenID Connect](https://openid.net/developers/how-connect-works/), so most login libraries can do this for you: give them `https://streetartcities.com` as the issuer, and they'll find everything else in our discovery document:

```text
https://streetartcities.com/.well-known/openid-configuration
```

## How it works

It's the same [OAuth flow](/authentication/oauth-flow/), with one or more of these scopes:

| Scope     | What your app gets                                                    |
| --------- | --------------------------------------------------------------------- |
| `openid`  | An ID token that says who the person is. Always needed for logging in |
| `profile` | Their name, username, profile picture and a link to their profile     |
| `email`   | Their email address, and whether they've confirmed it                 |

You can combine them with API scopes, like `openid profile collections:read`.

When your request includes `openid`, the token response also has an `id_token`:

```json
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "Yh1c...",
  "scope": "openid profile email",
  "id_token": "eyJhbGciOi..."
}
```

## The ID token

The ID token is a JWT signed with RS256. Before trusting it, check that:

- the signature matches one of the keys in our [JWKS](https://streetartcities-production-auth.s3-eu-west-1.amazonaws.com/.well-known/jwks.json)
- `iss` is `https://streetartcities.com`
- `aud` is your client ID
- `exp` hasn't passed
- `nonce` matches the one you sent, if you sent one

Send a random `nonce` to the authorize page, and we'll put it in the ID token. That stops someone from replaying an old token.

```json
{
  "iss": "https://streetartcities.com",
  "sub": "9b1c0e2f-…",
  "aud": "YOUR_CLIENT_ID",
  "exp": 1790000000,
  "iat": 1789996400,
  "nonce": "n-0S6_WzA2Mj",
  "name": "Ada L.",
  "preferred_username": "ada",
  "profile": "https://streetartcities.com/@ada",
  "picture": "https://…/512.jpg",
  "email": "ada@example.com",
  "email_verified": true
}
```

Use `sub` to recognise people: it never changes, unlike their username or email address.

## The userinfo endpoint

You can also get the same details with the access token:

```bash
curl https://streetartcities.com/api/oauth/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

This needs the `openid` scope, and only returns the details the person agreed to share.

<Admonition kind="tip" title="Keep them logged in">
  Refreshing the access token also gives you a new ID token, with up-to-date
  details. See [tokens](/authentication/tokens/).
</Admonition>
