Learn Authelia - OIDC Scopes & Claims
Episode 18 of 31

Learn Authelia - OIDC Scopes & Claims

This episode dissects OpenID Connect scopes and claims: standard scopes like openid, profile, email, groups, and offline_access, how claims are mapped from user attributes, per-client scope and audience configuration, custom scopes, up to an example of the token contents Authelia issues.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 17 you registered your first OIDC client: there's a client_id, client_secret, redirect_uris, and a scopes list. But what exactly is a client asking for when it requests the email or groups scope? In episode 18 we dissect scopes and claims — the two concepts that determine what identity data an application is allowed to read.

An analogy is giving a friend permission to borrow your car. Agreeing to "take the car" and agreeing to "take the car until the gas runs out" are two very different permissions. Scope is the permission list in OIDC's language; claims are the data that comes out once that permission is granted.

Scope and Claim, Two Sides of the Same Coin

  • Scope is a permission request a client sends when redirecting a user to Authelia, usually via the scope parameter on the authorization request.
  • Claim is a statement about the user that ends up in the token, like name, email, or groups.

The relationship is one-way: scope requests a group of data, claims are the contents of that group. The email scope requests the right to read the email and email_verified claims. Understanding this pair matters because Authelia only issues claims according to the scopes allowed for that client — the principle of least privilege at the token level.

Standard Scopes Supported by Authelia

ScopeMain ClaimsPurpose
openidsubUser identity; required in every OIDC request
profilename, preferred_usernameBasic profile data
emailemail, email_verifiedEmail address and its verification status
groupsgroupsList of the user's group memberships
offline_accessRefresh token permissionLong sessions without re-interaction
addressaddressUser's address
phonephone_numberPhone number

Not every client needs every scope. A dashboard-like client that only displays a name can be given just openid and profile. Giving excessive scopes to all clients is like giving every employee a key to every room.

openid: The Required Scope

The openid scope is the only one that's absolutely necessary for a request to be considered an OpenID Connect request; without it, the request is just plain OAuth 2.0. This scope provides the sub claim, a unique user identifier in the form of a UUID v4.

Important

Use sub as the account relation key in your applications, not email or preferred_username. sub is guaranteed unique and stable; email addresses can change, while sub doesn't. This is an official Authelia recommendation.

Claims from profile, email, and groups

Those scopes translate user attributes in users_database.yml into claims:

  • preferred_username — the username used at login.
  • name — the display name; if the display_name attribute is empty, Authelia uses preferred_username as a fallback.
  • email and email_verified — from the email attribute on the account.
  • groups — the list of groups the user belongs to.

Because of the fallback, an integration doesn't immediately break when profile data isn't complete. This makes Authelia friendly for phased deployments.

Configuring Scopes per Client

The scopes a client may request are configured per client via the scopes list. Authelia's default is openid, groups, profile, and email. To restrict a client to only minimal data:

configuration.yml — limit scope per client
identity_providers:
  oidc:
    clients:
      - id: client-minimal
        description: Only needs basic identity
        secret: '$plaintext$client-secret'
        redirect_uris:
          - https://app.example.com/callback
        scopes:
          - openid
          - email
        grant_types:
          - authorization_code
          - refresh_token
        response_types:
          - code

That client can't request groups or profile, even if its application tries. Authelia rejects unregistered scopes — the door is precise, not a master key.

Custom Scopes

Sometimes we want a scope that groups several claims at once. Authelia supports this via mapping a scope name to a list of claims at the provider level:

configuration.yml — custom scope
identity_providers:
  oidc:
    scopes:
      authelia:full-profile:
        - name
        - given_name
        - family_name
        - groups
        - email_verified
    clients:
      - id: client-a
        secret: '$plaintext$client-secret'
        scopes:
          - openid
          - authelia:full-profile
        redirect_uris:
          - https://a.example.com/callback

Other clients still have to list that scope in their own scopes list. Custom scopes aren't automatically available to everyone.

Audience: Locking Tokens to Specific Recipients

The aud claim tells you who the token was created for. By default it's the client identifier. If an access token will be used by another service, for example a backend API, register the audience via the audience list:

configuration.yml — audience per client
identity_providers:
  oidc:
    clients:
      - id: frontend-a
        secret: '$plaintext$client-secret'
        redirect_uris:
          - https://a.example.com/callback
        audience:
          - https://api.example.com
          - https://backoffice.example.com

Audience behavior is controlled via requested_audience_mode:

  • explicit (default) — an audience is included in the token only if the client actually requests it.
  • implicit — if a client is entitled to all audiences and doesn't mention a specific audience, all registered audiences are considered requested.

A backend API can reject tokens whose aud doesn't match, just like an airport officer checks the destination on a boarding pass.

Example Token Contents

After the flow completes, an ID token contains claims like this (values simplified):

Example ID token contents
{
  "iss": "https://auth.example.com",
  "sub": "6f3c2d58-4a1e-4b9c-8d7e-1f2a3b4c5d6e",
  "aud": "client-a",
  "exp": 1783245600,
  "iat": 1783242000,
  "auth_time": 1783241900,
  "nonce": "s9kdj2n29fn0a2k3",
  "amr": ["pwd", "totp"],
  "name": "Arman Dwi Pangestu",
  "preferred_username": "arman",
  "email": "arman@example.com",
  "email_verified": true,
  "groups": ["admin", "devops"]
}

Note amr — it contains the authentication methods used, like pwd for password and totp for TOTP. Applications can use this value to reject logins that didn't pass MFA.

Verifying via the Discovery Endpoint

Authelia announces all supported scopes at the discovery endpoint. Check it with curl:

View the OIDC metadata
curl -s https://auth.example.com/.well-known/openid-configuration

Then filter the result with jq .scopes_supported to see the list offline_access, openid, profile, email, address, phone, and groups. This is the first place to check when a client fails because of an unrecognized scope.

Tip

Start with the smallest scope that an application truly needs, then add as features require. A token with excessive claims is as risky as giving the warehouse key when only the locker key was requested.

Closing

In this episode you understood:

  • Scope is permission, claims are data; the openid scope is required and provides sub.
  • profile, email, and groups map user attributes into claims applications can read.
  • Scopes are limited per client, and custom scopes allow grouping claims.
  • Audience locks tokens to specific recipients with the explicit or implicit mode.

Armed with this, you're ready to connect real applications. In episode 19, we practice directly integrating real clients like Grafana, Gitea or Forgejo, Nextcloud, and Portainer with Authelia as the identity provider. See you there!

Learn Authelia - OIDC Scopes & Claims | Learn Authelia