1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-09 15:35:22 +02:00

Remove auth0 folder.

This commit is contained in:
Anthony Shew 2024-01-14 22:30:41 -07:00
parent 9fcf21e2cc
commit a2e96f8072
16 changed files with 0 additions and 2852 deletions

View file

@ -1,101 +0,0 @@
## Quick Start
### Setting up env locally
```
AUTH0_ENV=development
AUTH0_DEPLOY_CLIENT_SECRET=
POSTMARK_SMTP_PASS=
```
- `AUTH0_ENV` - This is either `development`, `staging`, or `production`. This should **always** be `development` when working locally.
- `AUTH0_DEPLOY_CLIENT_SECRET` - The secret for the `auth0-deploy-cli-extension` application in Auth0 dashboard
- `POSTMARK_SMTP_PASS` - Go to Postmark => Servers => "Mail Server" => Message Streams => "Default Transactional Message Stream" => Settings
You will need to install the Auth0 Client to test templates (you might need to change the commands depending on your platform):
```bash
# Linux example
wget -c https://github.com/auth0/auth0-cli/releases/download/v0.11.2/auth0-cli_0.11.2_Linux_x86_64.tar.gz -O - | sudo tar -xz -C /usr/local/bin/
```
### How deployments work
Per the [Auth0 docs](https://github.com/auth0/auth0-deploy-cli/tree/master/examples/directory), this repository uses Github Actions to define each Auth0 tenant configuration.
Maybe has 3 tenants:
1. `maybe-finance-development`
2. `maybe-finance-staging`
3. `maybe-finance-production`
On each push to a branch with `auth0` in it (e.g. `someuser/pr-title-auth0`), the configuration in `tenant.yaml` will be deployed to the **staging** tenant.
On each push to `main`, the configuration in `tenant.yaml` will be deployed to the **production** tenant.
These rules are defined in `.github/workflows/deploy-auth0-staging.yml` and `.github/workflows/deploy-auth0-prod.yml` respectively.
## Editing and Testing
### `tenant.yaml`
The `tenant.yaml` file will accept any options present in the [Auth0 Management API](https://auth0.com/docs/api/management/v2).
[Here is a sample `tenant.yaml` file](https://github.com/auth0/auth0-deploy-cli/blob/master/examples/yaml/tenant.yaml).
For example, you can define tenant-wide settings using the Management API [tenant endpoint](https://auth0.com/docs/api/management/v2#!/Tenants/tenant_settings_route) (abbreviated):
```json
# Abbreviated Management API V2 tenant endpoint GET response
{
"flags": {
"revoke_refresh_token_grant": false,
...
},
"friendly_name": "My Company",
"picture_url": "https://mycompany.org/logo.png",
"support_email": "support@mycompany.org",
...
}
```
```yaml
# tenant.yaml
tenant:
flags:
revoke_refresh_token_grant: false
friendly_name: Maybe Finance
picture_url: https://assets.maybe.co/images/maybe.svg
support_email: hello@maybe.co
```
### Testing custom templates
Testing custom templates (`/auth0/emailTemplates` and `/auth0/pages`) happens in 3 steps:
1. Run `live-server` with `yarn auth0:edit`. You can make HTML/CSS changes in this view
2. To deploy to the dev tenant, run `yarn auth0:deploy` (make sure your `.env` is setup per instructions at top of this README)
3. To test the new deployment, run `yarn auth0:test`
Unfortunately, you will have to deploy **every time** you make changes to properly test since Auth0 does not have many developer tools.
References:
- Auth0 client reference - https://github.com/auth0/auth0.js/tree/master/example
- Auth0 developer tool docs - https://auth0.github.io/auth0-cli/
- Relevant Auth0 docs - https://auth0.com/docs/brand-and-customize/universal-login-page-templates#using-the-auth0-cli-
### Password Reset
Of special note is the `/auth0/pages/password_reset.html` page. Auth0 currently does not have an API for password resets, but an Auth0 employee created an
[open source example](https://github.com/auth0/auth0-custom-password-reset-hosted-page) of how to tap into the login page endpoints to customize it. If this page ever breaks (due to changes in internal Auth0 API) we can easily revert back to Universal PW reset in `tenant.yaml`:
```yaml
emailTemplates:
- template: reset_email
body: ./emailTemplates/reset_email.html
enabled: false # CHANGE THIS
```
Setting this to false will revert to the default Auth0 password reset widget (not Maybe branded, but fully functional)

View file

@ -1,90 +0,0 @@
require('dotenv').config()
const path = require('path')
const cli = require('auth0-deploy-cli')
const env = require('./env')
// CI is always set to true in Github Actions environment
if (process.env.ENV === 'production' && !process.env.CI) {
throw new Error('Cannot deploy to production outside of CI/CD workflow!')
}
let AUTH0_DOMAIN
let AUTH0_CUSTOM_DOMAIN
let AUTH0_CLIENT_ID
let CLIENT_BASE_URLS
let SERVER_BASE_URLS
let ADMIN_ROLE_ID
let BETA_TESTER_ROLE_ID
const trustedOrigins = ['https://*.maybe.co', 'https://*.vercel.app']
const logoutOrigins = [...trustedOrigins]
switch (env.AUTH0_ENV) {
case 'development':
AUTH0_DOMAIN = 'REPLACE_THIS'
AUTH0_CUSTOM_DOMAIN = AUTH0_DOMAIN
AUTH0_CLIENT_ID = 'REPLACE_THIS'
// 8484 is for the local auth0-client testing
CLIENT_BASE_URLS = [
'http://localhost:4200',
'http://localhost:8484',
'https://localhost.maybe.co',
]
CLIENT_LOGOUT_URLS = [...logoutOrigins, 'http://localhost:4200']
SERVER_BASE_URLS = ['http://localhost:3333']
ADMIN_ROLE_ID = 'REPLACE_THIS'
BETA_TESTER_ROLE_ID = 'REPLACE_THIS'
break
case 'staging':
AUTH0_DOMAIN = 'REPLACE_THIS'
AUTH0_CUSTOM_DOMAIN = AUTH0_DOMAIN
AUTH0_CLIENT_ID = 'REPLACE_THIS'
CLIENT_BASE_URLS = ['https://staging-app.maybe.co', ...trustedOrigins]
CLIENT_LOGOUT_URLS = logoutOrigins
SERVER_BASE_URLS = ['https://staging-api.maybe.co']
ADMIN_ROLE_ID = 'REPLACE_THIS'
BETA_TESTER_ROLE_ID = 'REPLACE_THIS'
break
case 'production':
AUTH0_DOMAIN = 'REPLACE_THIS'
AUTH0_CUSTOM_DOMAIN = 'login.maybe.co'
AUTH0_CLIENT_ID = 'REPLACE_THIS'
CLIENT_BASE_URLS = ['https://app.maybe.co', ...trustedOrigins]
CLIENT_LOGOUT_URLS = logoutOrigins
SERVER_BASE_URLS = ['https://api.maybe.co']
ADMIN_ROLE_ID = 'REPLACE_THIS'
BETA_TESTER_ROLE_ID = 'REPLACE_THIS'
break
default:
throw new Error("Invalid environment: should be 'development' | 'staging' | 'production'")
}
// https://auth0.com/docs/deploy/deploy-cli-tool/import-export-tenant-configuration-to-yaml-file#example-configuration-file
module.exports = {
config: {
AUTH0_DOMAIN: AUTH0_CUSTOM_DOMAIN,
AUTH0_CLIENT_ID,
AUTH0_CLIENT_SECRET: env.AUTH0_DEPLOY_CLIENT_SECRET,
/* If something exists in the tenant, but NOT the tenant.yaml file, the resource in the
tenant will NOT be deleted (hence, `false`) - keeping this set to false as a safeguard */
AUTH0_ALLOW_DELETE: false,
// https://auth0.com/docs/deploy/deploy-cli-tool/environment-variables-and-keyword-mappings
AUTH0_KEYWORD_REPLACE_MAPPINGS: {
// While the JWT is issued from login.maybe.co in production, the management API still must use the default auth0.com domain
AUTH0_DOMAIN,
CLIENT_BASE_URLS,
CLIENT_LOGOUT_URLS,
SERVER_BASE_URLS,
SERVER_CALLBACK_URLS: SERVER_BASE_URLS.map((url) => `${url}/admin/callback`),
POSTMARK_SMTP_PASS: env.POSTMARK_SMTP_PASS,
ADMIN_ROLE_ID: ADMIN_ROLE_ID,
BETA_TESTER_ROLE_ID: BETA_TESTER_ROLE_ID,
APPLE_SIGN_IN_SECRET_KEY: env.APPLE_SIGN_IN_SECRET_KEY,
},
},
input_file: path.join(__dirname, 'tenant.yaml'),
sync: cli.export,
deploy: cli.deploy,
}

View file

@ -1,15 +0,0 @@
const { config, deploy, input_file } = require('./config')
deploy({
config: {
...config,
// The deploy client only works with the DEFAULT Auth0 domain, NOT with custom domains
AUTH0_DOMAIN: config.AUTH0_KEYWORD_REPLACE_MAPPINGS.AUTH0_DOMAIN,
},
input_file,
})
.then(() =>
console.log(`Deployed ${config.AUTH0_KEYWORD_REPLACE_MAPPINGS.AUTH0_DOMAIN} successfully!`)
)
.catch((err) => console.log(`Deploy failed: ${err}`))

View file

@ -1,432 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="x-apple-disable-message-reformatting" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="color-scheme" content="light dark" />
<meta name="supported-color-schemes" content="light dark" />
<title>Password Reset</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap"
rel="stylesheet"
/>
<style type="text/css" rel="stylesheet" media="all">
:root {
color-scheme: light dark;
supported-color-schemes: light dark;
}
body {
width: 100% !important;
height: 100%;
margin: 0;
-webkit-text-size-adjust: none;
}
a {
color: #4dabf7;
}
a img {
border: none;
}
td {
word-break: break-word;
}
.preheader {
display: none !important;
visibility: hidden;
mso-hide: all;
font-size: 1px;
line-height: 1px;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
}
/* Type ------------------------------ */
body,
td,
th {
font-family: 'Inter', sans-serif;
}
h1 {
margin-top: 0;
color: #333333;
font-size: 22px;
font-weight: bold;
text-align: left;
}
h2 {
margin-top: 0;
color: #333333;
font-size: 16px;
font-weight: bold;
text-align: left;
}
h3 {
margin-top: 0;
color: #333333;
font-size: 14px;
font-weight: bold;
text-align: left;
}
td,
th {
font-size: 16px;
}
p,
ul,
ol,
blockquote {
margin: 0.4em 0 1.1875em;
font-size: 16px;
line-height: 1.625;
}
p.sub {
font-size: 13px;
}
/* Utilities ------------------------------ */
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
/* Buttons ------------------------------ */
.button {
background-color: #4dabf7;
border-top: 10px solid #4dabf7;
border-right: 18px solid #4dabf7;
border-bottom: 10px solid #4dabf7;
border-left: 18px solid #4dabf7;
display: inline-block;
color: #fff !important;
text-decoration: none;
border-radius: 3px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
-webkit-text-size-adjust: none;
box-sizing: border-box;
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
text-align: center !important;
}
}
body {
background-color: #f4f4f7;
color: #51545e;
}
p {
color: #51545e;
}
p.sub {
color: #6b6e76;
}
.email-wrapper {
width: 100%;
margin: 0;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
background-color: #f4f4f7;
}
.email-content {
width: 100%;
margin: 0;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
}
/* Masthead ----------------------- */
.email-masthead {
padding: 25px 0;
text-align: center;
}
.email-masthead_logo {
width: 94px;
}
.email-masthead_name {
font-size: 16px;
font-weight: bold;
color: #a8aaaf;
text-decoration: none;
text-shadow: 0 1px 0 white;
}
/* Body ------------------------------ */
.email-body {
width: 100%;
margin: 0;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
background-color: #ffffff;
}
.email-body_inner {
width: 570px;
margin: 0 auto;
padding: 0;
-premailer-width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
background-color: #ffffff;
}
.email-footer {
width: 570px;
margin: 0 auto;
padding: 0;
-premailer-width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
text-align: center;
}
.email-footer p {
color: #6b6e76;
}
.body-action {
width: 100%;
margin: 30px auto;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
text-align: center;
}
.body-sub {
margin-top: 25px;
padding-top: 25px;
border-top: 1px solid #eaeaec;
}
.content-cell {
padding: 35px;
}
/*Media Queries ------------------------------ */
@media only screen and (max-width: 600px) {
.email-body_inner,
.email-footer {
width: 100% !important;
}
}
@media (prefers-color-scheme: dark) {
body,
.email-body,
.email-body_inner,
.email-content,
.email-wrapper,
.email-masthead,
.email-footer {
background-color: #333333 !important;
color: #fff !important;
}
p,
ul,
ol,
blockquote,
h1,
h2,
h3,
span,
.purchase_item {
color: #fff !important;
}
.attributes_content,
.discount {
background-color: #222 !important;
}
.email-masthead_name {
text-shadow: none !important;
}
}
</style>
<!--[if mso]>
<style type="text/css">
.f-fallback {
font-family: Arial, sans-serif;
}
</style>
<![endif]-->
</head>
<body>
<span class="preheader"
>Use this link to reset your password. The link is only valid for 24 hours.</span
>
<table
class="email-wrapper"
width="100%"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td align="center">
<table
class="email-content"
width="100%"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td class="email-masthead">
<img
src="https://assets.maybe.co/images/maybe-logo.png"
alt="Maybe Logo"
style="display: block; margin: 0 auto"
/>
</td>
</tr>
<!-- Email Body -->
<tr>
<td class="email-body" width="100%" cellpadding="0" cellspacing="0">
<table
class="email-body_inner"
align="center"
width="570"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<!-- Body content -->
<tr>
<td class="content-cell">
<div class="f-fallback">
<h1>Hello,</h1>
<p>
You recently requested to reset your password
for your Maybe account. Use the button below to
reset it.
<strong
>This password reset is only valid for the
next 24 hours.</strong
>
</p>
<!-- Action -->
<table
class="body-action"
align="center"
width="100%"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td align="center">
<!-- Border based button
https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
<table
width="100%"
border="0"
cellspacing="0"
cellpadding="0"
role="presentation"
>
<tr>
<td align="center">
<a
class="f-fallback button button--green"
target="_blank"
href="{{ url }}"
>Reset password</a
>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
If you did not request a password reset, please
ignore this email or
<a href="mailto:{{ support_email }}"
>contact support</a
>
if you have questions.
</p>
<p>Thanks, <br />The Maybe Team</p>
<!-- Sub copy -->
<table class="body-sub" role="presentation">
<tr>
<td>
<p class="f-fallback sub">
If youre having trouble with the
button above, copy and paste the URL
below into your web browser.
</p>
<p class="f-fallback sub">{{ url }}</p>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table
class="email-footer"
align="center"
width="570"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td class="content-cell" align="center">
<p class="f-fallback sub align-center">
&copy; {{ "now" | date: "%Y" }} Maybe Finance, Inc.
All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View file

@ -1,427 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="x-apple-disable-message-reformatting" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="color-scheme" content="light dark" />
<meta name="supported-color-schemes" content="light dark" />
<title>Verify Email</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap"
rel="stylesheet"
/>
<style type="text/css" rel="stylesheet" media="all">
:root {
color-scheme: light dark;
supported-color-schemes: light dark;
}
body {
width: 100% !important;
height: 100%;
margin: 0;
-webkit-text-size-adjust: none;
}
a {
color: #4dabf7;
}
a img {
border: none;
}
td {
word-break: break-word;
}
.preheader {
display: none !important;
visibility: hidden;
mso-hide: all;
font-size: 1px;
line-height: 1px;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
}
/* Type ------------------------------ */
body,
td,
th {
font-family: 'Inter', sans-serif;
}
h1 {
margin-top: 0;
color: #333333;
font-size: 22px;
font-weight: bold;
text-align: left;
}
h2 {
margin-top: 0;
color: #333333;
font-size: 16px;
font-weight: bold;
text-align: left;
}
h3 {
margin-top: 0;
color: #333333;
font-size: 14px;
font-weight: bold;
text-align: left;
}
td,
th {
font-size: 16px;
}
p,
ul,
ol,
blockquote {
margin: 0.4em 0 1.1875em;
font-size: 16px;
line-height: 1.625;
}
p.sub {
font-size: 13px;
}
/* Utilities ------------------------------ */
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
/* Buttons ------------------------------ */
.button {
background-color: #4dabf7;
border-top: 10px solid #4dabf7;
border-right: 18px solid #4dabf7;
border-bottom: 10px solid #4dabf7;
border-left: 18px solid #4dabf7;
display: inline-block;
color: #fff !important;
text-decoration: none;
border-radius: 3px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
-webkit-text-size-adjust: none;
box-sizing: border-box;
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
text-align: center !important;
}
}
body {
background-color: #f4f4f7;
color: #51545e;
}
p {
color: #51545e;
}
p.sub {
color: #6b6e76;
}
.email-wrapper {
width: 100%;
margin: 0;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
background-color: #f4f4f7;
}
.email-content {
width: 100%;
margin: 0;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
}
/* Masthead ----------------------- */
.email-masthead {
padding: 25px 0;
text-align: center;
}
.email-masthead_logo {
width: 94px;
}
.email-masthead_name {
font-size: 16px;
font-weight: bold;
color: #a8aaaf;
text-decoration: none;
text-shadow: 0 1px 0 white;
}
/* Body ------------------------------ */
.email-body {
width: 100%;
margin: 0;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
background-color: #ffffff;
}
.email-body_inner {
width: 570px;
margin: 0 auto;
padding: 0;
-premailer-width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
background-color: #ffffff;
}
.email-footer {
width: 570px;
margin: 0 auto;
padding: 0;
-premailer-width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
text-align: center;
}
.email-footer p {
color: #6b6e76;
}
.body-action {
width: 100%;
margin: 30px auto;
padding: 0;
-premailer-width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
text-align: center;
}
.body-sub {
margin-top: 25px;
padding-top: 25px;
border-top: 1px solid #eaeaec;
}
.content-cell {
padding: 35px;
}
/*Media Queries ------------------------------ */
@media only screen and (max-width: 600px) {
.email-body_inner,
.email-footer {
width: 100% !important;
}
}
@media (prefers-color-scheme: dark) {
body,
.email-body,
.email-body_inner,
.email-content,
.email-wrapper,
.email-masthead,
.email-footer {
background-color: #333333 !important;
color: #fff !important;
}
p,
ul,
ol,
blockquote,
h1,
h2,
h3,
span,
.purchase_item {
color: #fff !important;
}
.attributes_content,
.discount {
background-color: #222 !important;
}
.email-masthead_name {
text-shadow: none !important;
}
}
</style>
<!--[if mso]>
<style type="text/css">
.f-fallback {
font-family: Arial, sans-serif;
}
</style>
<![endif]-->
</head>
<body>
<span class="preheader">Verify your account and start using Maybe today!</span>
<table
class="email-wrapper"
width="100%"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td align="center">
<table
class="email-content"
width="100%"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td class="email-masthead">
<img
src="https://assets.maybe.co/images/maybe-logo.png"
alt="Maybe Logo"
style="display: block; margin: 0 auto"
/>
</td>
</tr>
<!-- Email Body -->
<tr>
<td class="email-body" width="100%" cellpadding="0" cellspacing="0">
<table
class="email-body_inner"
align="center"
width="570"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<!-- Body content -->
<tr>
<td class="content-cell">
<div class="f-fallback">
<h1>Welcome to Maybe, {{ user.given_name }}!</h1>
<p>
We're so glad you're here! At Maybe, we take
your data and privacy seriously. Please click
the link below to confirm your email so we know
you're a real person!
</p>
<!-- Action -->
<table
class="body-action"
align="center"
width="100%"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td align="center">
<!-- Border based button
https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
<table
width="100%"
border="0"
cellspacing="0"
cellpadding="0"
role="presentation"
>
<tr>
<td align="center">
<a
class="f-fallback button"
target="_blank"
href="{{ url }}"
>Confirm email</a
>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p>
If you did not sign up to Maybe, please ignore
this email or
<a href="mailto:{{ support_email }}"
>contact support</a
>
if you have questions.
</p>
<p>Thanks, <br />The Maybe Team</p>
<!-- Sub copy -->
<table class="body-sub" role="presentation">
<tr>
<td>
<p class="f-fallback sub">
If youre having trouble with the
button above, copy and paste the URL
below into your web browser.
</p>
<p class="f-fallback sub">{{ url }}</p>
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table
class="email-footer"
align="center"
width="570"
cellpadding="0"
cellspacing="0"
role="presentation"
>
<tr>
<td class="content-cell" align="center">
<p class="f-fallback sub align-center">
&copy; {{ "now" | date: "%Y" }} Maybe Finance, Inc.
All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View file

@ -1,12 +0,0 @@
const z = require('zod')
const envSchema = z.object({
AUTH0_DEPLOY_CLIENT_SECRET: z.string(),
AUTH0_ENV: z.string().default('development'),
POSTMARK_SMTP_PASS: z.string(),
APPLE_SIGN_IN_SECRET_KEY: z.string(),
})
const env = envSchema.parse(process.env)
module.exports = env

View file

@ -1,95 +0,0 @@
<!-- This page is not currently in use (see tenant.yaml) -->
<!DOCTYPE html>
<html>
<head>
<title>MFA Auth Maybe Finance</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link
rel="shortcut icon"
type="image/png"
href="https://app.maybe.co/assets/favicon-32x32.png"
/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<style type="text/css">
html, body { padding: 0; margin: 0; }
.table {
display: table;
position: absolute;
height: 100%;
width: 100%;
background-color: {{ pageBackgroundColor | default: '#2b2b33' }};
}
.cell {
display: table-cell;
vertical-align: middle;
}
.content {
padding: 25px 0px 25px 0px;
margin-left: auto;
margin-right: auto;
width: 280px; /* login widget width */
}
</style>
</head>
<body>
<div class="table">
<div class="cell">
<div class="content">
<!-- WIDGET -->
<div class="js-mfa-container mfa-container" id="container"></div>
</div>
</div>
</div>
<script src="//cdn.auth0.com/js/mfa-widget/mfa-widget-1.8.min.js"></script>
<script>
(function() {
return new Auth0MFAWidget({
container: "container",
theme: {
icon: "{{ iconUrl | default: '//cdn.auth0.com/styleguide/1.0.0/img/badge.png' }}",
primaryColor: "{{ primaryColor | default: '#ea5323' }}"
},
requesterErrors: [
{% for error in errors %}
{ message: "{{ error.message }}", errorCode: "{{ error.code }}" }
{% endfor %}
],
mfaServerUrl: "{{ mfaServerUrl }}",
{% if ticket %}
ticket: "{{ ticket }}",
{% else %}
requestToken: "{{ requestToken }}",
{% endif %}
postActionURL: "{{ postActionURL }}",
userData: {
userId: "{{ userData.userId }}",
email: "{{ userData.email }}",
friendlyUserId: "{{ userData.friendlyUserId }}",
tenant: "{{ userData.tenant }}",
{% if userData.tenantFriendlyName %}
tenantFriendlyName: "{{ userData.tenantFriendlyName }}"
{% endif %}
},
globalTrackingId: "{{ globalTrackingId }}",
{% if allowRememberBrowser %}allowRememberBrowser: {{ allowRememberBrowser }}, {% endif %}
{% if stateCheckingMechanism %}stateCheckingMechanism: "{{ stateCheckingMechanism }}", {% endif %}
});
})();
</script>
</body>
</html>

View file

@ -1,685 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Maybe Login</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="shortcut icon"
type="image/png"
href="https://app.maybe.co/assets/favicon-32x32.png"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap"
rel="stylesheet"
/>
<style>
[x-cloak] {
display: none !important;
}
:root {
--bg-color: #242629;
--cyan: #3bc9db;
--white-text: #f8f9fa;
--gray-text: #868e96;
--black-text: #242629;
--alert: #ff8787;
--success: #38d9a9;
}
@font-face {
font-family: 'Monument Extended';
font-weight: 700;
src: url('https://assets.maybe.co/fonts/monument/MonumentExtended-Bold.woff2')
format('woff2');
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Inter', sans-serif;
font-size: 14px;
}
body,
html {
background-color: var(--bg-color);
color: var(--gray-text);
padding: 0 10px;
}
form {
width: 100%;
max-width: 360px;
}
input,
select {
font-family: 'Inter', sans-serif;
width: 100%;
background: none;
border: 1px solid #48494b;
border-radius: 4px;
height: 40px;
margin-bottom: 10px;
color: white;
text-indent: 12px;
}
input:focus,
select:focus {
outline: none;
border: 1px solid var(--cyan);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 30px var(--bg-color) inset !important;
}
/*Change text in autofill textbox*/
input:-webkit-autofill {
-webkit-text-fill-color: var(--white-text) !important;
caret-color: var(--white-text);
}
h2 {
font-family: 'Monument Extended', sans-serif;
font-weight: 700;
font-size: 30px;
color: var(--white-text);
margin-bottom: 20px;
margin-top: 50px;
}
a {
color: var(--cyan);
text-decoration: none;
}
a:hover {
text-decoration: underline;
opacity: 0.875;
}
.btn {
padding: 8px;
border: none;
}
.btn:disabled {
opacity: 0.9;
}
.btn-block {
border-radius: 4px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
max-width: 360px;
width: 100%;
font-weight: 500;
}
.btn-text {
background: none;
border: none;
font-size: 14px;
color: var(--cyan);
}
.btn-primary {
background-color: var(--cyan);
}
.btn-white {
background: var(--white-text);
}
.btn-block:hover {
opacity: 0.875;
cursor: pointer;
}
.btn-text:hover {
text-decoration: underline;
opacity: 0.875;
cursor: pointer;
}
.action-btn {
margin-top: 24px;
}
#google-btn {
margin-bottom: 16px;
}
.container {
position: relative;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container-modal {
width: 100%;
max-width: 420px;
}
.auth-header {
text-align: center;
}
.title {
margin-bottom: 40px;
}
.form-container {
display: flex;
justify-content: center;
align-items: center;
}
.social {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.social button span {
margin-left: 5px;
color: var(--black-text);
}
.divider {
border-bottom: 1px solid #2f3134;
margin: 32px auto;
width: 100%;
max-width: 360px;
}
.disclosure {
text-align: center;
width: 540px;
max-width: 100%;
margin: 32px auto;
}
.disclosure * {
font-size: 12px;
}
.password-form-group {
position: relative;
}
.show-password-icon {
position: absolute;
right: 25px;
top: 10px;
}
.show-password-icon:hover {
cursor: pointer;
fill: var(--gray-text);
}
.show-password {
fill: var(--gray-text);
}
.register-form-group {
display: flex;
justify-content: space-between;
gap: 8px;
}
.toast {
position: absolute;
z-index: 10;
bottom: 20px;
right: 20px;
display: flex;
padding: 8px 16px;
border-radius: 4px;
align-items: center;
color: #242629;
}
.toast-message {
margin-left: 8px;
margin-bottom: 1px;
}
.toast-success {
background-color: var(--success);
}
.toast-error {
background-color: var(--alert);
}
#loader {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.svg-loader {
transform: scale(1);
animation: pulse 2.5s infinite;
}
#email-pw-reset {
color: var(--white-text);
}
@keyframes pulse {
0% {
transform: scale(0.95);
}
50% {
transform: scale(1);
opacity: 0.4;
}
100% {
transform: scale(0.95);
}
}
</style>
<script src="https://cdn.auth0.com/js/auth0/9.19/auth0.min.js"></script>
<script type="text/javascript">
const config =
'@@config@@'.length > 10
? JSON.parse(decodeURIComponent(escape(window.atob('@@config@@'))))
: {
auth0Domain: 'maybe-finance-development.us.auth0.com',
clientID: '7MtD6RWsXKInGPrFyeEseo7Y8PXSBEiV',
}
const options = {
overrides: {
__tenant: config.auth0Tenant,
__token_issuer: config.authorizationServer?.issuer,
},
domain: config.auth0Domain,
clientID: config.clientID,
redirectUri: config.callbackURL,
responseType: 'code',
...config.internalOptions,
}
const webAuth = new auth0.WebAuth(options)
console.debug('initialized auth0')
</script>
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body
x-data="{
init() {
console.debug('initializing alpine data')
if (this.screenHint === 'signup') {
this.setView('register')
}
},
/* current view */
view: 'login',
setView(view) {
this.view = view
},
isView(...view) {
return view.includes(this.view)
},
screenHint: new URLSearchParams(window.location.search).get('screen_hint'),
debug: new URLSearchParams(window.location.search).get('debug'),
/* notifications */
notifications: [],
addNotification(e) {
this.notifications.push({
id: e.timeStamp,
type: e.detail.type,
message: e.detail.message,
})
},
removeNotification(notification) {
this.notifications = this.notifications.filter(i => i.id !== notification.id)
},
/* captcha */
captcha: null,
renderCaptcha() {
try {
this.captcha = webAuth.renderCaptcha(this.$el)
} catch (e) {
console.warn('failed to render captcha', e)
}
},
/* auth functions */
submitting: false,
login(e) {
this.submitting = true
const { email, password } = Object.fromEntries(new FormData(e.target));
webAuth.login(
{
realm: 'Username-Password-Authentication',
email,
password,
captcha: this.captcha?.getValue(),
},
(err) => {
this.submitting = false
if (err) {
$dispatch('notify', { type: 'error', message: err.policy || err.description })
}
}
)
},
loginWithProvider(connection) {
webAuth.authorize({ connection }, (err) => {
if (err) {
$dispatch('notify', { type: 'error', message: err.policy || err.description })
}
})
},
signUp(e) {
this.submitting = true;
const { firstName, lastName, email, password } = Object.fromEntries(new FormData(e.target));
webAuth.signup(
{
connection: 'Username-Password-Authentication',
email,
password,
username: email,
given_name: firstName,
family_name: lastName,
name: `${firstName} ${lastName}`,
captcha: this.captcha?.getValue(),
},
(err) => {
this.submitting = false;
if (err) {
$dispatch('notify', { type: 'error', message: err.policy || err.description })
} else {
webAuth.login(
{
realm: 'Username-Password-Authentication',
email,
password,
},
(err) => {
if (err) {
$dispatch('notify', { type: 'error', message: err.policy || err.description })
} else {
$dispatch('notify', { type: 'success', message: 'You are now logged in!' })
}
}
)
}
}
)
},
resetPassword(e) {
this.submitting = true;
const { email } = Object.fromEntries(new FormData(e.target));
webAuth.changePassword(
{
connection: 'Username-Password-Authentication',
email: email,
},
(err, res) => {
this.submitting = false;
if (err) {
$dispatch('notify', { type: 'error', message: err.policy || err.description })
} else {
$nextTick(() => this.setView('reset-sent'))
}
}
)
},
}"
@notify.window="addNotification($event)"
>
<!-- notifications -->
<template x-for="notification in notifications" :key="notification.id">
<div
class="toast"
:class="`toast-${notification.type}`"
x-data="{
show: false,
init() {
this.$nextTick(() => this.show = true)
setTimeout(() => this.hide(), 8000)
},
hide() {
this.show = false
setTimeout(() => this.removeNotification(this.notification), 500)
},
}"
x-show="show"
@click="hide()"
x-transition.duration.500ms
>
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M1.6665 9.99984C1.6665 5.39746 5.39746 1.6665 9.99984 1.6665C12.21 1.6665 14.3296 2.54448 15.8924 4.10728C17.4552 5.67008 18.3332 7.7897 18.3332 9.99984C18.3332 14.6022 14.6022 18.3332 9.99984 18.3332C5.39746 18.3332 1.6665 14.6022 1.6665 9.99984ZM3.33317 9.99984C3.33317 13.6817 6.31794 16.6665 9.99984 16.6665C11.7679 16.6665 13.4636 15.9641 14.7139 14.7139C15.9641 13.4636 16.6665 11.7679 16.6665 9.99984C16.6665 6.31794 13.6817 3.33317 9.99984 3.33317C6.31794 3.33317 3.33317 6.31794 3.33317 9.99984ZM9.58317 11.6665C9.35305 11.6665 9.1665 11.8531 9.1665 12.0832V12.9165C9.1665 13.1466 9.35305 13.3332 9.58317 13.3332H10.4165C10.6466 13.3332 10.8332 13.1466 10.8332 12.9165V12.0832C10.8332 11.8531 10.6466 11.6665 10.4165 11.6665H9.58317ZM9.43317 6.6665H10.5665C10.6862 6.66564 10.8006 6.71633 10.8803 6.80565C10.9601 6.89497 10.9975 7.01429 10.9832 7.13317L10.6498 9.8165C10.6371 9.9217 10.5475 10.0006 10.4415 9.99984H9.55817C9.45221 10.0006 9.36255 9.9217 9.34984 9.8165L9.0165 7.13317C9.00213 7.01429 9.0396 6.89497 9.11935 6.80565C9.1991 6.71633 9.31343 6.66564 9.43317 6.6665Z"
fill="#2F3134"
/>
</svg>
<span class="toast-message" x-text="notification.message"></span>
</div>
</template>
<template x-if="debug">
<div style="position: absolute; top: 12px; right: 12px; z-index: 1">
<div style="position: relative">
<select x-model="view">
<option>login</option>
<option>register</option>
<option>reset</option>
<option>reset-sent</option>
</select>
</div>
</div>
</template>
<div class="container" x-cloak>
<div class="container-modal">
<!-- header -->
<div class="auth-header">
<img src="https://assets.maybe.co/images/maybe.svg" width="90" />
<div class="title" x-show="isView('login')">
<h2>Log in to Maybe</h2>
</div>
<div class="title" x-show="isView('register')">
<h2>Sign up for Maybe</h2>
<p>
Already have an account?
<button class="btn btn-text to-login" @click="setView('login')">
Log in
</button>
</p>
</div>
<div class="title" x-show="isView('reset')">
<h2>Reset Password</h2>
<p>
Enter your email address and we'll send you a link to reset your
password.
</p>
</div>
<div class="title" x-show="isView('reset-sent')">
<h2>Check your email</h2>
<p>
You should receive a reset link shortly. If you do not receive an email,
please contact us.
</p>
</div>
</div>
<!-- social logins -->
<div
class="social social-btns"
x-show="isView('login', 'register') && screenHint !== 'show-form-only'"
>
<button class="btn btn-block btn-white" @click="loginWithProvider('apple')">
<img src="https://assets.maybe.co/images/apple-icon.svg" width="20" />
<span
x-text="isView('login') ? 'Log in with Apple' : 'Sign up with Apple'"
></span>
</button>
</div>
<div x-show="isView('login', 'register')" class="divider"></div>
<div class="form-container">
<!-- login form -->
<template x-if="isView('login')">
<form @submit.prevent="login($event)">
<input
name="email"
type="email"
autocomplete="email"
placeholder="Enter your email address"
required
/>
<div class="password-form-group" x-data="{ show: false }">
<input
name="password"
:type="show ? 'text' : 'password'"
autocomplete="current-password"
placeholder="Password"
required
/>
<svg
class="show-password-icon"
@click="show = !show"
:class="show && 'show-password'"
width="20"
height="20"
viewBox="0 0 25 24"
fill="#38393B"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18.382 19.2969C16.6232 20.4125 14.5827 21.0033 12.5 20.9999C7.108 20.9999 2.622 17.1199 1.681 11.9999C2.11103 9.67066 3.28263 7.54284 5.021 5.93394L1.892 2.80794L3.307 1.39294L23.106 21.1929L21.691 22.6069L18.381 19.2969H18.382ZM6.435 7.34994C5.076 8.58553 4.12932 10.2087 3.723 11.9999C4.03529 13.3664 4.66226 14.6411 5.554 15.7225C6.44574 16.804 7.57763 17.6623 8.85955 18.2293C10.1415 18.7962 11.538 19.056 12.9381 18.9881C14.3381 18.9201 15.703 18.5263 16.924 17.8379L14.896 15.8099C14.0327 16.3538 13.0102 16.588 11.9962 16.4744C10.9823 16.3607 10.037 15.9058 9.31557 15.1844C8.5941 14.4629 8.13923 13.5177 8.02556 12.5037C7.9119 11.4897 8.14618 10.4673 8.69 9.60394L6.435 7.34994ZM13.414 14.3279L10.172 11.0859C9.99406 11.5389 9.95219 12.0339 10.0515 12.5103C10.1508 12.9867 10.387 13.4237 10.7311 13.7678C11.0752 14.1119 11.5123 14.3481 11.9887 14.4474C12.465 14.5468 12.9601 14.5049 13.413 14.3269L13.414 14.3279ZM21.307 16.5919L19.876 15.1619C20.5445 14.2092 21.0204 13.1351 21.277 11.9999C21.0052 10.8097 20.4943 9.68709 19.7751 8.70044C19.056 7.71379 18.1438 6.88367 17.0939 6.26055C16.044 5.63743 14.8783 5.23431 13.6677 5.07571C12.4572 4.9171 11.227 5.00632 10.052 5.33794L8.474 3.75994C9.721 3.26994 11.08 2.99994 12.5 2.99994C17.892 2.99994 22.378 6.87994 23.319 11.9999C23.0126 13.6656 22.3239 15.2375 21.307 16.5919ZM12.223 7.50794C12.8595 7.46861 13.4971 7.56501 14.0935 7.79076C14.69 8.01651 15.2316 8.36646 15.6825 8.81739C16.1335 9.26833 16.4834 9.80997 16.7092 10.4064C16.9349 11.0028 17.0313 11.6404 16.992 12.2769L12.222 7.50794H12.223Z"
fill="inherit"
/>
</svg>
</div>
<div x-init="renderCaptcha()"></div>
<button
type="submit"
class="btn btn-primary btn-block action-btn"
:disabled="submitting"
>
Continue with email
</button>
<button
type="button"
class="btn btn-text btn-block action-btn"
@click="setView('reset')"
>
Forgot your password?
</button>
</form>
</template>
<!-- password reset form -->
<template x-if="isView('reset')">
<form @submit.prevent="resetPassword($event)">
<input
name="email"
type="email"
autocomplete="email"
placeholder="Enter your email address"
required
/>
<button
type="submit"
class="btn btn-primary btn-block action-btn"
:disabled="submitting"
>
Send reset link
</button>
<button
type="button"
class="btn btn-text btn-block action-btn"
@click="setView('login')"
>
Back to login
</button>
</form>
</template>
<!-- password reset sent -->
<template x-if="isView('reset-sent')">
<button
type="button"
class="btn btn-text btn-block action-btn"
@click="setView('login')"
>
Back to login
</button>
</template>
</div>
</div>
<!-- disclosure -->
<div x-show="isView('login', 'register')" class="disclosure">
<p style="margin-bottom: 10px">
By signing up, you acknowledge that you have read and understood, and agree to
Maybe's
<a href="https://maybe.co/terms">Terms and Conditions</a> and
<a href="https://maybe.co/privacy">Privacy Policy.</a>
</p>
</div>
</div>
</body>
</html>

