BTW; you cannot map literals
"email_verified": true
for some reason.
BTW; you cannot map literals
"email_verified": true
for some reason.
Any updates about this? users created with enterprise connection should be able to set as “email_verified”: true. right now it’s not possible like any other mapping! also as mentioned before, mapping “email_verified” attribute to literal true value is not setting the created users to verified after being created!
Bump. Any updates on this? Being able to set the value of the email verified flag by default for SAML connections is a must.
Same for us as well. Plus, mapping to a “truthy” value breaks the Golang client that expects an actual boolean.
Ditto. This just broke one of our customers. The Auth0 Golang SDK requires “email_verified” to be a boolean, and will fail when it’s a string.
Bump. Not being able to set “email_verified” to true form SAML connections is breaking all of the Auth0 SDKs for reading users. We currently have to map to “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier” but that is not a sufficient solution given the issue above.
In case it can help anybody else, the workaround we ended up with is to wrap the resulting user list so we can use a custom unmarshal function.
// Specialized SAML user list function
//
// The Auth0 golang SDK does not properly handle the unmarshal of the returned payload into a management.UserList.
//
// The returned payload contains:
// "email":"user@domain.com",
// "emailVerified":"true",
// "email_verified":"user@domain.com"
//
// Which results in an unmarshal error when calling `func (m *UserManager) List(ctx context.Context, opts ...RequestOption) (ul *UserList, err error)`
// resulting in an error `strconv.ParseBool: parsing "user@domain.com": invalid syntax`
//
// The implementation below works around the issues by using custom JSON marshaling to map the values into the management.User instances.
type User struct {
management.User
}
type UserList struct {
management.List
Users []*User `json:"users"`
}
func (ul UserList) UserList() []*management.User {
return lo.Map(ul.Users, func(v *User, i int) *management.User { return &v.User })
}
func (u *User) UnmarshalJSON(b []byte) error {
var raw map[string]interface{}
if err := json.Unmarshal(b, &raw); err != nil {
return err
}
verified := false
if emailVerified, ok := raw["emailVerified"]; ok {
verified, _ = strconv.ParseBool(emailVerified.(string))
}
delete(raw, "emailVerified")
delete(raw, "email_verified")
buf, err := json.Marshal(raw)
if err != nil {
return err
}
type tTmpUser User
var tmpUser tTmpUser
if err := json.Unmarshal(buf, &tmpUser); err != nil {
return err
}
tmpUser.VerifyEmail = &verified
*u = User(tmpUser)
return nil
}
func ListUsers(ctx context.Context, m *management.Management, payload interface{}, options ...management.RequestOption) error {
options = append(options,
management.PerPage(100),
management.IncludeTotals(true),
)
request, err := m.NewRequest(ctx, "GET", m.URI("users"), payload, options...)
if err != nil {
return fmt.Errorf("failed to create a new request: %w", err)
}
response, err := m.Do(request)
if err != nil {
return fmt.Errorf("failed to send the request: %w", err)
}
defer response.Body.Close()
// If the response contains a client or a server error then return the error.
if response.StatusCode >= http.StatusBadRequest {
return err // newError(response) //TODO create correct error based on response
}
responseBody, err := io.ReadAll(response.Body)
if err != nil {
return fmt.Errorf("failed to read the response body: %w", err)
}
if len(responseBody) > 0 && string(responseBody) != "{}" {
if err = json.Unmarshal(responseBody, &payload); err != nil {
return fmt.Errorf("failed to unmarshal response payload: %w", err)
}
}
return nil
}
Link to the code which deploys this for further detail: