Skip to content
This repository was archived by the owner on Jul 12, 2023. It is now read-only.

Commit b7546f2

Browse files
authored
Custom email verify page (#757)
* Custom verify email page * routing
1 parent abd9123 commit b7546f2

File tree

4 files changed

+85
-7
lines changed

4 files changed

+85
-7
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{{define "login/verify-email-check"}}
2+
<!doctype html>
3+
<html lang="en">
4+
5+
<head>
6+
{{template "head" .}}
7+
{{template "firebase" .}}
8+
</head>
9+
10+
<body class="tab-content">
11+
{{template "navbar" .}}
12+
13+
<main role="main" class="container">
14+
{{template "flash" .}}
15+
16+
<div class="d-flex vh-100">
17+
<div class="d-flex w-100 justify-content-center">
18+
<div class="col-sm-6">
19+
20+
<div class="card mb-3 shadow-sm">
21+
<div class="card-header">Email verification</div>
22+
<div class="card-body">
23+
<p>Verifying email address ownership.</p>
24+
<a class="card-link" href="/">&larr; Login</a>
25+
</div>
26+
</div>
27+
</div>
28+
</div>
29+
</div>
30+
</main>
31+
32+
{{template "scripts" .}}
33+
<script type="text/javascript">
34+
$(function() {
35+
let urlVars = getUrlVars();
36+
let code = urlVars["oobCode"];
37+
if (!code) {
38+
code = "";
39+
}
40+
41+
firebase.auth().applyActionCode(code)
42+
.then(function(resp) {
43+
window.location.assign("/login/manage-account?mode=verifyEmail");
44+
}).catch(function(error) {
45+
flash.error("Invalid email verification code. "
46+
+ "The code may be malformed, expired, or has already been used.");
47+
});
48+
});
49+
50+
function getUrlVars() {
51+
let vars = [], hash;
52+
let queryParams = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
53+
for (var i = 0; i < queryParams.length; i++) {
54+
v = queryParams[i].split('=');
55+
vars.push(v[0]);
56+
vars[v[0]] = v[1];
57+
}
58+
return vars;
59+
}
60+
</script>
61+
</body>
62+
</html>
63+
{{end}}

cmd/server/main.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,11 @@ func realMain(ctx context.Context) error {
229229
sub.Handle("/login/reset-password", loginController.HandleShowResetPassword()).Methods("GET")
230230
sub.Handle("/login/reset-password", loginController.HandleSubmitResetPassword()).Methods("POST")
231231
sub.Handle("/login/manage-account", loginController.HandleShowSelectNewPassword()).
232-
Queries("oobCode", "", "mode", "{mode:(?:resetPassword|recoverEmail)}").Methods("GET")
232+
Queries("oobCode", "", "mode", "resetPassword").Methods("GET")
233233
sub.Handle("/login/manage-account", loginController.HandleSubmitNewPassword()).
234-
Queries("oobCode", "", "mode", "{mode:(?:resetPassword|recoverEmail)}").Methods("POST")
234+
Queries("oobCode", "", "mode", "resetPassword").Methods("POST")
235+
sub.Handle("/login/manage-account", loginController.HandleSubmitVerifyEmail()).
236+
Queries("oobCode", "{oobCode:.+}", "mode", "{mode:(?:verifyEmail|recoverEmail)}").Methods("GET")
235237
sub.Handle("/session", loginController.HandleCreateSession()).Methods("POST")
236238
sub.Handle("/signout", loginController.HandleSignOut()).Methods("GET")
237239

@@ -254,7 +256,7 @@ func realMain(ctx context.Context) error {
254256
sub.Use(loadCurrentRealm)
255257
sub.Use(requireRealm)
256258
sub.Use(processFirewall)
257-
sub.Handle("/login/manage-account", loginController.HandleVerifyEmail()).
259+
sub.Handle("/login/manage-account", loginController.HandleShowVerifyEmail()).
258260
Queries("mode", "verifyEmail").Methods("GET")
259261

260262
// SMS auth registration is realm-specific, so it needs to load the current realm.

internal/firebase/verify_password_reset_code.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@ type verifyPasswordResetCodeRequest struct {
2929
NewPassword string `json:"newPassword,omitempty"`
3030
}
3131

32-
// VerifyPasswordResetCode sends a password reset email to the user. If the new
33-
// password is given, it applies the password reset change with the new password
34-
// using the code.
32+
// VerifyPasswordResetCode is called with the one-time-code given from a reset email to the user.
33+
// It can be used to check that the code is valid without making changes to the user.
3534
//
3635
// See: https://firebase.google.com/docs/reference/rest/auth#section-send-password-reset-email
3736
func (c *Client) VerifyPasswordResetCode(ctx context.Context, code string) (string, error) {
3837
return c.ChangePasswordWithCode(ctx, code, "")
3938
}
4039

40+
// ChangePasswordWithCode is called with the one-time-code given from a reset email to the user.
41+
// When called with newPassword, it updates the user's password.
42+
//
43+
// See: https://firebase.google.com/docs/reference/rest/auth#section-send-password-reset-email
4144
func (c *Client) ChangePasswordWithCode(ctx context.Context, code, newPassword string) (string, error) {
4245
r := &verifyPasswordResetCodeRequest{Code: code}
4346
if newPassword != "" {

pkg/controller/login/verify_email.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"github.com/google/exposure-notifications-verification-server/pkg/controller"
2222
)
2323

24-
func (c *Controller) HandleVerifyEmail() http.Handler {
24+
func (c *Controller) HandleShowVerifyEmail() http.Handler {
2525
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2626
ctx := r.Context()
2727

@@ -39,3 +39,13 @@ func (c *Controller) HandleVerifyEmail() http.Handler {
3939
c.h.RenderHTML(w, "login/verify-email", m)
4040
})
4141
}
42+
43+
func (c *Controller) HandleSubmitVerifyEmail() http.Handler {
44+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
45+
ctx := r.Context()
46+
47+
m := controller.TemplateMapFromContext(ctx)
48+
m["firebase"] = c.config.Firebase
49+
c.h.RenderHTML(w, "login/verify-email-check", m)
50+
})
51+
}

0 commit comments

Comments
 (0)