feat: Enable parsing email_verified from string. (#139)

* Enable parsing email_verified from string.

AWS Cognito will return email_verified from /userinfo endpoint as string.
This fix will accept proper boolean values as well as string values.

Links for reference:
https://forums.aws.amazon.com/thread.jspa?messageID=949441&#949441
https://discuss.elastic.co/t/openid-error-after-authenticating-against-aws-cognito/206018/11

* feat: Enable parsing email_verified from string.
This commit is contained in:
Witold Konior 2021-11-02 09:14:33 +01:00 committed by GitHub
parent c45f03e144
commit 763d3334e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 7 deletions

View file

@ -115,7 +115,7 @@ func (u *introspectionResponse) GetEmail() string {
} }
func (u *introspectionResponse) IsEmailVerified() bool { func (u *introspectionResponse) IsEmailVerified() bool {
return u.EmailVerified return bool(u.EmailVerified)
} }
func (u *introspectionResponse) GetPhoneNumber() string { func (u *introspectionResponse) GetPhoneNumber() string {
@ -200,7 +200,7 @@ func (u *introspectionResponse) SetPreferredUsername(name string) {
func (u *introspectionResponse) SetEmail(email string, verified bool) { func (u *introspectionResponse) SetEmail(email string, verified bool) {
u.Email = email u.Email = email
u.EmailVerified = verified u.EmailVerified = boolString(verified)
} }
func (u *introspectionResponse) SetPhone(phone string, verified bool) { func (u *introspectionResponse) SetPhone(phone string, verified bool) {

View file

@ -154,7 +154,7 @@ func (u *userinfo) GetEmail() string {
} }
func (u *userinfo) IsEmailVerified() bool { func (u *userinfo) IsEmailVerified() bool {
return u.EmailVerified return bool(u.EmailVerified)
} }
func (u *userinfo) GetPhoneNumber() string { func (u *userinfo) GetPhoneNumber() string {
@ -235,7 +235,7 @@ func (u *userinfo) SetPreferredUsername(name string) {
func (u *userinfo) SetEmail(email string, verified bool) { func (u *userinfo) SetEmail(email string, verified bool) {
u.Email = email u.Email = email
u.EmailVerified = verified u.EmailVerified = boolString(verified)
} }
func (u *userinfo) SetPhone(phone string, verified bool) { func (u *userinfo) SetPhone(phone string, verified bool) {
@ -296,8 +296,22 @@ type userInfoProfile struct {
} }
type userInfoEmail struct { type userInfoEmail struct {
Email string `json:"email,omitempty"` Email string `json:"email,omitempty"`
EmailVerified bool `json:"email_verified,omitempty"`
// Handle providers that return email_verified as a string
// https://forums.aws.amazon.com/thread.jspa?messageID=949441&#949441
// https://discuss.elastic.co/t/openid-error-after-authenticating-against-aws-cognito/206018/11
EmailVerified boolString `json:"email_verified,omitempty"`
}
type boolString bool
func (bs *boolString) UnmarshalJSON(data []byte) error {
if string(data) == "true" || string(data) == `"true"` {
*bs = true
}
return nil
} }
type userInfoPhone struct { type userInfoPhone struct {
@ -324,6 +338,7 @@ func NewUserInfoAddress(streetAddress, locality, region, postalCode, country, fo
Formatted: formatted, Formatted: formatted,
} }
} }
func (i *userinfo) MarshalJSON() ([]byte, error) { func (i *userinfo) MarshalJSON() ([]byte, error) {
type Alias userinfo type Alias userinfo
a := &struct { a := &struct {

View file

@ -2,8 +2,9 @@ package oidc
import ( import (
"encoding/json" "encoding/json"
"github.com/stretchr/testify/assert"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestUserInfoMarshal(t *testing.T) { func TestUserInfoMarshal(t *testing.T) {
@ -24,3 +25,59 @@ func TestUserInfoMarshal(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, expected, marshal) assert.Equal(t, expected, marshal)
} }
func TestUserInfoEmailVerifiedUnmarshal(t *testing.T) {
t.Parallel()
t.Run("unmarsha email_verified from json bool true", func(t *testing.T) {
jsonBool := []byte(`{"email": "my@email.com", "email_verified": true}`)
var uie userInfoEmail
err := json.Unmarshal(jsonBool, &uie)
assert.NoError(t, err)
assert.Equal(t, userInfoEmail{
Email: "my@email.com",
EmailVerified: true,
}, uie)
})
t.Run("unmarsha email_verified from json string true", func(t *testing.T) {
jsonBool := []byte(`{"email": "my@email.com", "email_verified": "true"}`)
var uie userInfoEmail
err := json.Unmarshal(jsonBool, &uie)
assert.NoError(t, err)
assert.Equal(t, userInfoEmail{
Email: "my@email.com",
EmailVerified: true,
}, uie)
})
t.Run("unmarsha email_verified from json bool false", func(t *testing.T) {
jsonBool := []byte(`{"email": "my@email.com", "email_verified": false}`)
var uie userInfoEmail
err := json.Unmarshal(jsonBool, &uie)
assert.NoError(t, err)
assert.Equal(t, userInfoEmail{
Email: "my@email.com",
EmailVerified: false,
}, uie)
})
t.Run("unmarsha email_verified from json string false", func(t *testing.T) {
jsonBool := []byte(`{"email": "my@email.com", "email_verified": "false"}`)
var uie userInfoEmail
err := json.Unmarshal(jsonBool, &uie)
assert.NoError(t, err)
assert.Equal(t, userInfoEmail{
Email: "my@email.com",
EmailVerified: false,
}, uie)
})
}