From fa222c5efb331a225c931b07721c33f55cf6c2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20M=C3=B6hlmann?= Date: Fri, 3 Feb 2023 12:14:04 +0200 Subject: [PATCH] fix: nil pointer dereference on UserInfoAddress (#207) * oidc: add test case to reproduce #203 Running the tests will always result in a nil pointer dereference on UserInfoAddress. Co-authored-by: Livio Spring * fix: nil pointer dereference on UserInfoAddress userinfo.UnmarshalJSON now only sets the Address field if it was present in the json. userinfo.GetAddress will always return a non-nil value of UserInfoAddress to allow for safe chaining of Get functions. Fixes #203 --------- Co-authored-by: Livio Spring --- pkg/oidc/userinfo.go | 9 ++++++++- pkg/oidc/userinfo_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/pkg/oidc/userinfo.go b/pkg/oidc/userinfo.go index 4d524e3..c8e34d6 100644 --- a/pkg/oidc/userinfo.go +++ b/pkg/oidc/userinfo.go @@ -167,6 +167,9 @@ func (u *userinfo) IsPhoneNumberVerified() bool { } func (u *userinfo) GetAddress() UserInfoAddress { + if u.Address == nil { + return &userInfoAddress{} + } return u.Address } @@ -389,7 +392,11 @@ func (u *userinfo) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, &a); err != nil { return err } - u.Address = a.Address + + if a.Address != nil { + u.Address = a.Address + } + u.UpdatedAt = Time(time.Unix(a.UpdatedAt, 0).UTC()) if err := json.Unmarshal(data, &u.claims); err != nil { diff --git a/pkg/oidc/userinfo_test.go b/pkg/oidc/userinfo_test.go index f42ff3d..319a2fd 100644 --- a/pkg/oidc/userinfo_test.go +++ b/pkg/oidc/userinfo_test.go @@ -81,3 +81,39 @@ func TestUserInfoEmailVerifiedUnmarshal(t *testing.T) { }, uie) }) } + +// issue 203 test case. +func Test_userinfo_GetAddress_issue_203(t *testing.T) { + tests := []struct { + name string + data string + }{ + { + name: "with address", + data: `{"address":{"street_address":"Test 789\nPostfach 2"},"email":"test","email_verified":true,"name":"Test","phone_number":"0791234567","phone_number_verified":true,"private_claim":"test","sub":"test"}`, + }, + { + name: "without address", + data: `{"email":"test","email_verified":true,"name":"Test","phone_number":"0791234567","phone_number_verified":true,"private_claim":"test","sub":"test"}`, + }, + { + name: "null address", + data: `{"address":null,"email":"test","email_verified":true,"name":"Test","phone_number":"0791234567","phone_number_verified":true,"private_claim":"test","sub":"test"}`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + info := &userinfo{} + err := json.Unmarshal([]byte(tt.data), info) + assert.NoError(t, err) + + info.GetAddress().GetCountry() //<- used to panic + + // now shortly assure that a marshalling still produces the same as was parsed into the struct + marshal, err := json.Marshal(info) + assert.NoError(t, err) + assert.Equal(t, tt.data, string(marshal)) + }) + } +}