mirror of
https://github.com/teamhanko/hanko.git
synced 2025-10-26 21:57:14 +08:00
1166 lines
33 KiB
Go
1166 lines
33 KiB
Go
package handler
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/h2non/gock"
|
|
"github.com/teamhanko/hanko/backend/v2/thirdparty"
|
|
"github.com/teamhanko/hanko/backend/v2/utils"
|
|
)
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignUp_Google() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_abcde",
|
|
Email: "test-google-signup@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-google-signup@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signup_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_Google() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_abcde",
|
|
Email: "test-with-google-identity@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-google-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), "", "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignUp_GitHub() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
gock.New(thirdparty.GithubOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GithubUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GithubUser{
|
|
ID: 1234,
|
|
Name: "John Doe",
|
|
})
|
|
|
|
gock.New(thirdparty.GitHubEmailsEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON([]*thirdparty.GithubUserEmail{
|
|
{
|
|
Email: "test-github-signup@example.com",
|
|
Primary: true,
|
|
Verified: true,
|
|
},
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"github"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "github", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-github-signup@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("github", "1234")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signup_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_GitHub() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GithubOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GithubUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GithubUser{
|
|
ID: 1234,
|
|
Name: "John Doe",
|
|
})
|
|
|
|
gock.New(thirdparty.GitHubEmailsEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON([]*thirdparty.GithubUserEmail{
|
|
{
|
|
Email: "test-with-github-identity@example.com",
|
|
Primary: true,
|
|
Verified: true,
|
|
},
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"github"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "github", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-github-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("github", "1234")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignUp_Apple() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
fakeIdToken := s.setUpAppleIdToken("apple_abcde", "fakeClientID", "test-apple-signup@example.com", true, false)
|
|
gock.New(thirdparty.AppleTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken", "id_token": fakeIdToken})
|
|
|
|
fakeJwkSet := s.setUpFakeJwkSet()
|
|
gock.New(thirdparty.AppleKeysEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(fakeJwkSet)
|
|
|
|
cfg := s.setUpConfig([]string{"apple"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "apple", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-apple-signup@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("apple", "apple_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signup_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_Apple() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
fakeIdToken := s.setUpAppleIdToken("apple_abcde", "fakeClientID", "test-with-apple-identity@example.com", true, false)
|
|
gock.New(thirdparty.AppleTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken", "id_token": fakeIdToken})
|
|
|
|
fakeJwkSet := s.setUpFakeJwkSet()
|
|
gock.New(thirdparty.AppleKeysEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(fakeJwkSet)
|
|
|
|
cfg := s.setUpConfig([]string{"apple"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "apple", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-apple-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("apple", "apple_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_Apple_WithBooleanEmailVerifiedClaim() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
fakeIdToken := s.setUpAppleIdToken("apple_abcde", "fakeClientID", "test-with-apple-identity@example.com", true, true)
|
|
gock.New(thirdparty.AppleTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken", "id_token": fakeIdToken})
|
|
|
|
fakeJwkSet := s.setUpFakeJwkSet()
|
|
gock.New(thirdparty.AppleKeysEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(fakeJwkSet)
|
|
|
|
cfg := s.setUpConfig([]string{"apple"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "apple", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-apple-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("apple", "apple_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignUp_Discord() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
gock.New(thirdparty.DiscordOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.DiscordUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.DiscordUser{
|
|
ID: "discord_abcde",
|
|
Email: "test-discord-signup@example.com",
|
|
Verified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"discord"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "discord", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-discord-signup@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("discord", "discord_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signup_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_Discord() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.DiscordOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.DiscordUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.DiscordUser{
|
|
ID: "discord_abcde",
|
|
Email: "test-with-discord-identity@example.com",
|
|
Verified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"discord"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "discord", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-discord-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("discord", "discord_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), "", "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignUp_Microsoft() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
fakeIdToken := s.setUpMicrosoftIdToken("microsoft_abcde", "fakeClientID", "test-microsoft-signup@example.com", true)
|
|
gock.New(thirdparty.MicrosoftOAuthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken", "id_token": fakeIdToken})
|
|
|
|
fakeJwkSet := s.setUpFakeJwkSet()
|
|
gock.New(thirdparty.MicrosoftKeysEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(fakeJwkSet)
|
|
|
|
cfg := s.setUpConfig([]string{"microsoft"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "microsoft", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-microsoft-signup@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("microsoft", "microsoft_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signup_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_Microsoft() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
fakeIdToken := s.setUpMicrosoftIdToken("microsoft_abcde", "fakeClientID", "test-with-microsoft-identity@example.com", true)
|
|
gock.New(thirdparty.MicrosoftOAuthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken", "id_token": fakeIdToken})
|
|
|
|
fakeJwkSet := s.setUpFakeJwkSet()
|
|
gock.New(thirdparty.MicrosoftKeysEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(fakeJwkSet)
|
|
|
|
cfg := s.setUpConfig([]string{"microsoft"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "microsoft", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-microsoft-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("microsoft", "microsoft_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), "", "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignUp_Facebook() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
gock.New(thirdparty.FacebookOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.FacebookUserInfoEndpoint).
|
|
Get("/me").
|
|
Reply(200).
|
|
JSON(&thirdparty.FacebookUser{
|
|
ID: "facebook_abcde",
|
|
Email: "test-facebook-signup@example.com",
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"facebook"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "facebook", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-facebook-signup@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("facebook", "facebook_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signup_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_Facebook() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.FacebookOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.FacebookUserInfoEndpoint).
|
|
Get("/me").
|
|
Reply(200).
|
|
JSON(&thirdparty.FacebookUser{
|
|
ID: "facebook_abcde",
|
|
Email: "test-with-facebook-identity@example.com",
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"facebook"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "facebook", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-facebook-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("facebook", "facebook_abcde")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), "", "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignUp_WithUnclaimedEmail() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_unclaimed_email",
|
|
Email: "unclaimed-email@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("unclaimed-email@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.True(email.IsPrimary())
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_unclaimed_email")
|
|
s.NotNil(identity)
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signup_succeeded"}, user.ID.String(), email.Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_ProviderEMailChangedToExistingEmail() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_abcde",
|
|
Email: "test-with-google-identity-changed@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-google-identity-changed@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_abcde")
|
|
s.NotNil(identity)
|
|
s.Equal("test-with-google-identity-changed@example.com", identity.Data["email"])
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), user.Emails.GetPrimary().Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_ProviderEMailChangedToUnclaimedEmail() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_abcde",
|
|
Email: "unclaimed-email@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("unclaimed-email@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_abcde")
|
|
s.NotNil(identity)
|
|
s.Equal("unclaimed-email@example.com", identity.Data["email"])
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), user.Emails.GetPrimary().Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_SignIn_ProviderEMailChangedToNonExistentEmail() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_abcde",
|
|
Email: "non-existent-email@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("non-existent-email@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
s.Len(user.Emails, 3)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_abcde")
|
|
s.NotNil(identity)
|
|
s.Equal("non-existent-email@example.com", identity.Data["email"])
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_signin_succeeded"}, user.ID.String(), user.Emails.GetPrimary().Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_Link_ExistingAccountNoIdentities() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_1234",
|
|
Email: "test-no-identity@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-no-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
s.Len(user.Emails, 1)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_1234")
|
|
s.NotNil(identity)
|
|
s.Equal("test-no-identity@example.com", identity.Data["email"])
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_linking_succeeded"}, user.ID.String(), user.Emails.GetPrimary().Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|
|
|
|
func (s *thirdPartySuite) TestThirdPartyHandler_Callback_Link_GoogleToAccountWithGithubIdentity() {
|
|
defer gock.Off()
|
|
if testing.Short() {
|
|
s.T().Skip("skipping test in short mode.")
|
|
}
|
|
|
|
err := s.LoadFixtures("../test/fixtures/thirdparty")
|
|
s.NoError(err)
|
|
|
|
gock.New(thirdparty.GoogleOauthTokenEndpoint).
|
|
Post("/").
|
|
Reply(200).
|
|
JSON(map[string]string{"access_token": "fakeAccessToken"})
|
|
|
|
gock.New(thirdparty.GoogleUserInfoEndpoint).
|
|
Get("/").
|
|
Reply(200).
|
|
JSON(&thirdparty.GoogleUser{
|
|
ID: "google_1234",
|
|
Email: "test-with-github-identity@example.com",
|
|
EmailVerified: true,
|
|
})
|
|
|
|
cfg := s.setUpConfig([]string{"google", "github"}, []string{"https://example.com"})
|
|
|
|
state, err := thirdparty.GenerateState(cfg, "google", "https://example.com")
|
|
s.NoError(err)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/thirdparty/callback?code=abcde&state=%s", state), nil)
|
|
req.AddCookie(&http.Cookie{
|
|
Name: utils.HankoThirdpartyStateCookie,
|
|
Value: string(state),
|
|
})
|
|
|
|
c, rec := s.setUpContext(req)
|
|
handler := s.setUpHandler(cfg)
|
|
|
|
if s.NoError(handler.Callback(c)) {
|
|
s.Equal(http.StatusTemporaryRedirect, rec.Code)
|
|
|
|
s.assertLocationHeaderHasToken(rec)
|
|
s.assertStateCookieRemoved(rec)
|
|
|
|
email, err := s.Storage.GetEmailPersister().FindByAddress("test-with-github-identity@example.com")
|
|
s.NoError(err)
|
|
s.NotNil(email)
|
|
s.Len(email.Identities, 2)
|
|
|
|
user, err := s.Storage.GetUserPersister().Get(*email.UserID)
|
|
s.NoError(err)
|
|
s.NotNil(user)
|
|
s.Len(user.Emails, 1)
|
|
|
|
identity := email.Identities.GetIdentity("google", "google_1234")
|
|
s.NotNil(identity)
|
|
s.Equal("test-with-github-identity@example.com", identity.Data["email"])
|
|
|
|
logs, lerr := s.Storage.GetAuditLogPersister().List(0, 0, nil, nil, []string{"thirdparty_linking_succeeded"}, user.ID.String(), user.Emails.GetPrimary().Address, "", "")
|
|
s.NoError(lerr)
|
|
s.Len(logs, 1)
|
|
}
|
|
}
|