From 79d11601f87701fbfefb3af85c92e4c0ffcac688 Mon Sep 17 00:00:00 2001 From: Wouter Doppenberg Date: Fri, 17 Jan 2025 17:46:25 +0100 Subject: [PATCH] feat: Add custom claims from Keycloak user token --- internal/api/provider/keycloak.go | 44 ++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/internal/api/provider/keycloak.go b/internal/api/provider/keycloak.go index 39ccec5bff..480a467244 100644 --- a/internal/api/provider/keycloak.go +++ b/internal/api/provider/keycloak.go @@ -2,6 +2,7 @@ package provider import ( "context" + "encoding/json" "errors" "strings" @@ -16,10 +17,33 @@ type keycloakProvider struct { } type keycloakUser struct { - Name string `json:"name"` - Sub string `json:"sub"` - Email string `json:"email"` - EmailVerified bool `json:"email_verified"` + Name string `json:"name"` + Sub string `json:"sub"` + Email string `json:"email"` + EmailVerified bool `json:"email_verified"` + RawClaims map[string]interface{} `json:"-"` +} + +func (u *keycloakUser) UnmarshalJSON(data []byte) error { + if err := json.Unmarshal(data, &u.RawClaims); err != nil { + return err + } + + // Extract known fields + if v, ok := u.RawClaims["name"].(string); ok { + u.Name = v + } + if v, ok := u.RawClaims["sub"].(string); ok { + u.Sub = v + } + if v, ok := u.RawClaims["email"].(string); ok { + u.Email = v + } + if v, ok := u.RawClaims["email_verified"].(bool); ok { + u.EmailVerified = v + } + + return nil } // NewKeycloakProvider creates a Keycloak account provider. @@ -72,6 +96,17 @@ func (g keycloakProvider) GetUserData(ctx context.Context, tok *oauth2.Token) (* return nil, err } + customClaims := make(map[string]interface{}) + standardClaims := map[string]bool{ + "name": true, "sub": true, "email": true, "email_verified": true, + } + + for k, v := range u.RawClaims { + if !standardClaims[k] { + customClaims[k] = v + } + } + data := &UserProvidedData{} if u.Email != "" { data.Emails = []Email{{ @@ -87,6 +122,7 @@ func (g keycloakProvider) GetUserData(ctx context.Context, tok *oauth2.Token) (* Name: u.Name, Email: u.Email, EmailVerified: u.EmailVerified, + CustomClaims: customClaims, // To be deprecated FullName: u.Name,