View file

@ -1,427 +0,0 @@
<!--
This reset page is a workaround published by an Auth0 employee (because Auth0 doesn't natively support a custom pw reset page)
https://github.com/auth0/auth0-custom-password-reset-hosted-page
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link
rel="shortcut icon"
type="image/png"
href="https://app.maybe.co/assets/favicon-32x32.png"
/>
<style>
:root {
--bg-color: #242629;
--cyan: #3bc9db;
--white-text: #f8f9fa;
--gray-text: #868e96;
--black-text: #242629;
--alert: #ff8787;
--success: #38d9a9;
}
@font-face {
font-family: 'Monument Extended';
font-weight: 700;
src: url('https://assets.maybe.co/fonts/monument/MonumentExtended-Bold.woff2')
format('woff2');
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Inter', sans-serif;
font-size: 14px;
}
body,
html {
background-color: var(--bg-color);
color: var(--gray-text);
padding: 0 10px;
}
form {
width: 100%;
max-width: 360px;
}
input {
font-family: 'Inter', sans-serif;
width: 100%;
background: none;
border: 1px solid #48494b;
border-radius: 4px;
height: 40px;
margin-bottom: 10px;
color: white;
text-indent: 12px;
}
input:focus {
outline: none;
border: 1px solid var(--cyan);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 30px var(--bg-color) inset !important;
}
/*Change text in autofill textbox*/
input:-webkit-autofill {
-webkit-text-fill-color: var(--white-text) !important;
caret-color: var(--white-text);
}
h2 {
font-family: 'Monument Extended', sans-serif;
font-weight: 700;
font-size: 30px;
color: var(--white-text);
margin-bottom: 20px;
margin-top: 50px;
}
a {
color: var(--cyan);
text-decoration: none;
}
a:hover {
text-decoration: underline;
opacity: 0.875;
}
.btn {
padding: 8px;
border: none;
margin-top: 20px;
}
.btn-block {
border-radius: 4px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
max-width: 360px;
width: 100%;
font-weight: 500;
}
.btn-text {
background: none;
border: none;
font-size: 14px;
color: var(--cyan);
}
.btn-primary {
background-color: var(--cyan);
}
.btn-white {
background: var(--white-text);
}
.btn-block:hover {
opacity: 0.875;
cursor: pointer;
}
.btn-text:hover {
text-decoration: underline;
opacity: 0.875;
cursor: pointer;
}
.container {
position: relative;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container-modal {
width: 100%;
max-width: 470px;
}
.auth-header {
text-align: center;
}
.title {
margin-bottom: 40px;
}
.form-container {
display: flex;
justify-content: center;
align-items: center;
}
.password-form-group {
position: relative;
}
.show-password-input-icon {
position: absolute;
right: 25px;
top: 10px;
}
.show-password-input-icon:hover {
cursor: pointer;
fill: var(--gray-text);
}
.show-password {
fill: var(--gray-text);
}
.toast {
position: absolute;
bottom: 20px;
right: 20px;
display: flex;
padding: 8px 16px;
border-radius: 4px;
align-items: center;
color: #242629;
}
#toast-success {
background-color: var(--success);
}
#toast-error {
background-color: var(--alert);
}
#fail-message,
#success-message {
margin-left: 8px;
margin-bottom: 1px;
}
</style>
</head>
<body>
<div id="toast-error" class="toast">
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M1.6665 9.99984C1.6665 5.39746 5.39746 1.6665 9.99984 1.6665C12.21 1.6665 14.3296 2.54448 15.8924 4.10728C17.4552 5.67008 18.3332 7.7897 18.3332 9.99984C18.3332 14.6022 14.6022 18.3332 9.99984 18.3332C5.39746 18.3332 1.6665 14.6022 1.6665 9.99984ZM3.33317 9.99984C3.33317 13.6817 6.31794 16.6665 9.99984 16.6665C11.7679 16.6665 13.4636 15.9641 14.7139 14.7139C15.9641 13.4636 16.6665 11.7679 16.6665 9.99984C16.6665 6.31794 13.6817 3.33317 9.99984 3.33317C6.31794 3.33317 3.33317 6.31794 3.33317 9.99984ZM9.58317 11.6665C9.35305 11.6665 9.1665 11.8531 9.1665 12.0832V12.9165C9.1665 13.1466 9.35305 13.3332 9.58317 13.3332H10.4165C10.6466 13.3332 10.8332 13.1466 10.8332 12.9165V12.0832C10.8332 11.8531 10.6466 11.6665 10.4165 11.6665H9.58317ZM9.43317 6.6665H10.5665C10.6862 6.66564 10.8006 6.71633 10.8803 6.80565C10.9601 6.89497 10.9975 7.01429 10.9832 7.13317L10.6498 9.8165C10.6371 9.9217 10.5475 10.0006 10.4415 9.99984H9.55817C9.45221 10.0006 9.36255 9.9217 9.34984 9.8165L9.0165 7.13317C9.00213 7.01429 9.0396 6.89497 9.11935 6.80565C9.1991 6.71633 9.31343 6.66564 9.43317 6.6665Z"
fill="#2F3134"
/>
</svg>
<span id="fail-message">Something went wrong. Please try again.</span>
</div>
<div id="toast-success" class="toast">
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M1.6665 9.99984C1.6665 5.39746 5.39746 1.6665 9.99984 1.6665C12.21 1.6665 14.3296 2.54448 15.8924 4.10728C17.4552 5.67008 18.3332 7.7897 18.3332 9.99984C18.3332 14.6022 14.6022 18.3332 9.99984 18.3332C5.39746 18.3332 1.6665 14.6022 1.6665 9.99984ZM3.33317 9.99984C3.33317 13.6817 6.31794 16.6665 9.99984 16.6665C11.7679 16.6665 13.4636 15.9641 14.7139 14.7139C15.9641 13.4636 16.6665 11.7679 16.6665 9.99984C16.6665 6.31794 13.6817 3.33317 9.99984 3.33317C6.31794 3.33317 3.33317 6.31794 3.33317 9.99984ZM9.58317 11.6665C9.35305 11.6665 9.1665 11.8531 9.1665 12.0832V12.9165C9.1665 13.1466 9.35305 13.3332 9.58317 13.3332H10.4165C10.6466 13.3332 10.8332 13.1466 10.8332 12.9165V12.0832C10.8332 11.8531 10.6466 11.6665 10.4165 11.6665H9.58317ZM9.43317 6.6665H10.5665C10.6862 6.66564 10.8006 6.71633 10.8803 6.80565C10.9601 6.89497 10.9975 7.01429 10.9832 7.13317L10.6498 9.8165C10.6371 9.9217 10.5475 10.0006 10.4415 9.99984H9.55817C9.45221 10.0006 9.36255 9.9217 9.34984 9.8165L9.0165 7.13317C9.00213 7.01429 9.0396 6.89497 9.11935 6.80565C9.1991 6.71633 9.31343 6.66564 9.43317 6.6665Z"
fill="#2F3134"
/>
</svg>
<span id="success-message">Your password was reset.</span>
</div>
<div class="container">
<div class="container-modal">
<div class="auth-header">
<img src="https://assets.maybe.co/images/maybe.svg" width="90" />
<div class="title login">
<h2>Set new password</h2>
<p>Enter new password.</p>
</div>
</div>
<div class="form-container">
<form id="change-password-form" action="/lo/reset" method="post">
<!-- Do not remove these. This protects against CSRF vulnerabilities -->
<input type="hidden" name="_csrf" value="{{csrf_token}}" />
<input type="hidden" name="ticket" value="{{ticket}}" />
<input type="hidden" name="email" value="{{email}}" />
<div class="password-form-group">
<input
type="password"
id="newPassword"
name="newPassword"
placeholder="Password"
/>
<svg
id="setPasswordIcon"
class="show-password-input-icon"
width="20"
height="20"
viewBox="0 0 25 24"
fill="#38393B"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18.382 19.2969C16.6232 20.4125 14.5827 21.0033 12.5 20.9999C7.108 20.9999 2.622 17.1199 1.681 11.9999C2.11103 9.67066 3.28263 7.54284 5.021 5.93394L1.892 2.80794L3.307 1.39294L23.106 21.1929L21.691 22.6069L18.381 19.2969H18.382ZM6.435 7.34994C5.076 8.58553 4.12932 10.2087 3.723 11.9999C4.03529 13.3664 4.66226 14.6411 5.554 15.7225C6.44574 16.804 7.57763 17.6623 8.85955 18.2293C10.1415 18.7962 11.538 19.056 12.9381 18.9881C14.3381 18.9201 15.703 18.5263 16.924 17.8379L14.896 15.8099C14.0327 16.3538 13.0102 16.588 11.9962 16.4744C10.9823 16.3607 10.037 15.9058 9.31557 15.1844C8.5941 14.4629 8.13923 13.5177 8.02556 12.5037C7.9119 11.4897 8.14618 10.4673 8.69 9.60394L6.435 7.34994ZM13.414 14.3279L10.172 11.0859C9.99406 11.5389 9.95219 12.0339 10.0515 12.5103C10.1508 12.9867 10.387 13.4237 10.7311 13.7678C11.0752 14.1119 11.5123 14.3481 11.9887 14.4474C12.465 14.5468 12.9601 14.5049 13.413 14.3269L13.414 14.3279ZM21.307 16.5919L19.876 15.1619C20.5445 14.2092 21.0204 13.1351 21.277 11.9999C21.0052 10.8097 20.4943 9.68709 19.7751 8.70044C19.056 7.71379 18.1438 6.88367 17.0939 6.26055C16.044 5.63743 14.8783 5.23431 13.6677 5.07571C12.4572 4.9171 11.227 5.00632 10.052 5.33794L8.474 3.75994C9.721 3.26994 11.08 2.99994 12.5 2.99994C17.892 2.99994 22.378 6.87994 23.319 11.9999C23.0126 13.6656 22.3239 15.2375 21.307 16.5919ZM12.223 7.50794C12.8595 7.46861 13.4971 7.56501 14.0935 7.79076C14.69 8.01651 15.2316 8.36646 15.6825 8.81739C16.1335 9.26833 16.4834 9.80997 16.7092 10.4064C16.9349 11.0028 17.0313 11.6404 16.992 12.2769L12.222 7.50794H12.223Z"
fill="inherit"
/>
</svg>
</div>
<div class="password-form-group">
<input
type="password"
id="confirmNewPassword"
name="confirmNewPassword"
placeholder="Confirm password"
/>
<svg
id="confirmPasswordIcon"
class="show-password-input-icon"
width="20"
height="20"
viewBox="0 0 25 24"
fill="#38393B"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M18.382 19.2969C16.6232 20.4125 14.5827 21.0033 12.5 20.9999C7.108 20.9999 2.622 17.1199 1.681 11.9999C2.11103 9.67066 3.28263 7.54284 5.021 5.93394L1.892 2.80794L3.307 1.39294L23.106 21.1929L21.691 22.6069L18.381 19.2969H18.382ZM6.435 7.34994C5.076 8.58553 4.12932 10.2087 3.723 11.9999C4.03529 13.3664 4.66226 14.6411 5.554 15.7225C6.44574 16.804 7.57763 17.6623 8.85955 18.2293C10.1415 18.7962 11.538 19.056 12.9381 18.9881C14.3381 18.9201 15.703 18.5263 16.924 17.8379L14.896 15.8099C14.0327 16.3538 13.0102 16.588 11.9962 16.4744C10.9823 16.3607 10.037 15.9058 9.31557 15.1844C8.5941 14.4629 8.13923 13.5177 8.02556 12.5037C7.9119 11.4897 8.14618 10.4673 8.69 9.60394L6.435 7.34994ZM13.414 14.3279L10.172 11.0859C9.99406 11.5389 9.95219 12.0339 10.0515 12.5103C10.1508 12.9867 10.387 13.4237 10.7311 13.7678C11.0752 14.1119 11.5123 14.3481 11.9887 14.4474C12.465 14.5468 12.9601 14.5049 13.413 14.3269L13.414 14.3279ZM21.307 16.5919L19.876 15.1619C20.5445 14.2092 21.0204 13.1351 21.277 11.9999C21.0052 10.8097 20.4943 9.68709 19.7751 8.70044C19.056 7.71379 18.1438 6.88367 17.0939 6.26055C16.044 5.63743 14.8783 5.23431 13.6677 5.07571C12.4572 4.9171 11.227 5.00632 10.052 5.33794L8.474 3.75994C9.721 3.26994 11.08 2.99994 12.5 2.99994C17.892 2.99994 22.378 6.87994 23.319 11.9999C23.0126 13.6656 22.3239 15.2375 21.307 16.5919ZM12.223 7.50794C12.8595 7.46861 13.4971 7.56501 14.0935 7.79076C14.69 8.01651 15.2316 8.36646 15.6825 8.81739C16.1335 9.26833 16.4834 9.80997 16.7092 10.4064C16.9349 11.0028 17.0313 11.6404 16.992 12.2769L12.222 7.50794H12.223Z"
fill="inherit"
/>
</svg>
</div>
<button type="submit" id="btn-login" class="btn btn-primary btn-block">
Set new password
</button>
<a href="https://app.maybe.co/login" class="btn btn-text btn-block"
>Back to login</a
>
</form>
</div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"
></script>
<script>
$('#toast-error').hide()
$('#toast-success').hide()
function toggleShowPassword(selector) {
const isPassword = $(selector).attr('type') === 'password'
$(selector).attr('type', isPassword ? 'text' : 'password')
}
$('#setPasswordIcon').on('click', () => {
toggleShowPassword('#newPassword')
})
$('#confirmPasswordIcon').on('click', () => {
toggleShowPassword('#confirmNewPassword')
})
var form = $('#change-password-form')
form.submit(function (e) {
e.preventDefault()
const pw1 = $('#newPassword').val()
const pw2 = $('#confirmNewPassword').val()
if (pw1 !== pw2) {
displayError('Passwords do not match')
} else if (pw1.length < 8) {
displayError('Password must be at least 8 characters')
} else {
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data: form.serialize(),
success: handleSuccess,
error: handleError,
})
}
})
var handleSuccess = function (res) {
setTimeout(() => {
switch (window.location.host) {
case 'maybe-finance-development.us.auth0.com':
window.location.href = 'http://localhost:4200'
break
case 'maybe-finance-staging.us.auth0.com':
window.location.href = 'https://staging-app.maybe.co'
break
case 'login.maybe.co':
window.location.href = 'https://app.maybe.co'
}
}, 3_000)
displaySuccess('Your password was reset. Redirecting to login...')
$('#btn-login').prop('disabled', true)
}
var handleError = function (res) {
let error =
'Something went wrong. You may need to request a new password reset link.'
if (!!res && res.responseJSON && res.responseJSON.message) {
error = res.responseJSON.message
}
displayError(error)
}
function displayError(err) {
$('#fail-message').text(err)
setTimeout(() => {
$('#toast-error').hide()
}, 8_000)
$('#toast-error').show()
}
function displaySuccess(message) {
$('#success-message').text(message)
setTimeout(() => {
$('#toast-success').hide()
}, 8_000)
$('#toast-success').show()
}
</script>
</body>
</html>

