diff --git a/session_test.go b/session_test.go index 289b7ce..0972c38 100644 --- a/session_test.go +++ b/session_test.go @@ -194,3 +194,50 @@ func TestSessionStore_GetSessionFromToken(t *testing.T) { assert.Error(t, err) assert.Nil(t, session) } + +func TestSession_IDToken_CustomUser(t *testing.T) { + // very similar to `dummySession` above but uses + // `CustomTestUser` instead of `DefaultUser` so an + // additional claim can be added + customSession := &mockoidc.Session{ + SessionID: "DefaultSessionId", + Scopes: []string{"openid", "email", "profile", "groups"}, + User: &CustomTestUser{ + MockUser: *mockoidc.DefaultUser(), + PhoneVerified: true, + }, + } + + // register the custom claim + mockoidc.ClaimsSupported = append(mockoidc.ClaimsSupported, "phone_verified") + + keypair, _ := mockoidc.DefaultKeypair() + tokenString, err := customSession.IDToken(dummyConfig, keypair, mockoidc.NowFunc()) + assert.NoError(t, err) + + token, err := keypair.VerifyJWT(tokenString, mockoidc.NowFunc) + assert.NoError(t, err) + assert.True(t, token.Valid) + + claims, ok := token.Claims.(jwt.MapClaims) + assert.True(t, ok) + assert.NotNil(t, claims) + + assert.Equal(t, customSession.SessionID, claims["jti"]) + claimsAudience, err := claims.GetAudience() + assert.NoError(t, err) + assert.Equal(t, jwt.ClaimStrings{dummyConfig.ClientID}, claimsAudience) + assert.Equal(t, dummyConfig.Issuer, claims["iss"]) + assert.Equal(t, customSession.User.ID(), claims["sub"]) + + u := customSession.User.(*CustomTestUser) + assert.Equal(t, u.PreferredUsername, claims["preferred_username"]) + assert.Equal(t, u.Address, claims["address"]) + assert.Equal(t, u.Phone, claims["phone_number"]) + // check for the additional claim added by CustomTestUser + assert.Equal(t, u.PhoneVerified, claims["phone_verified"]) + + groups, ok := claims["groups"].([]interface{}) + assert.True(t, ok) + assert.Equal(t, len(groups), 2) +} diff --git a/user_custom_test.go b/user_custom_test.go new file mode 100644 index 0000000..c6edbda --- /dev/null +++ b/user_custom_test.go @@ -0,0 +1,85 @@ +package mockoidc_test + +import ( + "encoding/json" + + "github.com/golang-jwt/jwt/v5" + "github.com/oauth2-proxy/mockoidc" +) + +type mockCustomerTestUserInfo struct { + Email string `json:"email,omitempty"` + PreferredUsername string `json:"preferred_username,omitempty"` + Phone string `json:"phone_number,omitempty"` + Address string `json:"address,omitempty"` + Groups []string `json:"groups,omitempty"` +} + +type mockCustomeTestUserClaims struct { + *mockoidc.IDTokenClaims + Email string `json:"email,omitempty"` + EmailVerified bool `json:"email_verified,omitempty"` + PreferredUsername string `json:"preferred_username,omitempty"` + Phone string `json:"phone_number,omitempty"` + PhoneVerified bool `json:"phone_verified,omitempty"` + Address string `json:"address,omitempty"` + Groups []string `json:"groups,omitempty"` +} + +type CustomTestUser struct { + mockoidc.MockUser + PhoneVerified bool +} + +func (ctu *CustomTestUser) scopedClone(scopes []string) *CustomTestUser { + clone := &CustomTestUser{ + MockUser: mockoidc.MockUser{ + Subject: ctu.Subject, + }, + } + for _, scope := range scopes { + switch scope { + case "profile": + clone.PreferredUsername = ctu.PreferredUsername + clone.Address = ctu.Address + clone.Phone = ctu.Phone + clone.PhoneVerified = ctu.PhoneVerified + case "email": + clone.Email = ctu.Email + clone.EmailVerified = ctu.EmailVerified + case "groups": + clone.Groups = append(make([]string, 0, len(ctu.Groups)), ctu.Groups...) + } + } + return clone +} + +func (ctu *CustomTestUser) ID() string { + return ctu.Subject +} + +func (ctu *CustomTestUser) Userinfo(scope []string) ([]byte, error) { + user := ctu.scopedClone(scope) + info := &mockCustomerTestUserInfo{ + Email: user.Email, + PreferredUsername: user.PreferredUsername, + Phone: user.Phone, + Address: user.Address, + Groups: user.Groups, + } + return json.Marshal(info) +} + +func (ctu *CustomTestUser) Claim(scope []string, claims *mockoidc.IDTokenClaims) (jwt.Claims, error) { + user := ctu.scopedClone(scope) + return &mockCustomeTestUserClaims{ + IDTokenClaims: claims, + Email: user.Email, + EmailVerified: user.EmailVerified, + PreferredUsername: user.PreferredUsername, + Phone: user.Phone, + PhoneVerified: user.PhoneVerified, + Address: user.Address, + Groups: user.Groups, + }, nil +}