mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 03:57:32 +00:00
fix: use of generic oauth provider (#5345)
Adds a id_attribute to the GenericOAuthProvider, which is used to map the external User. Further mapping can be done in actions by using the `rawInfo` of the new `ctx.v1.providerInfo` field.
This commit is contained in:
@@ -2,6 +2,8 @@ package oauth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
|
||||
@@ -11,92 +13,97 @@ import (
|
||||
var _ idp.User = (*UserMapper)(nil)
|
||||
|
||||
// UserMapper is an implementation of [idp.User].
|
||||
// It can be used in ZITADEL actions to map the raw `info`
|
||||
// It can be used in ZITADEL actions to map the `RawInfo`
|
||||
type UserMapper struct {
|
||||
ID string
|
||||
FirstName string
|
||||
LastName string
|
||||
DisplayName string
|
||||
NickName string
|
||||
PreferredUsername string
|
||||
Email string
|
||||
EmailVerified bool
|
||||
Phone string
|
||||
PhoneVerified bool
|
||||
PreferredLanguage string
|
||||
AvatarURL string
|
||||
Profile string
|
||||
info map[string]interface{}
|
||||
idAttribute string
|
||||
RawInfo map[string]interface{}
|
||||
}
|
||||
|
||||
func NewUserMapper(idAttribute string) *UserMapper {
|
||||
return &UserMapper{
|
||||
idAttribute: idAttribute,
|
||||
RawInfo: make(map[string]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserMapper) UnmarshalJSON(data []byte) error {
|
||||
if u.info == nil {
|
||||
u.info = make(map[string]interface{})
|
||||
}
|
||||
return json.Unmarshal(data, &u.info)
|
||||
return json.Unmarshal(data, &u.RawInfo)
|
||||
}
|
||||
|
||||
// GetID is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetID() string {
|
||||
return u.ID
|
||||
id, ok := u.RawInfo[u.idAttribute]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
switch i := id.(type) {
|
||||
case string:
|
||||
return i
|
||||
case int:
|
||||
return strconv.Itoa(i)
|
||||
case float64:
|
||||
return strconv.FormatFloat(i, 'f', -1, 64)
|
||||
default:
|
||||
return fmt.Sprint(i)
|
||||
}
|
||||
}
|
||||
|
||||
// GetFirstName is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetFirstName() string {
|
||||
return u.FirstName
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetLastName is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetLastName() string {
|
||||
return u.LastName
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetDisplayName is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetDisplayName() string {
|
||||
return u.DisplayName
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetNickname is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetNickname() string {
|
||||
return u.NickName
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetPreferredUsername is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetPreferredUsername() string {
|
||||
return u.PreferredUsername
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetEmail is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetEmail() string {
|
||||
return u.Email
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsEmailVerified is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) IsEmailVerified() bool {
|
||||
return u.EmailVerified
|
||||
return false
|
||||
}
|
||||
|
||||
// GetPhone is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetPhone() string {
|
||||
return u.Phone
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsPhoneVerified is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) IsPhoneVerified() bool {
|
||||
return u.PhoneVerified
|
||||
return false
|
||||
}
|
||||
|
||||
// GetPreferredLanguage is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetPreferredLanguage() language.Tag {
|
||||
return language.Make(u.PreferredLanguage)
|
||||
return language.Und
|
||||
}
|
||||
|
||||
// GetAvatarURL is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetAvatarURL() string {
|
||||
return u.AvatarURL
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetProfile is an implementation of the [idp.User] interface.
|
||||
func (u *UserMapper) GetProfile() string {
|
||||
return u.Profile
|
||||
return ""
|
||||
}
|
||||
|
@@ -93,9 +93,7 @@ func TestProvider_FetchUser(t *testing.T) {
|
||||
Reply(http.StatusInternalServerError)
|
||||
},
|
||||
userMapper: func() idp.User {
|
||||
return &UserMapper{
|
||||
ID: "userID",
|
||||
}
|
||||
return NewUserMapper("userID")
|
||||
},
|
||||
authURL: "https://oauth2.com/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=user&state=testState",
|
||||
tokens: &oidc.Tokens{
|
||||
@@ -135,7 +133,7 @@ func TestProvider_FetchUser(t *testing.T) {
|
||||
})
|
||||
},
|
||||
userMapper: func() idp.User {
|
||||
return &UserMapper{}
|
||||
return NewUserMapper("userID")
|
||||
},
|
||||
authURL: "https://issuer.com/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=user&state=testState",
|
||||
tokens: &oidc.Tokens{
|
||||
@@ -147,12 +145,13 @@ func TestProvider_FetchUser(t *testing.T) {
|
||||
},
|
||||
want: want{
|
||||
user: &UserMapper{
|
||||
info: map[string]interface{}{
|
||||
idAttribute: "userID",
|
||||
RawInfo: map[string]interface{}{
|
||||
"userID": "id",
|
||||
"custom": "claim",
|
||||
},
|
||||
},
|
||||
id: "",
|
||||
id: "id",
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
displayName: "",
|
||||
@@ -202,7 +201,7 @@ func TestProvider_FetchUser(t *testing.T) {
|
||||
})
|
||||
},
|
||||
userMapper: func() idp.User {
|
||||
return &UserMapper{}
|
||||
return NewUserMapper("userID")
|
||||
},
|
||||
authURL: "https://issuer.com/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=user&state=testState",
|
||||
tokens: nil,
|
||||
@@ -210,12 +209,13 @@ func TestProvider_FetchUser(t *testing.T) {
|
||||
},
|
||||
want: want{
|
||||
user: &UserMapper{
|
||||
info: map[string]interface{}{
|
||||
idAttribute: "userID",
|
||||
RawInfo: map[string]interface{}{
|
||||
"userID": "id",
|
||||
"custom": "claim",
|
||||
},
|
||||
},
|
||||
id: "",
|
||||
id: "id",
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
displayName: "",
|
||||
|
Reference in New Issue
Block a user