View file

@ -1,45 +0,0 @@
function assignRolesOnLogin(user, context, callback) {
// This rule does not apply to unverified users - never assign a privileged role without verification!
if (!user.email || !user.email_verified) {
return callback(null, user, context);
}
const maybeEmailDomain = 'maybe.co';
const emailSplit = user.email.split('@');
const isMaybeEmployee = emailSplit[emailSplit.length - 1].toLowerCase() === maybeEmailDomain;
if (!isMaybeEmployee) {
return callback(null, user, context);
}
// Use latest version that is allowed here - https://auth0-extensions.github.io/canirequire/#auth0
const ManagementClient = require('auth0@2.35.0').ManagementClient;
const cli = new ManagementClient({
token: auth0.accessToken,
domain: auth0.domain,
});
const admins = ['REPLACE_THIS'];
const rolesToAssign = [];
// https://auth0.com/docs/rules/configuration#use-the-configuration-object
if (admins.includes(user.email)) {
rolesToAssign.push(configuration.ADMIN_ROLE_ID);
}
// https://auth0.com/docs/rules/configuration#use-the-configuration-object
if (isMaybeEmployee) {
rolesToAssign.push(configuration.BETA_TESTER_ROLE_ID);
}
// If we make it here, we know the user has verified their email and their email is in the Maybe Finance Gmail domain
cli.assignRolestoUser({ id: user.user_id }, { roles: rolesToAssign }, function (err) {
if (err) {
console.log(err);
}
return callback(null, user, context);
});
}

