mirror of
https://github.com/tale/headplane.git
synced 2026-07-26 07:48:14 +00:00
feat: add OIDC subject claim fallbacks
This commit is contained in:
@@ -98,6 +98,7 @@ const oidcConfig = type({
|
||||
.optional(),
|
||||
disable_api_key_login: "boolean = false",
|
||||
scope: 'string = "openid email profile"',
|
||||
subject_claims: "string[]?",
|
||||
profile_picture_source: '"oidc" | "gravatar" = "oidc"',
|
||||
extra_params: "Record<string, string>?",
|
||||
|
||||
@@ -120,6 +121,7 @@ const partialOidcConfig = type({
|
||||
redirect_uri: "string.url?",
|
||||
disable_api_key_login: "boolean?",
|
||||
scope: "string?",
|
||||
subject_claims: "string[]?",
|
||||
extra_params: "Record<string, string>?",
|
||||
profile_picture_source: '"oidc" | "gravatar"?',
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ const appLoadContext = {
|
||||
: config.oidc.token_endpoint_auth_method,
|
||||
usePkce: config.oidc.use_pkce,
|
||||
scope: config.oidc.scope,
|
||||
subjectClaims: config.oidc.subject_claims,
|
||||
extraParams: config.oidc.extra_params,
|
||||
profilePictureSource: config.oidc.profile_picture_source,
|
||||
}),
|
||||
|
||||
@@ -217,6 +217,13 @@ integration:
|
||||
# The scopes to request when authenticating users. The default is below.
|
||||
# scope: "openid email profile"
|
||||
|
||||
# Optional fallback claims to use when your provider does not return a standard
|
||||
# OIDC `sub` claim. Headplane always checks `sub` first, then each claim here
|
||||
# in order. For Feishu/Lark, `["open_id", "email"]` is a reasonable fallback.
|
||||
# subject_claims:
|
||||
# - "open_id"
|
||||
# - "email"
|
||||
|
||||
# Extra query parameters can be passed to the authorization endpoint
|
||||
# by setting them here. This is useful for providers that require any kind
|
||||
# of custom hinting.
|
||||
|
||||
@@ -70,6 +70,7 @@ oidc:
|
||||
# token_endpoint: ""
|
||||
# userinfo_endpoint: ""
|
||||
# scope: "openid email profile"
|
||||
# subject_claims: ["open_id", "email"]
|
||||
# extra_params:
|
||||
# foo: "bar"
|
||||
```
|
||||
@@ -78,6 +79,22 @@ Headplane automatically discovers OIDC endpoints from your issuer's
|
||||
`/.well-known/openid-configuration`. If your IdP does not support discovery,
|
||||
you'll need to set the endpoints manually.
|
||||
|
||||
### Non-standard Subject Claims
|
||||
|
||||
Some providers do not return the standard OIDC `sub` claim in the ID token.
|
||||
Headplane always uses `sub` first, but you can configure fallback claims with
|
||||
`oidc.subject_claims`.
|
||||
|
||||
For Feishu/Lark, the recommended configuration is:
|
||||
|
||||
```yaml
|
||||
oidc:
|
||||
subject_claims: ["open_id", "email"]
|
||||
```
|
||||
|
||||
This keeps identity matching stable by preferring `open_id` and only falling
|
||||
back to `email` if needed.
|
||||
|
||||
### PKCE
|
||||
|
||||
::: warning
|
||||
|
||||
@@ -112,6 +112,24 @@ describe("Configuration YAML file loading", () => {
|
||||
expect(config.oidc?.enabled).toBe(false);
|
||||
});
|
||||
|
||||
test("oidc.subject_claims can be configured from YAML", async () => {
|
||||
const filePath = "/config/oidc-subject-claims.yaml";
|
||||
writeYaml(filePath, {
|
||||
headscale: { url: "http://localhost:8080" },
|
||||
server: { cookie_secret: "thirtytwo-character-cookiesecret" },
|
||||
oidc: {
|
||||
issuer: "https://accounts.google.com",
|
||||
client_id: "my-client-id",
|
||||
client_secret: "my-client-secret",
|
||||
headscale_api_key: "my-api-key",
|
||||
subject_claims: ["open_id", "email"],
|
||||
},
|
||||
});
|
||||
|
||||
const config = await loadConfig(filePath);
|
||||
expect(config.oidc?.subject_claims).toEqual(["open_id", "email"]);
|
||||
});
|
||||
|
||||
test("partial oidc config with enabled field can be parsed", async () => {
|
||||
const filePath = "/config/oidc-partial.yaml";
|
||||
writeYaml(filePath, {
|
||||
|
||||
Reference in New Issue
Block a user