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

Commit

Permalink
Custom email verify page (#757)
Browse files Browse the repository at this point in the history
* Custom verify email page

* routing
  • Loading branch information
whaught authored Oct 6, 2020
1 parent abd9123 commit b7546f2
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 7 deletions.
63 changes: 63 additions & 0 deletions cmd/server/assets/login/verify-email-check.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{{define "login/verify-email-check"}}
<!doctype html>
<html lang="en">

<head>
{{template "head" .}}
{{template "firebase" .}}
</head>

<body class="tab-content">
{{template "navbar" .}}

<main role="main" class="container">
{{template "flash" .}}

<div class="d-flex vh-100">
<div class="d-flex w-100 justify-content-center">
<div class="col-sm-6">

<div class="card mb-3 shadow-sm">
<div class="card-header">Email verification</div>
<div class="card-body">
<p>Verifying email address ownership.</p>
<a class="card-link" href="/">&larr; Login</a>
</div>
</div>
</div>
</div>
</div>
</main>

{{template "scripts" .}}
<script type="text/javascript">
$(function() {
let urlVars = getUrlVars();
let code = urlVars["oobCode"];
if (!code) {
code = "";
}

firebase.auth().applyActionCode(code)
.then(function(resp) {
window.location.assign("/login/manage-account?mode=verifyEmail");
}).catch(function(error) {
flash.error("Invalid email verification code. "
+ "The code may be malformed, expired, or has already been used.");
});
});

function getUrlVars() {
let vars = [], hash;
let queryParams = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < queryParams.length; i++) {
v = queryParams[i].split('=');
vars.push(v[0]);
vars[v[0]] = v[1];
}
return vars;
}
</script>
</body>
</html>
{{end}}
8 changes: 5 additions & 3 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,11 @@ func realMain(ctx context.Context) error {
sub.Handle("/login/reset-password", loginController.HandleShowResetPassword()).Methods("GET")
sub.Handle("/login/reset-password", loginController.HandleSubmitResetPassword()).Methods("POST")
sub.Handle("/login/manage-account", loginController.HandleShowSelectNewPassword()).
Queries("oobCode", "", "mode", "{mode:(?:resetPassword|recoverEmail)}").Methods("GET")
Queries("oobCode", "", "mode", "resetPassword").Methods("GET")
sub.Handle("/login/manage-account", loginController.HandleSubmitNewPassword()).
Queries("oobCode", "", "mode", "{mode:(?:resetPassword|recoverEmail)}").Methods("POST")
Queries("oobCode", "", "mode", "resetPassword").Methods("POST")
sub.Handle("/login/manage-account", loginController.HandleSubmitVerifyEmail()).
Queries("oobCode", "{oobCode:.+}", "mode", "{mode:(?:verifyEmail|recoverEmail)}").Methods("GET")
sub.Handle("/session", loginController.HandleCreateSession()).Methods("POST")
sub.Handle("/signout", loginController.HandleSignOut()).Methods("GET")

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

// SMS auth registration is realm-specific, so it needs to load the current realm.
Expand Down
9 changes: 6 additions & 3 deletions internal/firebase/verify_password_reset_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,18 @@ type verifyPasswordResetCodeRequest struct {
NewPassword string `json:"newPassword,omitempty"`
}

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

// ChangePasswordWithCode is called with the one-time-code given from a reset email to the user.
// When called with newPassword, it updates the user's password.
//
// See: https://firebase.google.com/docs/reference/rest/auth#section-send-password-reset-email
func (c *Client) ChangePasswordWithCode(ctx context.Context, code, newPassword string) (string, error) {
r := &verifyPasswordResetCodeRequest{Code: code}
if newPassword != "" {
Expand Down
12 changes: 11 additions & 1 deletion pkg/controller/login/verify_email.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/google/exposure-notifications-verification-server/pkg/controller"
)

func (c *Controller) HandleVerifyEmail() http.Handler {
func (c *Controller) HandleShowVerifyEmail() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

Expand All @@ -39,3 +39,13 @@ func (c *Controller) HandleVerifyEmail() http.Handler {
c.h.RenderHTML(w, "login/verify-email", m)
})
}

func (c *Controller) HandleSubmitVerifyEmail() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

m := controller.TemplateMapFromContext(ctx)
m["firebase"] = c.config.Firebase
c.h.RenderHTML(w, "login/verify-email-check", m)
})
}

0 comments on commit b7546f2

Please sign in to comment.