View file

@ -1,53 +0,0 @@
function enhanceIdToken(user, context, callback) {
// Does not have to be a valid URL, just has to be unique and start with http / https
const namespace = 'https://maybe.co';
const assignedRoles = (context.authorization || {}).roles;
let idTokenClaims = context.idToken || {};
let accessTokenClaims = context.accessToken || {};
let identityClaim;
if (user.identities && user.identities.length) {
const primaryIdentities = user.identities.filter((identity) => {
// https://auth0.com/docs/manage-users/user-accounts/user-account-linking#how-it-works
const isSecondary = 'profileData' in identity;
return !isSecondary;
});
if (primaryIdentities.length === 0) {
identityClaim = undefined;
}
// Based on prior checks, this should represent the primary identity
const primaryIdentity = primaryIdentities[0];
identityClaim = {
connection: primaryIdentity.connection,
provider: primaryIdentity.provider,
isSocial: primaryIdentity.isSocial,
};
}
// Access token claims are populated on the parsed server-side JWT
accessTokenClaims[`${namespace}/name`] = user.name;
accessTokenClaims[`${namespace}/email`] = user.email;
accessTokenClaims[`${namespace}/picture`] = user.picture;
accessTokenClaims[`${namespace}/roles`] = assignedRoles;
accessTokenClaims[`${namespace}/user-metadata`] = user.user_metadata;
accessTokenClaims[`${namespace}/app-metadata`] = user.app_metadata;
accessTokenClaims[`${namespace}/primary-identity`] = identityClaim;
// ID token claims are populated in the parsed client-side React hook
idTokenClaims[`${namespace}/roles`] = assignedRoles;
idTokenClaims[`${namespace}/user-metadata`] = user.user_metadata;
idTokenClaims[`${namespace}/app-metadata`] = user.app_metadata;
idTokenClaims[`${namespace}/primary-identity`] = identityClaim;
context.idToken = idTokenClaims;
context.accessToken = accessTokenClaims;
return callback(null, user, context);
}

