Skip to content

Instantly share code, notes, and snippets.

@Auz
Created June 7, 2021 07:42
Show Gist options
  • Save Auz/d60682132ce4430ed0c720b9b16917d9 to your computer and use it in GitHub Desktop.
Save Auz/d60682132ce4430ed0c720b9b16917d9 to your computer and use it in GitHub Desktop.
Auth0 custom login page example with forgot password
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Welcome to Growth Book - Sign in or register</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css">
<style>
@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,300;0,400;0,500;0,600;0,700;1,400&display=swap");
body, html {
-webkit-font-smoothing: antialiased;
height: 100%;
background-color: #f9f9f9;
}
.login-container {
position: relative;
height: 100%;
}
.btn-block {
display:block;
width: 100%;
}
.btn-google {
color: #545454;
background-color: #ffffff;
box-shadow: 0 1px 2px 1px #ddd;
}
.form-group {
margin-bottom: 1rem;
}
.login-box {
position: absolute;
top: 50%;
transform: translateY(-50%);
padding: 15px;
background-color: #fff;
box-shadow: 0px 5px 5px #ccc;
border-radius: 5px;
border-top: 1px solid #e9e9e9;
}
.login-header {
text-align: center;
}
.login-header img {
width: 75px;
}
.error-message {
display: none;
white-space: break-spaces;
}
.welcome {
z-index: 1000;
position: relative;
min-height: 100vh;
font-family: Poppins, "Helvetica Neue", Arial, sans-serif;
}
.welcome .intro-side {
position:relative;
background-color: #4817a1;
background: radial-gradient(
at 50% 100%,
rgba(109, 18, 228, 0.75),
rgb(15, 1, 94)
);
color: #fff;
padding-bottom: 30px;
vertical-align: middle;
min-height: 100%;
}
.welcome .ghosted-logo {
background: transparent url("https://app.growthbook.io/logo/growth-book-logomark-ghosted.png") 50%
50%;
background-size: contain;
background-repeat: no-repeat;
min-height: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 10px;
right: 10px;
opacity: 0.5;
}
.welcome .logo {
position: absolute;
bottom: 10px;
left: 0;
right: 0;
text-align: center;
}
.welcome .form-side {
background-color: #fff;
}
.welcome .formwrap {
width: 100%;
max-width: 500px;
}
.welcome h1,
.welcome h2,
.welcome h3 {
font-weight: 600;
}
@media (min-width: 575px) {
.welcome .full-height {
min-height: 100vh;
}
.welcome .intro-side {
padding-bottom: 0;
}
}
</style>
</head>
<body>
<div class="welcome container-fluid">
<div class="row full-height align-items-stretch d-flex flex-fill d-flex justify-content-start">
<div class="col-sm-5 intro-side ">
<div class="ghosted-logo"></div>
<div class="p-sm-1 p-md-3 pt-3 pt-sm-3 pt-md-5 d-flex align-items-center justify-content-center h-100">
<div class="text-center">
<h1 class="title h1">Welcome to Growth&nbsp;Book Cloud!</h1>
<p>We&apos;re glad you&apos;re here</p>
<div class="d-none" id="extrainfo">
<p class="h4 mt-4 px-3" style="font-weight:400; font-size: 1.1em">
Get everything you need to start experimenting in as little as 2 minutes using Growth Book cloud - for free!</p>
</div>
</div>
</div>
<div class="logo">
<a
href="https://www.growthbook.io"
target="_blank"
rel="noreferrer"
>
<img
src="https://app.growthbook.io/logo/growth-book-logo-white.png"
style="max-width: 150px"
/>
</a>
</div>
</div>
<div class="col-sm-7 form-side p-0">
<div class="welcomemodal p-4 h-100">
<div class="h-100 align-items-center justify-content-center d-flex pr-2">
<div class="formwrap">
<div class="d-none" id="registerform">
<form onsubmit="return false;" method="post">
<div>
<h3 class="h2">Register</h3>
<p>
Already have an account?
<a
href="#"
id="registerSwitcher"
>
Log In
</a>
</p>
</div>
<div class="form-group">
Email Address
<input
required
type="email"
name="email"
autoFocus="true"
autoComplete="username"
id="regemail"
class="form-control"
/>
</div>
<div class="form-group">
Password
<input
required
type="password"
name="password"
autoComplete="new-password"
minLength="8"
class="form-control"
id="regpassword"
/>
</div>
<div class="captcha-container form-group"></div>
<div class="alert alert-danger error-message form-group"></div>
<button
class="btn btn-primary btn-block btn-lg mt-4"
type="submit"
id="btn-signup"
>
Sign up
</button>
<hr>
<button
type="button"
id="btn-google"
class="btn btn-lg btn-google btn-block btn-outline">
<img src="https://img.icons8.com/color/16/000000/google-logo.png" class="mr-2"> Sign up with Google
</button>
</form>
</div>
<div class="loginform" id="loginform">
<form onsubmit="return false;" method="post">
<div>
<h3 class="h2">Log In</h3>
<p>
Don&apos;t have an account yet?
<a
href="#"
id="loginSwitcher"
>
Register
</a>
</p>
</div>
<div class="form-group">
Email Address
<input
required
type="email"
name="email"
autoComplete="username"
id="loginemail"
class="form-control"
/>
</div>
<div class="form-group">
Password
<input
required
type="password"
name="password"
autoComplete="new-password"
minLength="8"
class="form-control"
id="loginpassword"
/>
<small class="form-text text-muted">
<a
href="#"
id="forgotswitcher"
>
Forgot Password?
</a>
</small>
</div>
<div class="captcha-container form-group"></div>
<div class="alert alert-danger error-message form-group"></div>
<button
class="btn btn-primary btn-block btn-lg mt-4"
type="submit"
id="btn-login"
>
Sign in
</button>
<hr>
<button
type="button"
id="btn-google2"
class="btn btn-lg btn-google btn-block btn-outline">
<img src="https://img.icons8.com/color/16/000000/google-logo.png" class="mr-2"> Sign in with Google
</button>
</form>
</div>
<div class="d-none" id="forgotpassword">
<form onsubmit="return false;" method="post">
<div>
<h3 class="h2">Forgot password</h3>
<p>
Back to
<a
href="#"
id="registerSwitcher2"
>
Log In
</a>
</p>
</div>
<div class="form-group" id="forgot-contents">
Email Address
<input
required
type="email"
name="email"
autoFocus="true"
autoComplete="username"
id="forgotemail"
class="form-control"
/>
</div>
<div class="captcha-container form-group"></div>
<div class="alert alert-danger error-message form-group"></div>
<button
class="btn btn-primary btn-block btn-lg mt-4"
type="submit"
id="btn-forgot"
>
Lookup
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--[if IE 8]>
<script src="//cdnjs.cloudflare.com/ajax/libs/ie8/0.2.5/ie8.js"></script>
<![endif]-->
<!--[if lte IE 9]>
<script src="https://cdn.auth0.com/js/polyfills/1.0/base64.min.js"></script>
<script src="https://cdn.auth0.com/js/polyfills/1.0/es5-shim.min.js"></script>
<![endif]-->
<script src="https://cdn.auth0.com/js/auth0/9.16/auth0.min.js"></script>
<script src="https://cdn.auth0.com/js/polyfills/1.0/object-assign.min.js"></script>
<script>
window.addEventListener('load', function() {
var config = JSON.parse(
decodeURIComponent(escape(window.atob('@@config@@')))
);
document.getElementById('registerSwitcher').addEventListener('click', function(e){
e.preventDefault();
clearErrors();
document.getElementById('registerform').className = 'd-none';
document.getElementById('loginform').className = '';
document.getElementById('forgotpassword').className = 'd-none';
document.getElementById('extrainfo').className = 'd-none';
});
document.getElementById('registerSwitcher2').addEventListener('click', function(e){
e.preventDefault();
clearErrors();
document.getElementById('registerform').className = 'd-none';
document.getElementById('loginform').className = '';
document.getElementById('forgotpassword').className = 'd-none';
document.getElementById('extrainfo').className = 'd-none';
});
document.getElementById('loginSwitcher').addEventListener('click', function(e){
e.preventDefault();
clearErrors();
document.getElementById('registerform').className = '';
document.getElementById('loginform').className = 'd-none';
document.getElementById('forgotpassword').className = 'd-none';
document.getElementById('extrainfo').className = '';
});
document.getElementById('forgotswitcher').addEventListener('click', function(e){
e.preventDefault();
clearErrors();
document.getElementById('registerform').className = 'd-none';
document.getElementById('loginform').className = 'd-none';
document.getElementById('forgotpassword').className = '';
document.getElementById('extrainfo').className = 'd-none';
});
if(config && "internalOptions" in config) {
var leeway = config.internalOptions.leeway;
if (leeway) {
var convertedLeeway = parseInt(leeway);
if (!isNaN(convertedLeeway)) {
config.internalOptions.leeway = convertedLeeway;
}
}
}
var params = Object.assign({
overrides: {
__tenant: config.auth0Tenant,
__token_issuer: config.authorizationServer.issuer
},
domain: config.auth0Domain,
clientID: config.clientID,
redirectUri: config.callbackURL,
responseType: 'code'
}, config.internalOptions);
var webAuth = new auth0.WebAuth(params);
var databaseConnection = 'Username-Password-Authentication';
var captcha = webAuth.renderCaptcha(
document.querySelector('.captcha-container')
);
function login(e) {
e.preventDefault();
clearErrors();
var button = this;
var username = document.getElementById('loginemail').value;
var password = document.getElementById('loginpassword').value;
button.disabled = true;
webAuth.login({
realm: databaseConnection,
username: username,
password: password,
captcha: captcha.getValue()
}, function(err) {
if (err) displayError(err);
button.disabled = false;
});
}
function forgotpassword(e) {
e.preventDefault();
clearErrors();
var button = this;
var email = document.getElementById('forgotemail').value;
button.disabled = true;
webAuth.changePassword({
connection: databaseConnection,
email: email,
captcha: captcha.getValue()
}, function (err, resp) {
if (err) {
if (err) displayError(err);
} else {
document.getElementById("forgot-contents").innerHTML = resp;
document.getElementById("btn-forgot").classList.add('d-none');
button.disabled = false;
}
});
}
function signup(e) {
e.preventDefault();
clearErrors();
var button = this;
var email = document.getElementById('regemail').value;
var password = document.getElementById('regpassword').value;
button.disabled = true;
webAuth.redirect.signupAndLogin({
connection: databaseConnection,
email: email,
password: password,
captcha: captcha.getValue()
}, function(err) {
if(err) {
displayError(err);
}
else {
console.error('unknown error', err);
}
button.disabled = false;
});
}
function loginWithGoogle() {
webAuth.authorize({
connection: 'google-oauth2'
}, function(err) {
if (err) displayError(err);
});
}
function clearErrors() {
var errorMessage = document.getElementsByClassName('error-message');
for (var i=0; i<errorMessage.length; i++) {
errorMessage[i].innerHTML = "";
errorMessage[i].style.display = 'none';
}
}
function displayError(err) {
captcha.reload();
var errorMessage = document.getElementsByClassName('error-message');
for (var i=0; i<errorMessage.length; i++) {
errorMessage[i].innerHTML = err.policy || err.description;
errorMessage[i].style.display = 'block';
}
}
document.getElementById('btn-login').addEventListener('click', login);
document.getElementById('btn-google').addEventListener('click', loginWithGoogle);
document.getElementById('btn-google2').addEventListener('click', loginWithGoogle);
document.getElementById('btn-signup').addEventListener('click', signup);
document.getElementById('btn-forgot').addEventListener('click', forgotpassword);
});
</script>
</body>
</html>
@mrsquish
Copy link

Thanks so much for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment