[Bug] Cannot create preauth keys for users without username #980

Closed
opened 2025-12-29 02:27:00 +01:00 by adam · 3 comments
Owner

Originally created by @paapug on GitHub (Mar 19, 2025).

Is this a support request?

  • This is not a support request

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When using Google as OIDC it's not possible to create a preshared key. This is because Google does not provide username (as stated by @kradalby in #2333).

Expected Behavior

The headscale preauthkeys create command should fallback to user e-mail (or id) if it cannot find user by username.

Steps To Reproduce

  1. Configure headscale with Google OIDC as per documentation: https://headscale.net/stable/ref/oidc/#google-oauth-example
  2. Create a new user via OIDC
ID | Name             | Username | Email                            | Created            
1  | My User          |          | my.user@example.com     | 2025-03-19 12:41:30
- id: 1
  name: ""
  createdat:
    seconds: 1742388090
    nanos: 923918172
  displayname: My User
  email: my.user@example.com
  providerid: <url to https://accounts.google.com>
  provider: oidc
  profilepicurl: <url to https://lh3.googleusercontent.com>
  1. Try to create a preshared key
sudo headscale preauthkeys create  -u my.user@example.com
2025-03-19T13:27:17Z TRC expiration has been set expiration=3600000
Cannot create Pre Auth Key: rpc error: code = Unknown desc = user not found
sudo headscale preauthkeys create  -u 1
2025-03-19T13:27:17Z TRC expiration has been set expiration=3600000
Cannot create Pre Auth Key: rpc error: code = Unknown desc = user not found

Environment

- OS: Debian 12
- Headscale version: 0.25.1
- Tailscale version: N/A

Runtime environment

  • Headscale is behind a (reverse) proxy
  • Headscale runs in a container

Debug information

oidc:
  issuer: "https://accounts.google.com"
  client_id: "<my client id>"
  client_secret: "<my client secret>"
  scope: ["openid", "profile", "email"]
Originally created by @paapug on GitHub (Mar 19, 2025). ### Is this a support request? - [x] This is not a support request ### Is there an existing issue for this? - [x] I have searched the existing issues ### Current Behavior When using Google as OIDC it's not possible to create a preshared key. This is because Google does not provide username (as stated by @kradalby in #2333). ### Expected Behavior The `headscale preauthkeys create` command should fallback to user e-mail (or id) if it cannot find user by username. ### Steps To Reproduce 1. Configure headscale with Google OIDC as per documentation: https://headscale.net/stable/ref/oidc/#google-oauth-example 2. Create a new user via OIDC ``` ID | Name | Username | Email | Created 1 | My User | | my.user@example.com | 2025-03-19 12:41:30 ``` ``` - id: 1 name: "" createdat: seconds: 1742388090 nanos: 923918172 displayname: My User email: my.user@example.com providerid: <url to https://accounts.google.com> provider: oidc profilepicurl: <url to https://lh3.googleusercontent.com> ``` 3. Try to create a preshared key ``` sudo headscale preauthkeys create -u my.user@example.com 2025-03-19T13:27:17Z TRC expiration has been set expiration=3600000 Cannot create Pre Auth Key: rpc error: code = Unknown desc = user not found ``` ``` sudo headscale preauthkeys create -u 1 2025-03-19T13:27:17Z TRC expiration has been set expiration=3600000 Cannot create Pre Auth Key: rpc error: code = Unknown desc = user not found ``` ### Environment ```markdown - OS: Debian 12 - Headscale version: 0.25.1 - Tailscale version: N/A ``` ### Runtime environment - [ ] Headscale is behind a (reverse) proxy - [ ] Headscale runs in a container ### Debug information ``` oidc: issuer: "https://accounts.google.com" client_id: "<my client id>" client_secret: "<my client secret>" scope: ["openid", "profile", "email"] ```
adam added the bug label 2025-12-29 02:27:00 +01:00
adam closed this issue 2025-12-29 02:27:00 +01:00
Author
Owner

@paapug commented on GitHub (Mar 19, 2025):

Perhaps one solution would be to use user email as username if the OIDC provider does not provide preferred_username?

func (u *User) FromClaim(claims *OIDCClaims) {
	username := claims.Username
	// Some providers does not provide preferred_username (e.g. Google), so we use the email.
	if username == "" {
		username = claims.Email
	}

	err := util.ValidateUsername(username)
	if err == nil {
		u.Name = username
	} else {
		log.Debug().Err(err).Msgf("Username %s is not valid", username)
	}

	if claims.EmailVerified {
		_, err := mail.ParseAddress(claims.Email)
		if err == nil {
			u.Email = claims.Email
		}
	}

	u.ProviderIdentifier = sql.NullString{String: claims.Identifier(), Valid: true}
	u.DisplayName = claims.Name
	u.ProfilePicURL = claims.ProfilePictureURL
	u.Provider = util.RegisterMethodOIDC
}
@paapug commented on GitHub (Mar 19, 2025): Perhaps one solution would be to use user email as username if the OIDC provider does not provide `preferred_username`? ``` func (u *User) FromClaim(claims *OIDCClaims) { username := claims.Username // Some providers does not provide preferred_username (e.g. Google), so we use the email. if username == "" { username = claims.Email } err := util.ValidateUsername(username) if err == nil { u.Name = username } else { log.Debug().Err(err).Msgf("Username %s is not valid", username) } if claims.EmailVerified { _, err := mail.ParseAddress(claims.Email) if err == nil { u.Email = claims.Email } } u.ProviderIdentifier = sql.NullString{String: claims.Identifier(), Valid: true} u.DisplayName = claims.Name u.ProfilePicURL = claims.ProfilePictureURL u.Provider = util.RegisterMethodOIDC } ```
Author
Owner

@idefixcert commented on GitHub (Apr 6, 2025):

My question is if I could contribute the following change:
Calculate the username from the token user if the preffered_username is not set.
-> https://github.com/juanfont/headscale/compare/main...idefixcert:headscale:oidc_username

@idefixcert commented on GitHub (Apr 6, 2025): My question is if I could contribute the following change: Calculate the username from the token user if the preffered_username is not set. -> https://github.com/juanfont/headscale/compare/main...idefixcert:headscale:oidc_username
Author
Owner

@kradalby commented on GitHub (Apr 7, 2025):

I don’t think it is ideal to have a lot of branching and different behaviours for all sorts of different conditions, so no, I would prefer to not add things based on the name.

@kradalby commented on GitHub (Apr 7, 2025): I don’t think it is ideal to have a lot of branching and different behaviours for all sorts of different conditions, so no, I would prefer to not add things based on the name.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#980