feat(oidc): bind email to namespace
@@ -9,7 +9,6 @@ import (
"fmt"
"html/template"
"net/http"
- "regexp"
"strings"
"time"
@@ -282,7 +281,15 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
now := time.Now().UTC()
- if namespaceName, ok := h.getNamespaceFromEmail(claims.Email); ok {
+ namespaceName, err := NormalizeNamespaceName(claims.Email)
+ if err != nil {
+ log.Error().Err(err).Caller().Msgf("couldn't normalize email")
+ ctx.String(
+ http.StatusInternalServerError,
+ "couldn't normalize email",
+ )
+ return
+ }
// register the machine if it's new
if !machine.Registered {
log.Debug().Msg("Registering new machine after successful callback")
@@ -361,30 +368,3 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) {
return
}
-
- log.Error().
- Caller().
- Str("email", claims.Email).
- Str("username", claims.Username).
- Str("machine", machine.Name).
- Msg("Email could not be mapped to a namespace")
- ctx.String(
- http.StatusBadRequest,
- "email from claim could not be mapped to a namespace",
- )
-}
-
-// getNamespaceFromEmail passes the users email through a list of "matchers"
-// and iterates through them until it matches and returns a namespace.
-// If no match is found, an empty string will be returned.
-// TODO(kradalby): golang Maps key order is not stable, so this list is _not_ deterministic. Find a way to make the list of keys stable, preferably in the order presented in a users configuration.
-func (h *Headscale) getNamespaceFromEmail(email string) (string, bool) {
- for match, namespace := range h.cfg.OIDC.MatchMap {
- regex := regexp.MustCompile(match)
- if regex.MatchString(email) {
- return namespace, true
- }
- }
-
- return "", false
-}