View file

@ -1,23 +0,0 @@
// https://auth0.com/docs/secure/multi-factor-authentication/customize-mfa
function mfaAuth(user, context, callback) {
const ENABLED_CLIENT_IDS = [
'REPLACE_THIS',
];
// Only enable MFA on the Next.js app (client IDs above)
if (ENABLED_CLIENT_IDS.indexOf(context.clientID) !== -1) {
// This makes MFA optional for users (they can enroll via their profile within the app)
if (user.user_metadata && user.user_metadata.enrolled_mfa) {
context.multifactor = {
// See options here - https://auth0.com/docs/secure/multi-factor-authentication/customize-mfa#use-rules
// `any` is the generic option (i.e. Google Authenticator or something similar)
provider: 'any',
// If set to true, MFA will turn off for 30 days for the user's current browser
allowRememberBrowser: true,
};
}
}
return callback(null, user, context);
}

View file

@ -1,27 +0,0 @@
function updateUserMetadata(user, context, callback) {
// Use latest version that is allowed here (2.4.0 as of today) - https://auth0-extensions.github.io/canirequire/#auth0
const ManagementClient = require('auth0@2.35.0').ManagementClient;
const cli = new ManagementClient({
token: auth0.accessToken,
domain: auth0.domain,
});
const metadata = {
firstName:
(user.user_metadata && user.user_metadata.firstName) ||
user.first_name ||
user.given_name ||
'',
lastName:
(user.user_metadata && user.user_metadata.lastName) ||
user.last_name ||
user.family_name ||
'',
};
// Maps data from various identity providers to a normalized identity
cli.updateUserMetadata({ id: user.user_id }, metadata, function (err, updatedUser) {
return callback(null, updatedUser, context);
});
}

