mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-23 18:15:26 +00:00
138 lines
4.1 KiB
Markdown
138 lines
4.1 KiB
Markdown
|
# Configuring Headscale to use OIDC authentication
|
|||
|
|
|||
|
In order to authenticate users through a centralized solution one must enable the OIDC integration.
|
|||
|
|
|||
|
Known limitations:
|
|||
|
|
|||
|
- No dynamic ACL support
|
|||
|
- OIDC groups cannot be used in ACLs
|
|||
|
|
|||
|
## Basic configuration
|
|||
|
|
|||
|
In your `config.yaml`, customize this to your liking:
|
|||
|
|
|||
|
```yaml
|
|||
|
oidc:
|
|||
|
# Block further startup until the OIDC provider is healthy and available
|
|||
|
only_start_if_oidc_is_available: true
|
|||
|
# Specified by your OIDC provider
|
|||
|
issuer: "https://your-oidc.issuer.com/path"
|
|||
|
# Specified/generated by your OIDC provider
|
|||
|
client_id: "your-oidc-client-id"
|
|||
|
client_secret: "your-oidc-client-secret"
|
|||
|
|
|||
|
# Customize the scopes used in the OIDC flow, defaults to "openid", "profile" and "email" and add custom query
|
|||
|
# parameters to the Authorize Endpoint request. Scopes default to "openid", "profile" and "email".
|
|||
|
scope: ["openid", "profile", "email", "custom"]
|
|||
|
# Optional: Passed on to the browser login request – used to tweak behaviour for the OIDC provider
|
|||
|
extra_params:
|
|||
|
domain_hint: example.com
|
|||
|
|
|||
|
# Optional: List allowed principal domains and/or users. If an authenticated user's domain is not in this list,
|
|||
|
# the authentication request will be rejected.
|
|||
|
allowed_domains:
|
|||
|
- example.com
|
|||
|
# Optional. Note that groups from Keycloak have a leading '/'.
|
|||
|
allowed_groups:
|
|||
|
- /headscale
|
|||
|
# Optional.
|
|||
|
allowed_users:
|
|||
|
- alice@example.com
|
|||
|
|
|||
|
# If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed.
|
|||
|
# This will transform `first-name.last-name@example.com` to the namespace `first-name.last-name`
|
|||
|
# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following
|
|||
|
# namespace: `first-name.last-name.example.com`
|
|||
|
strip_email_domain: true
|
|||
|
```
|
|||
|
|
|||
|
## Azure AD example
|
|||
|
|
|||
|
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:
|
|||
|
|
|||
|
```hcl
|
|||
|
resource "azuread_application" "headscale" {
|
|||
|
display_name = "Headscale"
|
|||
|
|
|||
|
sign_in_audience = "AzureADMyOrg"
|
|||
|
fallback_public_client_enabled = false
|
|||
|
|
|||
|
required_resource_access {
|
|||
|
// Microsoft Graph
|
|||
|
resource_app_id = "00000003-0000-0000-c000-000000000000"
|
|||
|
|
|||
|
resource_access {
|
|||
|
// scope: profile
|
|||
|
id = "14dad69e-099b-42c9-810b-d002981feec1"
|
|||
|
type = "Scope"
|
|||
|
}
|
|||
|
resource_access {
|
|||
|
// scope: openid
|
|||
|
id = "37f7f235-527c-4136-accd-4a02d197296e"
|
|||
|
type = "Scope"
|
|||
|
}
|
|||
|
resource_access {
|
|||
|
// scope: email
|
|||
|
id = "64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0"
|
|||
|
type = "Scope"
|
|||
|
}
|
|||
|
}
|
|||
|
web {
|
|||
|
# Points at your running Headscale instance
|
|||
|
redirect_uris = ["https://headscale.example.com/oidc/callback"]
|
|||
|
|
|||
|
implicit_grant {
|
|||
|
access_token_issuance_enabled = false
|
|||
|
id_token_issuance_enabled = true
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
group_membership_claims = ["SecurityGroup"]
|
|||
|
optional_claims {
|
|||
|
# Expose group memberships
|
|||
|
id_token {
|
|||
|
name = "groups"
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
resource "azuread_application_password" "headscale-application-secret" {
|
|||
|
display_name = "Headscale Server"
|
|||
|
application_object_id = azuread_application.headscale.object_id
|
|||
|
}
|
|||
|
|
|||
|
resource "azuread_service_principal" "headscale" {
|
|||
|
application_id = azuread_application.headscale.application_id
|
|||
|
}
|
|||
|
|
|||
|
resource "azuread_service_principal_password" "headscale" {
|
|||
|
service_principal_id = azuread_service_principal.headscale.id
|
|||
|
end_date_relative = "44640h"
|
|||
|
}
|
|||
|
|
|||
|
output "headscale_client_id" {
|
|||
|
value = azuread_application.headscale.application_id
|
|||
|
}
|
|||
|
|
|||
|
output "headscale_client_secret" {
|
|||
|
value = azuread_application_password.headscale-application-secret.value
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
And in your Headscale `config.yaml`:
|
|||
|
|
|||
|
```yaml
|
|||
|
oidc:
|
|||
|
issuer: "https://login.microsoftonline.com/<tenant-UUID>/v2.0"
|
|||
|
client_id: "<client-id-from-terraform>"
|
|||
|
client_secret: "<client-secret-from-terraform>"
|
|||
|
|
|||
|
# Optional: add "groups"
|
|||
|
scope: ["openid", "profile", "email"]
|
|||
|
extra_params:
|
|||
|
# Use your own domain, associated with Azure AD
|
|||
|
domain_hint: example.com
|
|||
|
# Optional: Force the Azure AD account picker
|
|||
|
prompt: select_account
|
|||
|
```
|