Skip to content

Commit

Permalink
Document the new usptream OAuth 2.0 configuration options
Browse files Browse the repository at this point in the history
  • Loading branch information
sandhose committed Dec 17, 2024
1 parent afc3ae7 commit 9d84e84
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 7 deletions.
4 changes: 2 additions & 2 deletions crates/handlers/src/upstream_oauth2/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use minijinja::{
/// Context passed to the attribute mapping template
///
/// The variables available in the template are:
/// - `user`: claims for the user, currently from the ID token. Later, we'll
/// also allow importing from the userinfo endpoint
/// - `user`: claims for the user, merged from the ID token and userinfo endpoint
/// - `id_token_claims`: claims from the ID token
/// - `userinfo_claims`: claims from the userinfo endpoint
/// - `extra_callback_parameters`: extra parameters passed to the callback
#[derive(Debug, Default)]
pub(crate) struct AttributeMappingContext {
Expand Down
39 changes: 37 additions & 2 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,8 @@ upstream_oauth2:
# The issuer URL, which will be used to discover the provider's configuration.
# If discovery is enabled, this *must* exactly match the `issuer` field
# advertised in `<issuer>/.well-known/openid-configuration`.
issuer: https://example.com/
# It must be set if OIDC discovery is enabled (which is the default).
#issuer: https://example.com/

# A human-readable name for the provider,
# which will be displayed on the login page
Expand Down Expand Up @@ -569,8 +570,19 @@ upstream_oauth2:
# - `client_secret_post`
# - `client_secret_jwt`
# - `private_key_jwt` (using the keys defined in the `secrets.keys` section)
# - `sign_in_with_apple` (a special authentication method for Sign-in with Apple)
token_endpoint_auth_method: client_secret_post

# Additional paramaters for the `sign_in_with_apple` authentication method
# See https://www.oauth.com/oauth2-servers/pkce/authorization-code-flow-with-pkce/
#sign_in_with_apple:
# private_key: |
# -----BEGIN PRIVATE KEY-----
# ...
# -----END PRIVATE KEY-----
# team_id: "<team-id>"
# key_id: "<key-id>"

# Which signing algorithm to use to sign the authentication request when using
# the `private_key_jwt` or the `client_secret_jwt` authentication methods
#token_endpoint_auth_signing_alg: RS256
Expand All @@ -595,6 +607,19 @@ upstream_oauth2:
# - `never`: never use PKCE
#pkce_method: auto

# Whether to fetch user claims from the userinfo endpoint
# This is disabled by default, as most providers will return the necessary
# claims in the `id_token`
#fetch_userinfo: true

# If set, ask for a signed response on the userinfo endpoint, and validate
# the response uses the given algorithm
#userinfo_endpoint_auth_signing_alg: RS256

# The userinfo endpoint
# This takes precedence over the discovery mechanism
#userinfo_endpoint: https://example.com/oauth2/userinfo

# The provider authorization endpoint
# This takes precedence over the discovery mechanism
#authorization_endpoint: https://example.com/oauth2/authorize
Expand All @@ -607,6 +632,10 @@ upstream_oauth2:
# This takes precedence over the discovery mechanism
#jwks_uri: https://example.com/oauth2/keys

# Additional parameters to include in the authorization request
#additional_authorization_parameters:
# foo: "bar"

# How user attributes should be mapped
#
# Most of those attributes have two main properties:
Expand All @@ -617,7 +646,8 @@ upstream_oauth2:
# - `require`: always import the attribute, and fail if it's missing
# - `template`: a Jinja2 template used to generate the value. In this template,
# the `user` variable is available, which contains the user's attributes
# retrieved from the `id_token` given by the upstream provider.
# retrieved from the `id_token` given by the upstream provider and/or through
# the userinfo endpoint.
#
# Each attribute has a default template which follows the well-known OIDC claims.
#
Expand Down Expand Up @@ -654,6 +684,11 @@ upstream_oauth2:
# - `always`: mark the email address as verified
# - `never`: mark the email address as not verified
#set_email_verification: import

# An account name, for display purposes only
# This helps end user identify what account they are using
account_name:
#template: "@{{ user.preferred_username }}"
```

## `experimental`
Expand Down
70 changes: 67 additions & 3 deletions docs/setup/sso.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ The authentication service supports importing the following user attributes from
- The localpart/username (e.g. `@localpart:example.com`)
- The display name
- An email address
- An account name, to help end users identify what account they are using

For each of those attributes, administrators can configure a mapping using the claims provided by the upstream provider.
They can also configure what should be done for each of those attributes. It can either:
Expand All @@ -49,12 +50,20 @@ They can also configure what should be done for each of those attributes. It can
- `force`: automatically import the attribute, but don't fail if it is not provided by the provider
- `require`: automatically import the attribute, and fail if it is not provided by the provider

A Jinja2 template is used as mapping for each attribute. The template currently has one `user` variable, which is an object with the claims got through the `id_token` given by the provider.
A Jinja2 template is used as mapping for each attribute.
The following default templates are used:

- `localpart`: `{{ user.preferred_username }}`
- `displayname`: `{{ user.name }}`
- `email`: `{{ user.email }}`
- `account_name`: none

The template has the following variables available:

- `id_token_claims`: an object with the claims got through the `id_token` given by the provider, if provided by the provider
- `userinfo_claims`: an object with the claims got through the `userinfo` endpoint, if `fetch_userinfo` is enabled
- `user`: an object which contains the claims from both the `id_token` and the `userinfo` endpoint
- `extra_callback_parameters`: an object with the additional parameters the provider sent to the redirect URL

## Multiple providers behaviour

Expand Down Expand Up @@ -95,10 +104,14 @@ upstream_oauth2:
# SiWA passes down the user infos as query parameters in the callback
# which is available in the extra_callback_parameters variable
template: |
{%- set user = extra_callback_parameters["user"] | from_json -%}
{{- user.name.firstName }} {{ user.name.lastName -}}
{%- set u = extra_callback_parameters["user"] | from_json -%}
{{- u.name.firstName }} {{ u.name.lastName -}}
email:
action: suggest
account_name:
template: |
{%- set u = extra_callback_parameters["user"] | from_json -%}
{{- u.name.firstName }} {{ u.name.lastName -}}
```
### Authelia
Expand Down Expand Up @@ -230,6 +243,8 @@ upstream_oauth2:
action: suggest
template: "{{ user.email }}"
set_email_verification: always
account_name:
template: "{{ user.name }}"
```


Expand Down Expand Up @@ -261,6 +276,51 @@ upstream_oauth2:
email:
action: suggest
template: "{{ user.email }}"
account_name:
template: "@{{ user.preferred_username }}"
```

### GitHub

GitHub doesn't support OpenID Connect, but it does support OAuth 2.0.
It will use the `fetch_userinfo` option with a manual `userinfo_endpoint` to fetch the user's profile through the GitHub API.

1. Create a [new application](https://github.com/settings/applications/new).
2. Fill in the form with an application name and homepage URL.
3. Use the following Authorization callback URL: `https://<auth-service-domain>/upstream/callback/<id>`
4. Retrieve the Client ID
5. Generate a Client Secret and copy it

Authentication service configuration:

```yaml
upstream_oauth2:
providers:
- id: "01HFS67GJ145HCM9ZASYS9DC3J"
human_name: GitHub
brand_name: github
discovery_mode: disabled
fetch_userinfo: true
token_endpoint_auth_method: "client_secret_post"
client_id: "<client-id>" # TO BE FILLED
client_secret: "<client-secret>" # TO BE FILLED
authorization_endpoint: "https://github.com/login/oauth/authorize"
token_endpoint: "https://github.com/login/oauth/access_token"
userinfo_endpoint: "https://api.github.com/user"
scope: "read:user"
claims_imports:
subject:
template: "{{ userinfo_claims.id }}"
displayname:
action: suggest
template: "{{`{{ userinfo_claims.name }}"
localpart:
action: ignore
email:
action: suggest
template: "{{ userinfo_claims.email }}"
account_name:
template: "@{{ userinfo_claims.login }}"
```
Expand Down Expand Up @@ -291,6 +351,8 @@ upstream_oauth2:
email:
action: suggest
template: "{{ user.email }}"
account_name:
template: "{{ user.email }}"
```


Expand Down Expand Up @@ -384,4 +446,6 @@ upstream_oauth2:
action: suggest
template: "{{ user.email }}"
set_email_verification: always
account_name:
template: "{{ user.preferred_username }}"
```

0 comments on commit 9d84e84

Please sign in to comment.