View file

@ -1,34 +0,0 @@
// If the user successfully performs a password reset, we *know* their email is valid, so go ahead and verify it if not already verified
function verifyUserWithPasswordReset(user, context, callback) {
const request = require('request');
const userApiUrl = auth0.baseUrl + '/users/';
// This rule is only for Auth0 databases
if (context.connectionStrategy !== 'auth0') {
return callback(null, user, context);
}
if (user.email_verified || !user.last_password_reset) {
return callback(null, user, context);
}
// Set email verified if a user has already updated his/her password
request.patch(
{
url: userApiUrl + user.user_id,
headers: {
Authorization: 'Bearer ' + auth0.accessToken,
},
json: { email_verified: true },
timeout: 5000,
},
function (err, response, body) {
// Setting email verified isn't propagated to id_token in this
// authentication cycle so explicitly set it to true given no errors.
context.idToken.email_verified = !err && response.statusCode === 200;
// Return with success at this point.
return callback(null, user, context);
}
);
}

View file

@ -1,26 +0,0 @@
const { config, sync } = require('./config')
const firstArg = process.argv.slice(2)[0]
if (firstArg === '--force') {
sync({
config: {
...config,
// The deploy client only works with the DEFAULT Auth0 domain, NOT with custom domains
AUTH0_DOMAIN: config.AUTH0_KEYWORD_REPLACE_MAPPINGS.AUTH0_DOMAIN,
},
format: 'yaml',
output_folder: __dirname,
})
.then(() =>
console.log(
`Synced ${config.AUTH0_KEYWORD_REPLACE_MAPPINGS.AUTH0_DOMAIN} successfully!`
)
)
.catch((err) => console.log(`Sync failed: ${err}`))
} else {
console.log(
'Syncing not recommended (see README.md). Instead, you should make changes locally and deploy to the tenant. \n\nIf you are sure you want to do this, run: \n\n`node sync --force`\n'
)
}

