Use multiple oidc claim to find the username

The clim `preferred_username` is optional in Azure AD. Although is listed as preferred, in some enterprise environment it's not possible to add this additional claim. `unique_name` and `upn` are legacy alternatives
This commit is contained in:
totomz
2023-04-07 12:15:06 +02:00
parent b11eb0879e
commit cdf6e68684

View File

@@ -3,10 +3,12 @@ package web
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors"
"github.com/bolkedebruin/rdpgw/cmd/rdpgw/identity" "github.com/bolkedebruin/rdpgw/cmd/rdpgw/identity"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"log"
"math/rand" "math/rand"
"net/http" "net/http"
"time" "time"
@@ -15,7 +17,6 @@ import (
const ( const (
CacheExpiration = time.Minute * 2 CacheExpiration = time.Minute * 2
CleanupInterval = time.Minute * 5 CleanupInterval = time.Minute * 5
oidcKeyUserName = "preferred_username"
) )
type OIDC struct { type OIDC struct {
@@ -81,7 +82,15 @@ func (h *OIDC) HandleCallback(w http.ResponseWriter, r *http.Request) {
} }
id := identity.FromRequestCtx(r) id := identity.FromRequestCtx(r)
id.SetUserName(data[oidcKeyUserName].(string))
userName := findUsernameInClaims(data)
if userName == "" {
err = errors.New("no odic claim for username found")
log.Print(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
}
id.SetUserName(userName)
id.SetAuthenticated(true) id.SetAuthenticated(true)
id.SetAuthTime(time.Now()) id.SetAuthTime(time.Now())
id.SetAttribute(identity.AttrAccessToken, oauth2Token.AccessToken) id.SetAttribute(identity.AttrAccessToken, oauth2Token.AccessToken)
@@ -93,6 +102,18 @@ func (h *OIDC) HandleCallback(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, url, http.StatusFound) http.Redirect(w, r, url, http.StatusFound)
} }
func findUsernameInClaims(data map[string]interface{}) string {
candidates := []string{"preferred_username", "unique_name", "upn"}
for _, claim := range candidates {
userName, found := data[claim].(string)
if found {
return userName
}
}
return ""
}
func (h *OIDC) Authenticated(next http.Handler) http.Handler { func (h *OIDC) Authenticated(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := identity.FromRequestCtx(r) id := identity.FromRequestCtx(r)