Summary
For generic OIDC (authd-oidc), the Linux username is derived from the OIDC email claim today (genericprovider.GetUserInfo → info.NewUser(userClaims.Email, …)). That yields full email-shaped usernames such as alex.garcia@wayve.ai, which propagate into passwd entries and homedirs like /home/alex.garcia@wayve.ai.
Long-running upstream discussions (#574, #1317, #508) explore naming policy and broker UX, but enterprises remain blocked today: IdPs commonly issue email-shaped identities, and downstream tooling assumes POSIX-safe login names without @.
We propose an opt-in [users] knob in broker.conf:
use_short_usernames (bool, default false): when true, strip the @domain suffix by cutting at the first @. The strip happens at the very top of finishAuth, before the owner auto-registration call (b.cfg.registerOwner), the allowed-users check (b.userNameIsAllowed), and the b.isOwner-driven owner_extra_groups merge. That ordering is important: it ensures all three name-based steps see a consistent stripped name, so the value persisted to broker.conf as owner= matches what b.isOwner(authInfo.UserInfo.Name) checks on subsequent logins, and so operators write short forms in allowed_users without surprise.
The UUID/sub claim is untouched (authInfo.UserInfo.UUID remains the canonical identity key for the daemon's user mapping).
Versions / context
authd-oidc-brokers on a branch carrying #1476 (email verification via /userinfo where needed) and the dedupe-groups fix from #1496.
Failure modes the @-suffix causes today
- Azure CLI rejects
@ in certain --user / principal contexts; $USER interpolation breaks scripted Azure workflows.
- URLs and tooling that interpret
@ as URI userinfo (scheme://user@host) mis-parse paths or logs containing $HOME.
- Paths under
/home/ with @ confuse editors, SSH wrappers, and legacy scripts that split fields naïvely.
- NSS/GECOS/PAM: operational surprises when integrators assume
$USER matches typical Unix [a-z_][a-z0-9_-]* conventions.
Concrete behaviour
|
Before |
After (use_short_usernames = true) |
Linux login / NSS name |
alex.garcia@wayve.ai |
alex.garcia |
Homedir (under home_base_dir) |
/home/alex.garcia@wayve.ai |
/home/alex.garcia |
Guard: only strip when the first @ is not at index 0 (so a pathological @something does not yield an empty username — falls through to the original name in that case).
Proposed patch (unified diff)
Applies on top of #1476 after the dedupe-groups fix (#1496 style).
diff --git a/authd-oidc-brokers/internal/broker/broker.go b/authd-oidc-brokers/internal/broker/broker.go
--- a/authd-oidc-brokers/internal/broker/broker.go
+++ b/authd-oidc-brokers/internal/broker/broker.go
@@ -920,6 +920,24 @@ func (b *Broker) passwordAuth(ctx context.Context, session *session, secret stri
}
func (b *Broker) finishAuth(session *session, authInfo *token.AuthCachedInfo) (string, isAuthenticatedDataResponse) {
+ // Apply use_short_usernames before any name-based logic (owner auto-registration,
+ // allowed-users check, isOwner matching) so they all see a consistent stripped name.
+ // Opt-in via [users] use_short_usernames in broker.conf — default off preserves
+ // current behavior. The Home rewrite is defensive: today the generic provider passes
+ // userClaims.Home through (empty unless the IdP sends a "home" claim), so the home
+ // path under home_base_dir is computed downstream from the (now stripped) Name.
+ if b.cfg.useShortUsernames {
+ name := authInfo.UserInfo.Name
+ if i := strings.Index(name, "@"); i > 0 {
+ oldName := name
+ unixName := name[:i]
+ authInfo.UserInfo.Name = unixName
+ if authInfo.UserInfo.Home != "" && filepath.Base(authInfo.UserInfo.Home) == oldName {
+ authInfo.UserInfo.Home = filepath.Join(filepath.Dir(authInfo.UserInfo.Home), unixName)
+ }
+ }
+ }
+
if b.cfg.shouldRegisterOwner() {
if err := b.cfg.registerOwner(b.cfg.ConfigFile, authInfo.UserInfo.Name); err != nil {
// The user is not allowed if we fail to create the owner-autoregistration file.
diff --git a/authd-oidc-brokers/internal/broker/config.go b/authd-oidc-brokers/internal/broker/config.go
--- a/authd-oidc-brokers/internal/broker/config.go
+++ b/authd-oidc-brokers/internal/broker/config.go
@@ -53,6 +53,8 @@ const (
extraGroupsKey = "extra_groups"
// ownerExtraGroupsKey is the key in the config file for the extra groups to add to the owner.
ownerExtraGroupsKey = "owner_extra_groups"
+ // useShortUsernamesKey strips "@domain" from the OIDC-derived Linux username when true (optional).
+ useShortUsernamesKey = "use_short_usernames"
// allUsersKeyword is the keyword for the `allowed_users` key that allows access to all users.
allUsersKeyword = "ALL"
// ownerUserKeyword is the keyword for the `allowed_users` key that allows access to the owner.
@@ -94,6 +96,7 @@ type userConfig struct {
allowedSSHSuffixes []string
extraGroups []string
ownerExtraGroups []string
+ useShortUsernames bool
extraScopes []string
provider provider
@@ -253,6 +256,14 @@ func parseConfig(cfgContent []byte, dropInContent []any, p provider) (userConfig
cfg.populateUsersConfig(iniCfg.Section(usersSection))
+ if sec := iniCfg.Section(usersSection); sec != nil && sec.HasKey(useShortUsernamesKey) {
+ var parseErr error
+ cfg.useShortUsernames, parseErr = sec.Key(useShortUsernamesKey).Bool()
+ if parseErr != nil {
+ return userConfig{}, fmt.Errorf("error parsing '%s': %w", useShortUsernamesKey, parseErr)
+ }
+ }
+
return cfg, nil
}
We can open this as a draft PR if maintainers want it wired against main / canonical/authd-oidc-brokers packaging — happy to iterate on naming (use_short_usernames matches the vocabulary from #574).
— Wayve Linux Sign-In team
Summary
For generic OIDC (
authd-oidc), the Linux username is derived from the OIDCemailclaim today (genericprovider.GetUserInfo→info.NewUser(userClaims.Email, …)). That yields full email-shaped usernames such asalex.garcia@wayve.ai, which propagate into passwd entries and homedirs like/home/alex.garcia@wayve.ai.Long-running upstream discussions (#574, #1317, #508) explore naming policy and broker UX, but enterprises remain blocked today: IdPs commonly issue email-shaped identities, and downstream tooling assumes POSIX-safe
loginnames without@.We propose an opt-in
[users]knob inbroker.conf:use_short_usernames(bool, defaultfalse): whentrue, strip the@domainsuffix by cutting at the first@. The strip happens at the very top offinishAuth, before the owner auto-registration call (b.cfg.registerOwner), the allowed-users check (b.userNameIsAllowed), and theb.isOwner-drivenowner_extra_groupsmerge. That ordering is important: it ensures all three name-based steps see a consistent stripped name, so the value persisted tobroker.confasowner=matches whatb.isOwner(authInfo.UserInfo.Name)checks on subsequent logins, and so operators write short forms inallowed_userswithout surprise.The UUID/sub claim is untouched (
authInfo.UserInfo.UUIDremains the canonical identity key for the daemon's user mapping).Versions / context
authd-oidc-brokerson a branch carrying #1476 (email verification via/userinfowhere needed) and the dedupe-groups fix from #1496.Failure modes the
@-suffix causes today@in certain--user/ principal contexts;$USERinterpolation breaks scripted Azure workflows.@as URI userinfo (scheme://user@host) mis-parse paths or logs containing$HOME./home/with@confuse editors, SSH wrappers, and legacy scripts that split fields naïvely.$USERmatches typical Unix[a-z_][a-z0-9_-]*conventions.Concrete behaviour
use_short_usernames = true)login/ NSS namealex.garcia@wayve.aialex.garciahome_base_dir)/home/alex.garcia@wayve.ai/home/alex.garciaGuard: only strip when the first
@is not at index 0 (so a pathological@somethingdoes not yield an empty username — falls through to the original name in that case).Proposed patch (unified diff)
Applies on top of #1476 after the dedupe-groups fix (#1496 style).
We can open this as a draft PR if maintainers want it wired against
main/canonical/authd-oidc-brokerspackaging — happy to iterate on naming (use_short_usernamesmatches the vocabulary from #574).— Wayve Linux Sign-In team