View file

@ -1,360 +0,0 @@
rules:
- name: mfaAuth
script: ./rules/mfaAuth.js
stage: login_success
enabled: true
order: 1
- name: verifyUserOnPasswordReset
script: ./rules/verifyUserOnPasswordReset.js
stage: login_success
enabled: true
order: 2
- name: assignRolesOnLogin
script: ./rules/assignRolesOnLogin.js
stage: login_success
enabled: true
order: 3
- name: updateUserMetadata
script: ./rules/updateUserMetadata.js
stage: login_success
enabled: true
order: 4
- name: enhanceIdToken
script: ./rules/enhanceIdToken.js
stage: login_success
enabled: true
order: 5
rulesConfigs:
- key: "ADMIN_ROLE_ID"
value: '##ADMIN_ROLE_ID##'
- key: "BETA_TESTER_ROLE_ID"
value: '##BETA_TESTER_ROLE_ID##'
hooks: []
pages:
- name: guardian_multifactor
enabled: false
html: ./pages/guardian_multifactor.html
- name: login
enabled: true
html: ./pages/login.html
- name: password_reset
enabled: true
html: ./pages/password_reset.html
resourceServers:
- name: maybe-finance-api
identifier: https://maybe-finance-api/v1
allow_offline_access: true
signing_alg: RS256
skip_consent_for_verifiable_first_party_clients: true
token_lifetime: 86400 # 24 hours
token_lifetime_for_web: 7200
clients:
- name: Maybe
app_type: spa
allowed_clients: []
callbacks: @@CLIENT_BASE_URLS@@
allowed_logout_urls: @@CLIENT_LOGOUT_URLS@@
allowed_origins: @@CLIENT_BASE_URLS@@
web_origins: @@CLIENT_BASE_URLS@@
client_aliases: []
cross_origin_auth: false
custom_login_page_on: true
grant_types:
- authorization_code
- implicit
- refresh_token
- password
- http://auth0.com/oauth/grant-type/password-realm
is_first_party: true
is_token_endpoint_ip_header_trusted: false
jwt_configuration:
alg: RS256
lifetime_in_seconds: 36000
secret_encoded: false
native_social_login:
apple:
enabled: false
facebook:
enabled: false
oidc_conformant: true
refresh_token:
expiration_type: expiring
leeway: 0
token_lifetime: 2592000 # 30 days
idle_token_lifetime: 1296000 # 15 days
infinite_token_lifetime: false
infinite_idle_token_lifetime: false
rotation_type: rotating
sso_disabled: false
token_endpoint_auth_method: none
- name: Maybe Admin
allowed_clients: []
app_type: regular_web
callbacks: @@SERVER_CALLBACK_URLS@@
allowed_logout_urls: @@SERVER_BASE_URLS@@
allowed_origins: @@SERVER_BASE_URLS@@
web_origins: @@SERVER_BASE_URLS@@
client_aliases: []
cross_origin_auth: false
custom_login_page_on: true
grant_types:
- authorization_code
- implicit
- refresh_token
- client_credentials
- password
is_first_party: true
is_token_endpoint_ip_header_trusted: false
jwt_configuration:
alg: RS256
lifetime_in_seconds: 36000
secret_encoded: false
native_social_login:
apple:
enabled: false
facebook:
enabled: false
oidc_conformant: true
refresh_token:
expiration_type: non-expiring
leeway: 0
infinite_token_lifetime: true
infinite_idle_token_lifetime: true
token_lifetime: 31557600
idle_token_lifetime: 2592000
rotation_type: non-rotating
sso_disabled: false
token_endpoint_auth_method: client_secret_post
- name: auth0-deploy-cli-extension
app_type: non_interactive
cross_origin_auth: false
custom_login_page_on: true
grant_types:
- client_credentials
is_first_party: true
is_token_endpoint_ip_header_trusted: false
jwt_configuration:
alg: RS256
lifetime_in_seconds: 36000
secret_encoded: false
oidc_conformant: true
refresh_token:
expiration_type: non-expiring
leeway: 0
infinite_token_lifetime: true
infinite_idle_token_lifetime: true
token_lifetime: 31557600
idle_token_lifetime: 2592000
rotation_type: non-rotating
sso_disabled: false
token_endpoint_auth_method: client_secret_post
- name: server-m2m-cli
allowed_clients: []
allowed_origins: []
app_type: non_interactive
callbacks: []
client_aliases: []
cross_origin_auth: false
custom_login_page_on: true
grant_types:
- client_credentials
is_first_party: true
is_token_endpoint_ip_header_trusted: false
jwt_configuration:
alg: RS256
lifetime_in_seconds: 36000
secret_encoded: false
native_social_login:
apple:
enabled: false
facebook:
enabled: false
oidc_conformant: true
refresh_token:
expiration_type: non-expiring
leeway: 0
infinite_token_lifetime: true
infinite_idle_token_lifetime: true
token_lifetime: 31557600
idle_token_lifetime: 2592000
rotation_type: non-rotating
sso_disabled: false
token_endpoint_auth_method: client_secret_post
databases:
- name: Username-Password-Authentication
strategy: auth0
enabled_clients:
- auth0-deploy-cli-extension
- Maybe
- Maybe Admin
is_domain_connection: false
options:
mfa:
active: true
return_enroll_settings: true
passwordPolicy: good
strategy_version: 2
brute_force_protection: true
realms:
- Username-Password-Authentication
connections:
- name: google-oauth2
strategy: google-oauth2
enabled_clients:
- auth0-deploy-cli-extension
- Maybe
- Maybe Admin
- server-m2m-cli
is_domain_connection: false
options:
email: true
scope:
- email
- profile
profile: true
- name: apple
strategy: apple
enabled_clients:
- auth0-deploy-cli-extension
- Maybe
- Maybe Admin
- server-m2m-cli
is_domain_connection: false
options:
client_id: co.maybe.webapp
app_secret: @@APPLE_SIGN_IN_SECRET_KEY@@
team_id: 8TQ4KDWF2S
kid: 47WD7B27JK
email: true
name: true
scope:
- email
- name
tenant:
enabled_locales:
- en
# https://auth0.com/docs/authorization/flows/call-your-api-using-resource-owner-password-flow#configure-tenant
default_directory: Username-Password-Authentication
default_audience: https://maybe-finance-api/v1
flags:
new_universal_login_experience_enabled: true
universal_login: true
revoke_refresh_token_grant: false
disable_clickjack_protection_headers: false
friendly_name: Maybe Finance
picture_url: >-
https://assets.maybe.co/images/maybe.svg
universal_login:
colors:
page_background: '#242629'
primary: '#3bc9db'
support_email: hello@maybe.co
emailProvider:
name: smtp
credentials:
smtp_host: smtp.postmarkapp.com
smtp_port: 587
smtp_user: REPLACE_THIS
smtp_pass: '##POSTMARK_SMTP_PASS##'
default_from_address: account@maybe.co
enabled: true
emailTemplates:
- template: reset_email
body: ./emailTemplates/reset_email.html
enabled: true
from: reset@maybe.co
subject: Reset your password
syntax: liquid
urlLifetimeInSeconds: 86400
- template: verify_email
body: ./emailTemplates/verify_email.html
enabled: true
from: 'account@maybe.co'
resultUrl: '{{ application.callback_domain }}'
subject: 'Verify your email for Maybe Finance'
syntax: liquid
urlLifetimeInSeconds: 432000
clientGrants:
- client_id: server-m2m-cli
audience: https://##AUTH0_DOMAIN##/api/v2/
scope:
- read:users
- update:users
- delete:users
- read:users_app_metadata
- update:users_app_metadata
- delete:users_app_metadata
- create:users_app_metadata
guardianFactors:
- name: duo
enabled: false
- name: email
enabled: true
- name: otp
enabled: true
- name: push-notification
enabled: false
- name: recovery-code
enabled: true
- name: sms
enabled: false
- name: webauthn-platform
enabled: false
- name: webauthn-roaming
enabled: false
guardianFactorProviders: []
guardianFactorTemplates: []
guardianPolicies:
policies: []
guardianPhoneFactorSelectedProvider:
provider: auth0
guardianPhoneFactorMessageTypes:
message_types: []
roles:
- name: Admin
description: Maybe Employee Admin
permissions: []
- name: CIUser
description: Identifies our CI users for e2e testing
permissions: []
branding:
colors:
page_background: '#242629'
primary: '#3bc9db'
logo_url: >-
https://assets.maybe.co/images/maybe.svg
prompts:
universal_login_experience: new
identifier_first: false
migrations: {}
actions: []
triggers: {}
organizations: []