From f6273b4ba6f1f066726f5d62d48589971f37bd43 Mon Sep 17 00:00:00 2001 From: toshinori sato Date: Fri, 20 May 2022 14:51:41 +0900 Subject: [PATCH 1/5] add feature to create email action link of verify and change email (cherry picked from commit 2c5dd06172854f4388663eefd3db50b109259a44) --- auth/email_action_links.go | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/auth/email_action_links.go b/auth/email_action_links.go index 6b649254..30b66af5 100644 --- a/auth/email_action_links.go +++ b/auth/email_action_links.go @@ -64,9 +64,10 @@ func (settings *ActionCodeSettings) toMap() (map[string]interface{}, error) { type linkType string const ( - emailLinkSignIn linkType = "EMAIL_SIGNIN" - emailVerification linkType = "VERIFY_EMAIL" - passwordReset linkType = "PASSWORD_RESET" + emailLinkSignIn linkType = "EMAIL_SIGNIN" + emailVerification linkType = "VERIFY_EMAIL" + passwordReset linkType = "PASSWORD_RESET" + verifyAndChangeEmail linkType = "VERIFY_AND_CHANGE_EMAIL" ) // EmailVerificationLink generates the out-of-band email action link for email verification flows for the specified @@ -79,7 +80,7 @@ func (c *baseClient) EmailVerificationLink(ctx context.Context, email string) (s // specified email address, using the action code settings provided. func (c *baseClient) EmailVerificationLinkWithSettings( ctx context.Context, email string, settings *ActionCodeSettings) (string, error) { - return c.generateEmailActionLink(ctx, emailVerification, email, settings) + return c.generateEmailActionLink(ctx, emailVerification, email, settings, nil) } // PasswordResetLink generates the out-of-band email action link for password reset flows for the specified email @@ -92,18 +93,31 @@ func (c *baseClient) PasswordResetLink(ctx context.Context, email string) (strin // specified email address, using the action code settings provided. func (c *baseClient) PasswordResetLinkWithSettings( ctx context.Context, email string, settings *ActionCodeSettings) (string, error) { - return c.generateEmailActionLink(ctx, passwordReset, email, settings) + return c.generateEmailActionLink(ctx, passwordReset, email, settings, nil) } // EmailSignInLink generates the out-of-band email action link for email link sign-in flows, using the action // code settings provided. func (c *baseClient) EmailSignInLink( ctx context.Context, email string, settings *ActionCodeSettings) (string, error) { - return c.generateEmailActionLink(ctx, emailLinkSignIn, email, settings) + return c.generateEmailActionLink(ctx, emailLinkSignIn, email, settings, nil) +} + +// VerifyAndChangeEmailLink generates the out-of-band email action link for email verification and change flows for the +// specified email address. +func (c *baseClient) VerifyAndChangeEmailLink(ctx context.Context, email string, newEmail string) (string, error) { + return c.VerifyAndChangeEmailLinkWithSettings(ctx, email, newEmail, nil) +} + +// VerifyAndChangeEmailLinkWithSettings generates the out-of-band email action link for email verification and change +// flows for the specified email address, using the action code settings provided. +func (c *baseClient) VerifyAndChangeEmailLinkWithSettings( + ctx context.Context, email string, newEmail string, settings *ActionCodeSettings) (string, error) { + return c.generateEmailActionLink(ctx, verifyAndChangeEmail, email, settings, &newEmail) } func (c *baseClient) generateEmailActionLink( - ctx context.Context, linkType linkType, email string, settings *ActionCodeSettings) (string, error) { + ctx context.Context, linkType linkType, email string, settings *ActionCodeSettings, newEmail *string) (string, error) { if email == "" { return "", errors.New("email must not be empty") @@ -118,6 +132,14 @@ func (c *baseClient) generateEmailActionLink( "email": email, "returnOobLink": true, } + + if linkType == verifyAndChangeEmail { + if newEmail == nil { + return "", errors.New("newEmail must not be nil when linkType is verifyAndChangeEmail") + } + payload["newEmail"] = *newEmail + } + if settings != nil { settingsMap, err := settings.toMap() if err != nil { From 0d3f096f916921e63376e4ff5742b5071c42d572 Mon Sep 17 00:00:00 2001 From: toshinori sato Date: Fri, 20 May 2022 14:51:57 +0900 Subject: [PATCH 2/5] add test for VerifyAndChangeEmailLink (cherry picked from commit 57b9ee10658a6869ad4855d6fc1fc6075d669160) --- auth/email_action_links_test.go | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/auth/email_action_links_test.go b/auth/email_action_links_test.go index 876f3300..0f7b6db2 100644 --- a/auth/email_action_links_test.go +++ b/auth/email_action_links_test.go @@ -29,6 +29,7 @@ const ( testActionLink = "https://test.link" testActionLinkFormat = `{"oobLink": %q}` testEmail = "user@domain.com" + testNewEmail = "user-new@domain.com" ) var testActionLinkResponse = []byte(fmt.Sprintf(testActionLinkFormat, testActionLink)) @@ -309,6 +310,55 @@ func TestEmailVerificationLinkError(t *testing.T) { } } +func TestVerifyAndChangeEmailLink(t *testing.T) { + s := echoServer(testActionLinkResponse, t) + defer s.Close() + + link, err := s.Client.VerifyAndChangeEmailLink(context.Background(), testEmail, testNewEmail) + if err != nil { + t.Fatal(err) + } + if link != testActionLink { + t.Errorf("TestVerifyAndChangeEmailLink() = %q; want = %q", link, testActionLink) + } + + want := map[string]interface{}{ + "requestType": "VERIFY_AND_CHANGE_EMAIL", + "email": testEmail, + "returnOobLink": true, + "newEmail": testNewEmail, + } + if err := checkActionLinkRequest(want, s); err != nil { + t.Fatalf("TestVerifyAndChangeEmailLink() %v", err) + } +} + +func TestVerifyAndChangeEmailLinkWithSettings(t *testing.T) { + s := echoServer(testActionLinkResponse, t) + defer s.Close() + + link, err := s.Client.VerifyAndChangeEmailLinkWithSettings(context.Background(), testEmail, testNewEmail, testActionCodeSettings) + if err != nil { + t.Fatal(err) + } + if link != testActionLink { + t.Errorf("VerifyAndChangeEmailLinkWithSettings() = %q; want = %q", link, testActionLink) + } + + want := map[string]interface{}{ + "requestType": "VERIFY_AND_CHANGE_EMAIL", + "email": testEmail, + "returnOobLink": true, + "newEmail": testNewEmail, + } + for k, v := range testActionCodeSettingsMap { + want[k] = v + } + if err := checkActionLinkRequest(want, s); err != nil { + t.Fatalf("VerifyAndChangeEmailLinkWithSettings() %v", err) + } +} + func checkActionLinkRequest(want map[string]interface{}, s *mockAuthServer) error { wantURL := "/projects/mock-project-id/accounts:sendOobCode" return checkActionLinkRequestWithURL(want, wantURL, s) From dbda8384f674a7c4ae85d326a0bf12d3a0a351c2 Mon Sep 17 00:00:00 2001 From: toshinori sato Date: Fri, 20 May 2022 14:52:18 +0900 Subject: [PATCH 3/5] add tenant test for VerifyAndChangeEmailLink (cherry picked from commit 108834beeda018c2699e4c67a5aca80161dacb17) --- auth/tenant_mgt_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/auth/tenant_mgt_test.go b/auth/tenant_mgt_test.go index 1e9e2b91..66a45f6a 100644 --- a/auth/tenant_mgt_test.go +++ b/auth/tenant_mgt_test.go @@ -569,6 +569,34 @@ func TestTenantEmailSignInLink(t *testing.T) { } } +func TestTenantVerifyAndChangeEmail(t *testing.T) { + s := echoServer(testActionLinkResponse, t) + defer s.Close() + + client, err := s.Client.TenantManager.AuthForTenant("tenantID") + if err != nil { + t.Fatalf("AuthForTenant() = %v", err) + } + + link, err := client.VerifyAndChangeEmailLink(context.Background(), testEmail, testNewEmail) + if err != nil { + t.Fatal(err) + } + if link != testActionLink { + t.Errorf("VerifyAndChangeEmailLink() = %q; want = %q", link, testActionLink) + } + + want := map[string]interface{}{ + "requestType": "VERIFY_AND_CHANGE_EMAIL", + "email": testEmail, + "returnOobLink": true, + "newEmail": testNewEmail, + } + if err := checkActionLinkRequestWithURL(want, wantEmailActionURL, s); err != nil { + t.Fatalf("VerifyAndChangeEmailLink() %v", err) + } +} + func TestTenantOIDCProviderConfig(t *testing.T) { s := echoServer([]byte(oidcConfigResponse), t) defer s.Close() From 0d34c24b987db611506b3d1994bf19d6fcb25914 Mon Sep 17 00:00:00 2001 From: toshinori sato Date: Fri, 20 May 2022 14:53:15 +0900 Subject: [PATCH 4/5] add tenant integration test for VerifyAndChangeEmailLink (cherry picked from commit 8a7ccb605a8bf8cdbec15548cdcad82fa473b0ad) --- integration/auth/tenant_mgt_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/integration/auth/tenant_mgt_test.go b/integration/auth/tenant_mgt_test.go index 190a29f4..d74beaeb 100644 --- a/integration/auth/tenant_mgt_test.go +++ b/integration/auth/tenant_mgt_test.go @@ -348,6 +348,23 @@ func testTenantAwareUserManagement(t *testing.T, id string) { } }) + t.Run("VerifyAndChangeEmailLink()", func(t *testing.T) { + newEmail := "new-" + want.Email + link, err := tenantClient.VerifyAndChangeEmailLink(context.Background(), want.Email, newEmail) + if err != nil { + t.Fatalf("VerifyAndChangeEmailLink() = %v", err) + } + + tenant, err := extractTenantID(link) + if err != nil { + t.Fatalf("VerifyAndChangeEmailLink() = %v", err) + } + + if id != tenant { + t.Fatalf("VerifyAndChangeEmailLink() TenantID = %q; want = %q", tenant, id) + } + }) + t.Run("RevokeRefreshTokens()", func(t *testing.T) { validSinceMillis := time.Now().Unix() * 1000 time.Sleep(1 * time.Second) From 889a9bbf0027e8c7dd0896871ac07d439e30932a Mon Sep 17 00:00:00 2001 From: toshinori sato Date: Thu, 9 Jun 2022 08:07:15 +0900 Subject: [PATCH 5/5] fix error message in test --- auth/email_action_links_test.go | 2 +- auth/tenant_mgt_test.go | 2 +- integration/auth/tenant_mgt_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/auth/email_action_links_test.go b/auth/email_action_links_test.go index 0f7b6db2..90651875 100644 --- a/auth/email_action_links_test.go +++ b/auth/email_action_links_test.go @@ -355,7 +355,7 @@ func TestVerifyAndChangeEmailLinkWithSettings(t *testing.T) { want[k] = v } if err := checkActionLinkRequest(want, s); err != nil { - t.Fatalf("VerifyAndChangeEmailLinkWithSettings() %v", err) + t.Fatalf("checkActionLinkRequest() = %v", err) } } diff --git a/auth/tenant_mgt_test.go b/auth/tenant_mgt_test.go index 66a45f6a..dc0cdaaa 100644 --- a/auth/tenant_mgt_test.go +++ b/auth/tenant_mgt_test.go @@ -593,7 +593,7 @@ func TestTenantVerifyAndChangeEmail(t *testing.T) { "newEmail": testNewEmail, } if err := checkActionLinkRequestWithURL(want, wantEmailActionURL, s); err != nil { - t.Fatalf("VerifyAndChangeEmailLink() %v", err) + t.Fatalf("checkActionLinkRequestWithURL() = %v", err) } } diff --git a/integration/auth/tenant_mgt_test.go b/integration/auth/tenant_mgt_test.go index d74beaeb..1a67180d 100644 --- a/integration/auth/tenant_mgt_test.go +++ b/integration/auth/tenant_mgt_test.go @@ -357,7 +357,7 @@ func testTenantAwareUserManagement(t *testing.T, id string) { tenant, err := extractTenantID(link) if err != nil { - t.Fatalf("VerifyAndChangeEmailLink() = %v", err) + t.Fatalf("extractTenantID(%s) = %v", link, err) } if id != tenant {