Skip to content

[Feature] Configurable OIDC username mapping (fallback when preferred_username is missing) #3002

@angelbarrera92

Description

@angelbarrera92

Use case

When Headscale is configured with Google (or other IdPs that don’t emit preferred_username), the user record may be created without a usable username. This causes friction when:

  • Writing ACLs that reference users by username.
  • Generating predictable MagicDNS names that depend on usernames.
  • Operating CLIs/UX where usernames are shown or selected.

A configurable mapping from OIDC claims would let operators decide which claim(s) should define the username (e.g., email local-part), avoiding incomplete users and ACL hassles.

Description

Introduce an optional setting to control how a username is derived from OIDC claims, trying candidates in order until one is valid:

  • Config: oidc.username_claim_order (array of strings)
  • Supported values:
    • preferred_username (OIDC standard)
    • email_localpart (portion before @)
    • email (full email address)
    • name (display name)
    • sub (subject/ID)
  • Default order (if unset): [preferred_username, email_localpart, email, name, sub]
  • Validation: candidates must pass Headscale’s ValidateUsername (start with a letter; letters, digits, -, ., _; at most one @). Invalid candidates are skipped.

This keeps current behavior for IdPs that already provide a valid preferred_username, and provides a safe, opinionated fallback path for providers like Google.

Contribution

  • I can write the design doc for this feature
  • I can contribute this feature

How can it be implemented?

Suggested approach (for the design doc):

  • Add UsernameClaimOrder []string to OIDCConfig with YAML key username_claim_order.
  • Implement a helper that derives a username from OIDCClaims using the configured order and ValidateUsername.
  • Apply the helper in the OIDC callback flow before persisting/updating the user.
  • Tests covering: preferred_username present; fallback to email local-part; email/name/sub fallbacks; validation rejections.
  • Docs: configuration reference, OIDC guide (with a Google note and example configuration).

Metadata

Metadata

Assignees

No one assigned

    Labels

    OIDCOpenID Connect related issuesenhancementNew feature or requeststale

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions