- Client ID from the identity provider (example: `headscale`).
- Client secret generated by the identity provider (example: `generated-secret`).
- Redirect URI for your identity provider (example: `https://headscale.example.com/oidc/callback`).
## Azure AD example
=== "Headscale"
In order to integrate headscale with Azure Active Directory, we'll need to provision an App Registration with the correct scopes and redirect URI. Here with Terraform:
```yaml
oidc:
issuer: "https://sso.example.com"
client_id: "headscale"
client_secret: "generated-secret"
```
```hcl title="terraform.hcl"
resource "azuread_application" "headscale" {
display_name = "Headscale"
=== "Identity provider"
sign_in_audience = "AzureADMyOrg"
fallback_public_client_enabled = false
* Create a new confidential client (`Client ID`, `Client secret`)
In order to integrate headscale with Google, you'll need to have a [Google Cloud Console](https://console.cloud.google.com) account.
```yaml hl_lines="5-7"
oidc:
issuer: "https://sso.example.com"
client_id: "headscale"
client_secret: "generated-secret"
allowed_users:
- "alice@example.com"
- "bob@example.net"
```
Google OAuth has a [verification process](https://support.google.com/cloud/answer/9110914?hl=en) if you need to have users authenticate who are outside of your domain. If you only need to authenticate users from your domain name (ie `@example.com`), you don't need to go through the verification process.
=== "Allowed groups"
However if you don't have a domain, or need to add users outside of your domain, you can manually add emails via Google Console.
* Use the OIDC `groups` claim of each authenticating user to get their group membership and only authorize users
which are members in at least one of the referenced groups.
* Access allowed: users in the `headscale_users` group
* Access denied: users without groups, users with other groups
### Steps
```yaml hl_lines="5-7"
oidc:
issuer: "https://sso.example.com"
client_id: "headscale"
client_secret: "generated-secret"
scope: ["openid", "profile", "email", "groups"]
allowed_groups:
- "headscale_users"
```
### Customize node expiration
The node expiration is the amount of time a node is authenticated with OpenID Connect until it expires and needs to
reauthenticate. The default node expiration is 180 days. This can either be customized or set to the expiration from the
Access Token.
=== "Customize node expiration"
```yaml hl_lines="5"
oidc:
issuer: "https://sso.example.com"
client_id: "headscale"
client_secret: "generated-secret"
expiry: 30d # Use 0 to disable node expiration
```
=== "Use expiration from Access Token"
Please keep in mind that the Access Token is typically a short-lived token that expires within a few minutes. You
will have to configure token expiration in your identity provider to avoid frequent reauthentication.
```yaml hl_lines="5"
oidc:
issuer: "https://sso.example.com"
client_id: "headscale"
client_secret: "generated-secret"
use_expiry_from_token: true
```
!!! tip "Expire a node and force re-authentication"
A node can be expired immediately via:
```console
headscale node expire -i <NODE_ID>
```
### Reference a user in the policy
You may refer to users in the Headscale policy via:
- Email address
- Username
- Provider identifier (only available in the database or from your identity provider)
!!! note "A user identifier in the policy must contain a single `@`"
The Headscale policy requires a single `@` to reference a user. If the username or provider identifier doesn't
already contain a single `@`, it needs to be appended at the end. For example: the username `ssmith` has to be
written as `ssmith@` to be correctly identified as user within the policy.
!!! warning "Email address or username might be updated by users"
Many identity providers allow users to update their own profile. Depending on the identity provider and its
configuration, the values for username or email address might change over time. This might have unexpected
consequences for Headscale where a policy might no longer work or a user might obtain more access by hijacking an
existing username or email address.
## Supported OIDC claims
Headscale uses [the standard OIDC claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) to
populate and update its local user profile on each login. OIDC claims are read from the ID Token or from the UserInfo
9. Take note of the `Client ID` and `Client secret`, you can also download it for reference if you need it.
10. Edit your headscale config, under `oidc`, filling in your `client_id` and `client_secret`:
```yaml title="config.yaml"
oidc:
issuer: "https://accounts.google.com"
client_id: ""
client_secret: ""
scope: ["openid", "profile", "email"]
```
10. [Configure Headscale following the "Basic configuration" steps](#basic-configuration). The issuer URL for Google
OAuth is: `https://accounts.google.com`.
You can also use `allowed_domains` and `allowed_users` to restrict the users who can authenticate.
### Kanidm
## Authelia
- Kanidm is fully supported by Headscale.
- Groups for the [allowed groups filter](#authorize-users-with-filters) need to be specified with their full SPN, for
example: `headscale_users@sso.example.com`.
Authelia since v4.39.0, has removed most claims from the `ID Token`, they are still available when application queries [UserInfo Endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo).
### Keycloak
Following config restores sending 'default' claims in the `ID Token`
Keycloak is fully supported by Headscale.
For more information please read: [Authelia restore functionality prior to claims parameter](https://www.authelia.com/integration/openid-connect/openid-connect-1.0-claims/#restore-functionality-prior-to-claims-parameter)
#### Additional configuration to use the allowed groups filter
```yaml
identity_providers:
oidc:
claims_policies:
default:
id_token:
[
"groups",
"email",
"email_verified",
"alt_emails",
"preferred_username",
"name",
]
clients:
- client_id: "headscale"
client_name: "headscale"
client_secret: ""
public: false
claims_policy: "default"
authorization_policy: "two_factor"
require_pkce: true
pkce_challenge_method: "S256"
redirect_uris:
- "https://headscale.example.com/oidc/callback"
scopes:
- "openid"
- "profile"
- "groups"
- "email"
userinfo_signed_response_alg: "none"
token_endpoint_auth_method: "client_secret_basic"
```
Keycloak has no built-in client scope for the OIDC `groups` claim. This extra configuration step is **only** needed if
you need to [authorize access based on group membership](#authorize-users-with-filters).
- Create a new client scope `groups` for OpenID Connect:
- Configure a `Group Membership` mapper with name `groups` and the token claim name `groups`.
- Enable the mapper for the ID Token, Access Token and UserInfo endpoint.
- Configure the new client scope for your Headscale client:
- Edit the Headscale client.
- Search for the client scope `group`.
- Add it with assigned type `Default`.
- [Configure the allowed groups in Headscale](#authorize-users-with-filters). Keep in mind that groups in Keycloak start
with a leading `/`.
### Microsoft Entra ID
In order to integrate Headscale with Microsoft Entra ID, you'll need to provision an App Registration with the correct
scopes and redirect URI.
[Configure Headscale following the "Basic configuration" steps](#basic-configuration). The issuer URL for Microsoft
Entra ID is: `https://login.microsoftonline.com/<tenant-UUID>/v2.0`. The following `extra_params` might be useful:
- `domain_hint: example.com` to use your own domain
- `prompt: select_account` to force an account picker during login
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.