From df168e743fc1327b1beb12f0c308bd0ec6da8191 Mon Sep 17 00:00:00 2001 From: Bryan Robinson Date: Wed, 17 Dec 2025 15:52:02 -0500 Subject: [PATCH] Adds files and pointers --- kickstart/css/styles.css | 1868 ++++++++--------- kickstart/kickstart.json | 59 +- kickstart/templates/accountEdit.ftl | 83 + kickstart/templates/accountIndex.ftl | 54 + .../templates/accountTwoFactorDisable.ftl | 78 + .../templates/accountTwoFactorEnable.ftl | 155 ++ kickstart/templates/accountTwoFactorIndex.ftl | 71 + kickstart/templates/accountWebAuthnAdd.ftl | 71 + kickstart/templates/accountWebAuthnDelete.ftl | 61 + kickstart/templates/accountWebAuthnIndex.ftl | 85 + kickstart/templates/confirmationRequired.ftl | 48 + kickstart/templates/defaultMessages.txt | 707 +++++++ kickstart/templates/emailComplete.ftl | 27 + kickstart/templates/emailSend.ftl | 29 + kickstart/templates/emailSent.ftl | 29 + .../templates/emailVerificationRequired.ftl | 94 + kickstart/templates/emailVerify.ftl | 42 + kickstart/templates/helpers.ftl | 1344 ++++++++++++ kickstart/templates/index.ftl | 46 + kickstart/templates/oauth2Authorize.ftl | 122 ++ .../oauth2AuthorizedNotRegistered.ftl | 27 + .../oauth2ChildRegistrationNotAllowed.ftl | 38 + ...th2ChildRegistrationNotAllowedComplete.ftl | 27 + .../templates/oauth2CompleteRegistration.ftl | 109 + kickstart/templates/oauth2Consent.ftl | 56 + kickstart/templates/oauth2Device.ftl | 131 ++ kickstart/templates/oauth2DeviceComplete.ftl | 35 + kickstart/templates/oauth2Error.ftl | 33 + kickstart/templates/oauth2Logout.ftl | 46 + kickstart/templates/oauth2Passwordless.ftl | 56 + kickstart/templates/oauth2Register.ftl | 194 ++ kickstart/templates/oauth2StartIdPLink.ftl | 104 + kickstart/templates/oauth2TwoFactor.ftl | 73 + kickstart/templates/oauth2TwoFactorEnable.ftl | 124 ++ .../oauth2TwoFactorEnableComplete.ftl | 42 + .../templates/oauth2TwoFactorMethods.ftl | 100 + kickstart/templates/oauth2Wait.ftl | 30 + kickstart/templates/oauth2WebAuthn.ftl | 54 + kickstart/templates/oauth2WebAuthnReauth.ftl | 72 + .../templates/oauth2WebAuthnReauthEnable.ftl | 101 + kickstart/templates/passwordChange.ftl | 53 + kickstart/templates/passwordComplete.ftl | 28 + kickstart/templates/passwordForgot.ftl | 41 + kickstart/templates/passwordSent.ftl | 29 + kickstart/templates/phoneComplete.ftl | 27 + kickstart/templates/phoneSent.ftl | 28 + .../templates/phoneVerificationRequired.ftl | 91 + kickstart/templates/phoneVerify.ftl | 42 + kickstart/templates/registrationComplete.ftl | 27 + kickstart/templates/registrationSend.ftl | 29 + kickstart/templates/registrationSent.ftl | 29 + .../registrationVerificationRequired.ftl | 65 + kickstart/templates/registrationVerify.ftl | 42 + kickstart/templates/samlv2Logout.ftl | 51 + kickstart/templates/unauthorized.ftl | 40 + 55 files changed, 6211 insertions(+), 936 deletions(-) create mode 100644 kickstart/templates/accountEdit.ftl create mode 100644 kickstart/templates/accountIndex.ftl create mode 100644 kickstart/templates/accountTwoFactorDisable.ftl create mode 100644 kickstart/templates/accountTwoFactorEnable.ftl create mode 100644 kickstart/templates/accountTwoFactorIndex.ftl create mode 100644 kickstart/templates/accountWebAuthnAdd.ftl create mode 100644 kickstart/templates/accountWebAuthnDelete.ftl create mode 100644 kickstart/templates/accountWebAuthnIndex.ftl create mode 100644 kickstart/templates/confirmationRequired.ftl create mode 100644 kickstart/templates/defaultMessages.txt create mode 100644 kickstart/templates/emailComplete.ftl create mode 100644 kickstart/templates/emailSend.ftl create mode 100644 kickstart/templates/emailSent.ftl create mode 100644 kickstart/templates/emailVerificationRequired.ftl create mode 100644 kickstart/templates/emailVerify.ftl create mode 100644 kickstart/templates/helpers.ftl create mode 100644 kickstart/templates/index.ftl create mode 100644 kickstart/templates/oauth2Authorize.ftl create mode 100644 kickstart/templates/oauth2AuthorizedNotRegistered.ftl create mode 100644 kickstart/templates/oauth2ChildRegistrationNotAllowed.ftl create mode 100644 kickstart/templates/oauth2ChildRegistrationNotAllowedComplete.ftl create mode 100644 kickstart/templates/oauth2CompleteRegistration.ftl create mode 100644 kickstart/templates/oauth2Consent.ftl create mode 100644 kickstart/templates/oauth2Device.ftl create mode 100644 kickstart/templates/oauth2DeviceComplete.ftl create mode 100644 kickstart/templates/oauth2Error.ftl create mode 100644 kickstart/templates/oauth2Logout.ftl create mode 100644 kickstart/templates/oauth2Passwordless.ftl create mode 100644 kickstart/templates/oauth2Register.ftl create mode 100644 kickstart/templates/oauth2StartIdPLink.ftl create mode 100644 kickstart/templates/oauth2TwoFactor.ftl create mode 100644 kickstart/templates/oauth2TwoFactorEnable.ftl create mode 100644 kickstart/templates/oauth2TwoFactorEnableComplete.ftl create mode 100644 kickstart/templates/oauth2TwoFactorMethods.ftl create mode 100644 kickstart/templates/oauth2Wait.ftl create mode 100644 kickstart/templates/oauth2WebAuthn.ftl create mode 100644 kickstart/templates/oauth2WebAuthnReauth.ftl create mode 100644 kickstart/templates/oauth2WebAuthnReauthEnable.ftl create mode 100644 kickstart/templates/passwordChange.ftl create mode 100644 kickstart/templates/passwordComplete.ftl create mode 100644 kickstart/templates/passwordForgot.ftl create mode 100644 kickstart/templates/passwordSent.ftl create mode 100644 kickstart/templates/phoneComplete.ftl create mode 100644 kickstart/templates/phoneSent.ftl create mode 100644 kickstart/templates/phoneVerificationRequired.ftl create mode 100644 kickstart/templates/phoneVerify.ftl create mode 100644 kickstart/templates/registrationComplete.ftl create mode 100644 kickstart/templates/registrationSend.ftl create mode 100644 kickstart/templates/registrationSent.ftl create mode 100644 kickstart/templates/registrationVerificationRequired.ftl create mode 100644 kickstart/templates/registrationVerify.ftl create mode 100644 kickstart/templates/samlv2Logout.ftl create mode 100644 kickstart/templates/unauthorized.ftl diff --git a/kickstart/css/styles.css b/kickstart/css/styles.css index 4ba979e..7b028b9 100644 --- a/kickstart/css/styles.css +++ b/kickstart/css/styles.css @@ -1,444 +1,596 @@ :root { - --main-text-color: #424242; - --main-accent-color: #096324; - --input-background: #fbfbfb; - --body-background: #f7f7f7; - --tooltip-background: #e2e2e2; - --error-color: #ff0000; - --error-background: #ffe8e8; - --border-color: #dddddd; - --logo-url: url(https://fusionauth.io/cdn/samplethemes/changebank/changebank.svg); - --font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - } - body { - font-family: var(--font-stack); - font-size: 16px; - color: var(--main-text-color); - background: var(--body-background); - line-height: normal; - } - .page-body:before { - content: ''; - display: block; - width: 80%; - max-width: 20rem; - height: 3.5rem; - margin: 0 auto 3rem auto; - background-image: var(--logo-url); - background-size: contain; - background-position: center; - background-repeat: no-repeat; - } - - /* Changes for Powered by FusionAuth div */ - body > main main.page-body { - min-height: calc(100vh - 3rem); /* to make the Powered by FusionAuth div position at the bottom of the page if the page is shorter than the viewport */ - padding-top: 3rem; - } - body > main { - padding-bottom: 2.5rem; /* giving Powered by FusionAuth more space */ - } - #powered-by-fa { - position: absolute !important; - } - /* End Powered by FusionAuth */ - - - /* Hiding help bar at top */ - body > main { - padding-top: 0; - } - /* end help bar */ - - - /* Typical typography */ - h1, h2, h3, h4, h5, h6 { - line-height: normal; - } - p { - margin: 1.5em 0; - line-height: 1.375; - } - /* End typography */ - - - /* Typical Buttons and Links */ - a { - color: var(--main-accent-color); - text-decoration: underline; - } - a:hover { - color: var(--main-accent-color); - opacity: .8; - } - a:visited { - color: var(--main-accent-color); - } - .blue-text { - color: var(--main-accent-color) !important; - } - .form-row:last-of-type { - margin-bottom: 0; - } - .button { - font-size: 1.125rem !important; - border-radius: .5rem; - padding: 1rem !important; - line-height: normal !important; - letter-spacing: normal !important; - } - .button.blue { - background: var(--main-accent-color) !important; - width: 100%; - margin-top: 2.5rem; - } - .button.blue:hover { - opacity: .8 !important; - background: var(--main-accent-color) !important; - } - .button.blue:focus { - background: var(--main-accent-color) !important; - box-shadow: inset 0 1px 2px rgba(0,0,0,0.4),0 0 0 2px rgba(57,152,219,0.4); - outline: 1px solid #ffffff !important; - } - .button.blue > .fa { - display: none; - } - .secondary-btn, - main.page-body .row:last-of-type a { - text-decoration: none; - padding: .5em .75em; - border: 1px solid var(--main-accent-color); - border-radius: .25em; - font-size: .75rem; - margin-top: .7rem; - display: inline-block; - line-height: normal; - } - .button + a { - text-align: center; - display: block; - margin: 1em auto; - } - /* End buttons and links */ - - - /* Typical Form panel and inputs */ - .panel { - box-shadow: 0 0 1.5625rem 1.25rem rgba(234, 234, 234, 0.8); - border-radius: .625rem; - border: none; - padding: 2.25rem 2.75rem; - } - .panel h2, - fieldset legend, - legend { - text-align: center; - color: var(--main-accent-color); - font-size: 1.5625rem; - font-weight: 600; - margin: 0 0 2rem 0; - padding: 0; - border: none; - } - legend { - border: none; - width: auto; - } - form .form-row { - margin-bottom: 1.25rem; - } - label { - color: var(--main-text-color); - font-size: 1rem; - font-weight: 500; - } - label.radio, - label.checkbox { - margin: 1rem 0; - font-weight: 400; - } - .input-addon-group, - .input-addon-group > :last-child:not(.flat), - .input-addon-group > .input:last-child:not(.flat), - .input-addon-group > input:last-child:not(.flat) { - color: var(--main-text-color); /* overriding typical text color for inputs */ - } - .input-addon-group span { - display: none; /* Hiding icons on inputs */ - } - input::placeholder { - color: var(--main-text-color); - } - .input, - input[type="email"], - input[type="file"], - input[type="number"], - input[type="search"], - input[type="text"], - input[type="tel"], - input[type="url"], - input[type="password"], - textarea, - label.select select - { - background: var(--input-background); - border: 1px solid var(--border-color) !important; - border-radius: .25rem !important; - box-shadow: none; - font-size: 1rem; - padding: 1em .625em; - } - input:focus, - input:active, - textarea:focus, - textarea:active { - border: 1px solid #707070 !important; - box-shadow: none !important; - } - .radio input { - width: 1.3125rem; - height: 1.3125rem; - } - .radio span.box, - .checkbox span.box { - width: 1.3125rem; - height: 1.3125rem; - margin: 0; - border: solid 1px var(--border-color); - background-color: var(--input-background); - } - .radio span.box { - border-radius: 50%; - } - .radio input:checked + span.box { - border: 2px solid var(--main-accent-color); - } - .radio span.box::after { - box-shadow: none; - border-radius: 50%; - background: var(--main-accent-color); - width: .8125rem; - height: .8125rem; - top: .125rem; - left: .125rem; - } - .radio span.box:hover::after { - opacity: 0; - } - .radio span.label, - .checkbox span.label { - margin-left: .5rem; - } - .radio-items .form-row label span:last-of-type { - border-color: var(--border-color); - } - input[type="radio"] { - width: 1.3125rem; - height: 1.3125rem; - margin: 0; - border: solid 1px var(--border-color); - border-radius: 50%; - background-color: var(--input-background); - appearance: none; - -webkit-appearance: none; - vertical-align: text-bottom; - } - input[type="radio"]:focus, - input[type="radio"]:active, - input[type="radio"]:checked { - border: 2px solid var(--main-accent-color) !important; - } - input[type="radio"]:checked:after { - content: ''; - box-shadow: none; - border-radius: 50%; - background: var(--main-accent-color); - width: .8125rem; - height: .8125rem; - top: .125rem; - left: .125rem; - position: absolute; - } - .checkbox span.box { - border-radius: .25rem; - } - .checkbox input:checked + span.box { - background: var(--main-accent-color); - border-color: var(--main-accent-color); - } - .checkbox span.box::after { - height: .25rem; - left: .25rem; - top: .3125rem; - transform: rotate(-46deg); - width: .625rem; - box-shadow: none; - } - .checkbox-list { - background: transparent; - border: none; - box-shadow: none; - padding-left: 0; - } - input[type="checkbox"] { - width: 1.3125rem; - height: 1.3125rem; - margin: 0; - border: solid 1px var(--border-color); - border-radius: .25rem; - background-color: var(--input-background); - appearance: none; - -webkit-appearance: none; - vertical-align: text-bottom; - } - input[type="checkbox"]:checked { - background-color: var(--main-accent-color); - } - input[type="checkbox"]:checked:after { - content: ''; - background: transparent; - border: 2px solid #fff; - border-right: none; - border-top: none; - height: .25rem; - left: .25rem; - top: .3125rem; - transform: rotate(-46deg); - width: .625 rem; - display: block; - position: absolute; - } - label.select select { - color: var(--main-text-color); - } - label.select select option { - background: var(--input-background); - color: var(--main-text-color); - } - /* End Panel and Form Inputs */ - - - /* Errors */ - body .alert { - color: var(--main-text-color); - } - body .alert a { - height: auto; - width: auto; - } - body .alert.error a i.fa { - color: var(--error-color); - } - body .alert.error { - border: 1px solid var(--error-color); - margin: 0 0 2rem 0; - background: var(--error-background); - box-shadow: none; - border-radius: .25rem; - } - body .alert .dismiss-button i { - margin: 0; - } - .error { - font-size: .75rem; - margin: .5em 0; - } - label.error { - color: var(--error-color); - font-size: inherit; - } - form .form-row span.error { - color: var(--error-color); - } - input.error { - background: var(--error-background); - border-color: var(--error-color) !important; - } - /* End Errors */ - - - /* Tooltip */ - .tooltip { - background: var(--tooltip-background); - font-size: .75rem; - color: var(--main-text-color); - text-align: left; - } - .tooltip:after { - border-top-color: var(--tooltip-background); - } - .tooltip.inverted:before { - border-bottom-color: var(--tooltip-background); - } - .fa-info-circle { - color: var(--main-accent-color) !important; - } - /* End Tooltip */ - - - table thead tr th { - color: var(--main-text-color); - } - table thead tr { - border-color: var(--border-color); - } - #locale-select { - width: 50%; - min-width: 10rem; - } - .grecaptcha-msg { - margin: 1rem 0; - text-align: left; - } - .progress-bar { - border-radius: .5rem; - border: 1px solid var(--border-color); - height: 1rem; - } - .progress-bar div { - border-radius: .5rem; - background: var(--main-accent-color); - height: 1rem; - } - hr, - .hr-container hr { - border: none; - height: 1px; - background-color: #979797; - } - .hr-container div { - color: #959595; - font-size: .75rem; - } + --main-text-color: #424242; + --main-accent-color: #096324; + --input-background: #fbfbfb; + --body-background: #f7f7f7; + --tooltip-background: #e2e2e2; + --error-color: #ff0000; + --error-background: #ffe8e8; + --border-color: #dddddd; + --logo-url: url(https://fusionauth.io/cdn/samplethemes/changebank/changebank.svg); + --font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; +} +body { + font-family: var(--font-stack); + font-size: 16px; + color: var(--main-text-color); + background: var(--body-background); + line-height: normal; +} +.page-body:before { + content: ''; + display: block; + width: 80%; + max-width: 20rem; + height: 3.5rem; + margin: 0 auto 3rem auto; + background-image: var(--logo-url); + background-size: contain; + background-position: center; + background-repeat: no-repeat; +} + +/* Changes for Powered by FusionAuth div */ +body > main main.page-body { + min-height: calc(100vh - 3rem); /* to make the Powered by FusionAuth div position at the bottom of the page if the page is shorter than the viewport */ + padding-top: 3rem; +} +body > main { + padding-bottom: 2.5rem; /* giving Powered by FusionAuth more space */ +} +#powered-by-fa { + position: absolute !important; +} +/* End Powered by FusionAuth */ + + +/* Hiding help bar at top */ +body > main { + padding-top: 0; +} +/* end help bar */ + + +/* Typical typography */ +h1, h2, h3, h4, h5, h6 { + line-height: normal; +} +p { + margin: 1.5em 0; + line-height: 1.375; +} +/* End typography */ + + +/* Typical Buttons and Links */ +a { + color: var(--main-accent-color); + text-decoration: underline; +} +a:hover { + color: var(--main-accent-color); + opacity: .8; +} +a:visited { + color: var(--main-accent-color); +} +.blue-text { + color: var(--main-accent-color) !important; +} +.form-row:last-of-type { + margin-bottom: 0; +} +.button { + font-size: 1.125rem !important; + border-radius: .5rem; + padding: 1rem !important; + line-height: normal !important; + letter-spacing: normal !important; +} +.button.blue { + background: var(--main-accent-color) !important; + width: 100%; + margin-top: 2.5rem; +} +.button.blue:hover { + opacity: .8 !important; + background: var(--main-accent-color) !important; +} +.button.blue:focus { + background: var(--main-accent-color) !important; + box-shadow: inset 0 1px 2px rgba(0,0,0,0.4),0 0 0 2px rgba(57,152,219,0.4); + outline: 1px solid #ffffff !important; +} +.button.blue > .fa { + display: none; +} +.secondary-btn, +main.page-body .row:last-of-type a { + text-decoration: none; + padding: .5em .75em; + border: 1px solid var(--main-accent-color); + border-radius: .25em; + font-size: .75rem; + margin-top: .7rem; + display: inline-block; + line-height: normal; +} +.button + a { + text-align: center; + display: block; + margin: 1em auto; +} +/* End buttons and links */ + + +/* Typical Form panel and inputs */ +.panel { + box-shadow: 0 0 1.5625rem 1.25rem rgba(234, 234, 234, 0.8); + border-radius: .625rem; + border: none; + padding: 2.25rem 2.75rem; +} +.panel h2, +fieldset legend, +legend { + text-align: center; + color: var(--main-accent-color); + font-size: 1.5625rem; + font-weight: 600; + margin: 0 0 2rem 0; + padding: 0; + border: none; +} +legend { + border: none; + width: auto; +} +form .form-row { + margin-bottom: 1.25rem; +} +label { + color: var(--main-text-color); + font-size: 1rem; + font-weight: 500; +} +label.radio, +label.checkbox { + margin: 1rem 0; + font-weight: 400; +} +.input-addon-group, +.input-addon-group > :last-child:not(.flat), +.input-addon-group > .input:last-child:not(.flat), +.input-addon-group > input:last-child:not(.flat) { + color: var(--main-text-color); /* overriding typical text color for inputs */ +} +.input-addon-group span { + display: none; /* Hiding icons on inputs */ +} +input::placeholder { + color: var(--main-text-color); +} +.input, +input[type="email"], +input[type="file"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +label.select select +{ + background: var(--input-background); + border: 1px solid var(--border-color) !important; + border-radius: .25rem !important; + box-shadow: none; + font-size: 1rem; + padding: 1em .625em; +} +input:focus, +input:active, +textarea:focus, +textarea:active { + border: 1px solid #707070 !important; + box-shadow: none !important; +} +.radio input { + width: 1.3125rem; + height: 1.3125rem; +} +.radio span.box, +.checkbox span.box { + width: 1.3125rem; + height: 1.3125rem; + margin: 0; + border: solid 1px var(--border-color); + background-color: var(--input-background); +} +.radio span.box { + border-radius: 50%; +} +.radio input:checked + span.box { + border: 2px solid var(--main-accent-color); +} +.radio span.box::after { + box-shadow: none; + border-radius: 50%; + background: var(--main-accent-color); + width: .8125rem; + height: .8125rem; + top: .125rem; + left: .125rem; +} +.radio span.box:hover::after { + opacity: 0; +} +.radio span.label, +.checkbox span.label { + margin-left: .5rem; +} +.radio-items .form-row label span:last-of-type { + border-color: var(--border-color); +} +input[type="radio"] { + width: 1.3125rem; + height: 1.3125rem; + margin: 0; + border: solid 1px var(--border-color); + border-radius: 50%; + background-color: var(--input-background); + appearance: none; + -webkit-appearance: none; + vertical-align: text-bottom; +} +input[type="radio"]:focus, +input[type="radio"]:active, +input[type="radio"]:checked { + border: 2px solid var(--main-accent-color) !important; +} +input[type="radio"]:checked:after { + content: ''; + box-shadow: none; + border-radius: 50%; + background: var(--main-accent-color); + width: .8125rem; + height: .8125rem; + top: .125rem; + left: .125rem; + position: absolute; +} +.checkbox span.box { + border-radius: .25rem; +} +.checkbox input:checked + span.box { + background: var(--main-accent-color); + border-color: var(--main-accent-color); +} +.checkbox span.box::after { + height: .25rem; + left: .25rem; + top: .3125rem; + transform: rotate(-46deg); + width: .625rem; + box-shadow: none; +} +.checkbox-list { + background: transparent; + border: none; + box-shadow: none; + padding-left: 0; +} +input[type="checkbox"] { + width: 1.3125rem; + height: 1.3125rem; + margin: 0; + border: solid 1px var(--border-color); + border-radius: .25rem; + background-color: var(--input-background); + appearance: none; + -webkit-appearance: none; + vertical-align: text-bottom; +} +input[type="checkbox"]:checked { + background-color: var(--main-accent-color); +} +input[type="checkbox"]:checked:after { + content: ''; + background: transparent; + border: 2px solid #fff; + border-right: none; + border-top: none; + height: .25rem; + left: .25rem; + top: .3125rem; + transform: rotate(-46deg); + width: .625 rem; + display: block; + position: absolute; +} +label.select select { + color: var(--main-text-color); +} +label.select select option { + background: var(--input-background); + color: var(--main-text-color); +} +/* End Panel and Form Inputs */ + + +/* Errors */ +body .alert { + color: var(--main-text-color); +} +body .alert a { + height: auto; + width: auto; +} +body .alert.error a i.fa { + color: var(--error-color); +} +body .alert.error { + border: 1px solid var(--error-color); + margin: 0 0 2rem 0; + background: var(--error-background); + box-shadow: none; + border-radius: .25rem; +} +body .alert .dismiss-button i { + margin: 0; +} +.error { + font-size: .75rem; + margin: .5em 0; +} +label.error { + color: var(--error-color); + font-size: inherit; +} +form .form-row span.error { + color: var(--error-color); +} +input.error { + background: var(--error-background); + border-color: var(--error-color) !important; +} +/* End Errors */ + + +/* Tooltip */ +.tooltip { + background: var(--tooltip-background); + font-size: .75rem; + color: var(--main-text-color); + text-align: left; +} +.tooltip:after { + border-top-color: var(--tooltip-background); +} +.tooltip.inverted:before { + border-bottom-color: var(--tooltip-background); +} +.fa-info-circle { + color: var(--main-accent-color) !important; +} +/* End Tooltip */ + + +table thead tr th { + color: var(--main-text-color); +} +table thead tr { + border-color: var(--border-color); +} +#locale-select { + width: 50%; + min-width: 10rem; +} +.grecaptcha-msg { + margin: 1rem 0; + text-align: left; +} +.progress-bar { + border-radius: .5rem; + border: 1px solid var(--border-color); + height: 1rem; +} +.progress-bar div { + border-radius: .5rem; + background: var(--main-accent-color); + height: 1rem; +} +hr, +.hr-container hr { + border: none; + height: 1px; + background-color: #979797; +} +.hr-container div { + color: #959595; + font-size: .75rem; +} +.page-body > .row.center:last-of-type { + width: calc(100% - 30px); + margin: auto; + justify-content: space-between; +} +.page-body > .row.center:last-of-type > div { + width: 50%; + margin: 0; +} +@media only screen and (max-width: 450px) { .page-body > .row.center:last-of-type { - width: calc(100% - 30px); - margin: auto; - justify-content: space-between; - } - .page-body > .row.center:last-of-type > div { - width: 50%; - margin: 0; + flex-direction: column-reverse; + align-items: center; } - @media only screen and (max-width: 450px) { - .page-body > .row.center:last-of-type { - flex-direction: column-reverse; - align-items: center; - } - .secondary-btn, main.page-body .row:last-of-type a { - margin-bottom: 1rem; - } - .page-body > .row.center:last-of-type > div { - text-align: center !important; - } + .secondary-btn, main.page-body .row:last-of-type a { + margin-bottom: 1rem; } - @media only screen and (min-width: 768px) { - .page-body > .row.center:last-of-type { - width: 33rem; - } + .page-body > .row.center:last-of-type > div { + text-align: center !important; } - - /* Overriding existing grid per page */ +} +@media only screen and (min-width: 768px) { + .page-body > .row.center:last-of-type { + width: 33rem; + } +} + +/* Overriding existing grid per page */ +#oauth-register .page-body > .row > .col-xs, +#oauth-register .page-body > .row > .col-sm-8, +#oauth-register .page-body > .row > .col-md-6, +#oauth-register .page-body > .row > .col-lg-5, +#oauth-register .page-body > .row > .col-xl-4, +#oauth-authorize .page-body > .row > .col-xs, +#oauth-authorize .page-body > .row > .col-sm-8, +#oauth-authorize .page-body > .row > .col-md-6, +#oauth-authorize .page-body > .row > .col-lg-5, +#oauth-authorize .page-body > .row > .col-xl-4, +#oauth-passwordless .page-body > .row > .col-xs, +#oauth-passwordless .page-body > .row > .col-sm-8, +#oauth-passwordless .page-body > .row > .col-md-6, +#oauth-passwordless .page-body > .row > .col-lg-5, +#oauth-passwordless .page-body > .row > .col-xl-4, +#oauth-two-factor .page-body > .row > .col-xs, +#oauth-two-factor .page-body > .row > .col-sm-8, +#oauth-two-factor .page-body > .row > .col-md-6, +#oauth-two-factor .page-body > .row > .col-lg-5, +#oauth-two-factor .page-body > .row > .col-xl-4, +#oauth-two-factor-methods .page-body > .row > .col-xs, +#oauth-two-factor-methods .page-body > .row > .col-sm-8, +#oauth-two-factor-methods .page-body > .row > .col-md-6, +#oauth-two-factor-methods .page-body > .row > .col-lg-5, +#oauth-two-factor-methods .page-body > .row > .col-xl-4, +#oauth-logout .page-body > .row > .col-xs, +#oauth-logout .page-body > .row > .col-sm-8, +#oauth-logout .page-body > .row > .col-md-6, +#oauth-logout .page-body > .row > .col-lg-5, +#oauth-logout .page-body > .row > .col-xl-4, +#oauth-device .page-body > .row > .col-xs, +#oauth-device .page-body > .row > .col-sm-8, +#oauth-device .page-body > .row > .col-md-6, +#oauth-device .page-body > .row > .col-lg-5, +#oauth-device .page-body > .row > .col-xl-4, +#oauth-device-complete .page-body > .row > .col-xs, +#oauth-device-complete .page-body > .row > .col-sm-8, +#oauth-device-complete .page-body > .row > .col-md-6, +#oauth-device-complete .page-body > .row > .col-lg-5, +#oauth-device-complete .page-body > .row > .col-xl-4, +#oauth-complete-reg .page-body > .row > .col-xs, +#oauth-complete-reg .page-body > .row > .col-sm-8, +#oauth-complete-reg .page-body > .row > .col-md-6, +#oauth-complete-reg .page-body > .row > .col-lg-5, +#oauth-complete-reg .page-body > .row > .col-xl-4, +#oauth-child-reg .page-body > .row > .col-xs, +#oauth-child-reg .page-body > .row > .col-sm-8, +#oauth-child-reg .page-body > .row > .col-md-6, +#oauth-child-reg .page-body > .row > .col-lg-5, +#oauth-child-reg .page-body > .row > .col-xl-4, +#oauth-child-reg-complete .page-body > .row > .col-xs, +#oauth-child-reg-complete .page-body > .row > .col-sm-8, +#oauth-child-reg-complete .page-body > .row > .col-md-6, +#oauth-child-reg-complete .page-body > .row > .col-lg-5, +#oauth-child-reg-complete .page-body > .row > .col-xl-4, +#oauth-not-registered .page-body > .row > .col-xs, +#oauth-not-registered .page-body > .row > .col-sm-8, +#oauth-not-registered .page-body > .row > .col-md-6, +#oauth-not-registered .page-body > .row > .col-lg-5, +#oauth-not-registered .page-body > .row > .col-xl-4, +#oauth-error .page-body > .row > .col-xs, +#oauth-error .page-body > .row > .col-sm-8, +#oauth-error .page-body > .row > .col-md-6, +#oauth-error .page-body > .row > .col-lg-5, +#oauth-error .page-body > .row > .col-xl-4, +#oauthstart-idp-link .page-body > .row > .col-xs, +#oauthstart-idp-link .page-body > .row > .col-sm-8, +#oauthstart-idp-link .page-body > .row > .col-md-6, +#oauthstart-idp-link .page-body > .row > .col-lg-5, +#oauthstart-idp-link .page-body > .row > .col-xl-4, +#oauth-wait .page-body > .row > .col-xs, +#oauth-wait .page-body > .row > .col-sm-8, +#oauth-wait .page-body > .row > .col-md-6, +#oauth-wait .page-body > .row > .col-lg-5, +#oauth-wait .page-body > .row > .col-xl-4, +#email-verification .page-body > .row > .col-xs, +#email-verification .page-body > .row > .col-sm-8, +#email-verification .page-body > .row > .col-md-6, +#email-verification .page-body > .row > .col-lg-5, +#email-verification .page-body > .row > .col-xl-4, +#email-ver-required .page-body > .row > .col-xs, +#email-ver-required .page-body > .row > .col-sm-8, +#email-ver-required .page-body > .row > .col-md-6, +#email-ver-required .page-body > .row > .col-lg-5, +#email-ver-required .page-body > .row > .col-xl-4, +#email-ver-complete .page-body > .row > .col-xs, +#email-ver-complete .page-body > .row > .col-sm-8, +#email-ver-complete .page-body > .row > .col-md-6, +#email-ver-complete .page-body > .row > .col-lg-5, +#email-ver-complete .page-body > .row > .col-xl-4, +#email-ver-resent .page-body > .row > .col-xs, +#email-ver-resent .page-body > .row > .col-sm-8, +#email-ver-resent .page-body > .row > .col-md-6, +#email-ver-resent .page-body > .row > .col-lg-5, +#email-ver-resent .page-body > .row > .col-xl-4, +#forgot-pwd .page-body > .row > .col-xs, +#forgot-pwd .page-body > .row > .col-sm-8, +#forgot-pwd .page-body > .row > .col-md-6, +#forgot-pwd .page-body > .row > .col-lg-5, +#forgot-pwd .page-body > .row > .col-xl-4, +#forgot-pwd-sent .page-body > .row > .col-xs, +#forgot-pwd-sent .page-body > .row > .col-sm-8, +#forgot-pwd-sent .page-body > .row > .col-md-6, +#forgot-pwd-sent .page-body > .row > .col-lg-5, +#forgot-pwd-sent .page-body > .row > .col-xl-4, +#verify-reg .page-body > .row > .col-xs, +#verify-reg .page-body > .row > .col-sm-8, +#verify-reg .page-body > .row > .col-md-6, +#verify-reg .page-body > .row > .col-lg-5, +#verify-reg .page-body > .row > .col-xl-4, +#verify-reg-complete .page-body > .row > .col-xs, +#verify-reg-complete .page-body > .row > .col-sm-8, +#verify-reg-complete .page-body > .row > .col-md-6, +#verify-reg-complete .page-body > .row > .col-lg-5, +#verify-reg-complete .page-body > .row > .col-xl-4, +#verify-reg-resent .page-body > .row > .col-xs, +#verify-reg-resent .page-body > .row > .col-sm-8, +#verify-reg-resent .page-body > .row > .col-md-6, +#verify-reg-resent .page-body > .row > .col-lg-5, +#verify-reg-resent .page-body > .row > .col-xl-4, +#verify-reg-required .page-body > .row > .col-xs, +#verify-reg-required .page-body > .row > .col-sm-8, +#verify-reg-required .page-body > .row > .col-md-6, +#verify-reg-required .page-body > .row > .col-lg-5, +#verify-reg-required .page-body > .row > .col-xl-4, +#acct-2fa-enable .page-body > .row > .col-xs-12, +#acct-2fa-enable .page-body > .row > .col-sm-12, +#acct-2fa-enable .page-body > .row > .col-md-10, +#acct-2fa-enable .page-body > .row > .col-lg-8, +#acct-2fa-disable .page-body > .row > .col-xs-12, +#acct-2fa-disable .page-body > .row > .col-sm-12, +#acct-2fa-disable .page-body > .row > .col-md-10, +#acct-2fa-disable .page-body > .row > .col-lg-8, +#unauthorized-page .page-body > .row > .col-sm-10, +#unauthorized-page .page-body > .row > .col-md-8, +#unauthorized-page .page-body > .row > .col-lg-7, +#unauthorized-page .page-body > .row > .col-xl-5, +#change-pwd .page-body > .row > .col-xs, +#change-pwd .page-body > .row > .col-sm-8, +#change-pwd .page-body > .row > .col-md-6, +#change-pwd .page-body > .row > .col-lg-5, +#change-pwd .page-body > .row > .col-xl-4, +#change-pwd-complete .page-body > .row > .col-xs, +#change-pwd-complete .page-body > .row > .col-sm-8, +#change-pwd-complete .page-body > .row > .col-md-6, +#change-pwd-complete .page-body > .row > .col-lg-5, +#change-pwd-complete .page-body > .row > .col-xl-4 { + flex-basis: 33rem; + width: calc(100% - 30px); + max-width: 33rem; +} +@media only screen and (max-width: 575px) { #oauth-register .page-body > .row > .col-xs, #oauth-register .page-body > .row > .col-sm-8, #oauth-register .page-body > .row > .col-md-6, @@ -483,7 +635,7 @@ #oauth-complete-reg .page-body > .row > .col-sm-8, #oauth-complete-reg .page-body > .row > .col-md-6, #oauth-complete-reg .page-body > .row > .col-lg-5, - #oauth-complete-reg .page-body > .row > .col-xl-4, + #oauth-complete-reg .page-body > .row > .col-xl-4, #oauth-child-reg .page-body > .row > .col-xs, #oauth-child-reg .page-body > .row > .col-sm-8, #oauth-child-reg .page-body > .row > .col-md-6, @@ -493,47 +645,47 @@ #oauth-child-reg-complete .page-body > .row > .col-sm-8, #oauth-child-reg-complete .page-body > .row > .col-md-6, #oauth-child-reg-complete .page-body > .row > .col-lg-5, - #oauth-child-reg-complete .page-body > .row > .col-xl-4, + #oauth-child-reg-complete .page-body > .row > .col-xl-4, #oauth-not-registered .page-body > .row > .col-xs, #oauth-not-registered .page-body > .row > .col-sm-8, #oauth-not-registered .page-body > .row > .col-md-6, #oauth-not-registered .page-body > .row > .col-lg-5, - #oauth-not-registered .page-body > .row > .col-xl-4, + #oauth-not-registered .page-body > .row > .col-xl-4, #oauth-error .page-body > .row > .col-xs, #oauth-error .page-body > .row > .col-sm-8, #oauth-error .page-body > .row > .col-md-6, #oauth-error .page-body > .row > .col-lg-5, - #oauth-error .page-body > .row > .col-xl-4, + #oauth-error .page-body > .row > .col-xl-4, #oauthstart-idp-link .page-body > .row > .col-xs, #oauthstart-idp-link .page-body > .row > .col-sm-8, #oauthstart-idp-link .page-body > .row > .col-md-6, #oauthstart-idp-link .page-body > .row > .col-lg-5, - #oauthstart-idp-link .page-body > .row > .col-xl-4, + #oauthstart-idp-link .page-body > .row > .col-xl-4, #oauth-wait .page-body > .row > .col-xs, #oauth-wait .page-body > .row > .col-sm-8, #oauth-wait .page-body > .row > .col-md-6, #oauth-wait .page-body > .row > .col-lg-5, - #oauth-wait .page-body > .row > .col-xl-4, + #oauth-wait .page-body > .row > .col-xl-4, #email-verification .page-body > .row > .col-xs, #email-verification .page-body > .row > .col-sm-8, #email-verification .page-body > .row > .col-md-6, #email-verification .page-body > .row > .col-lg-5, - #email-verification .page-body > .row > .col-xl-4, + #email-verification .page-body > .row > .col-xl-4, #email-ver-required .page-body > .row > .col-xs, #email-ver-required .page-body > .row > .col-sm-8, #email-ver-required .page-body > .row > .col-md-6, #email-ver-required .page-body > .row > .col-lg-5, - #email-ver-required .page-body > .row > .col-xl-4, + #email-ver-required .page-body > .row > .col-xl-4, #email-ver-complete .page-body > .row > .col-xs, #email-ver-complete .page-body > .row > .col-sm-8, #email-ver-complete .page-body > .row > .col-md-6, #email-ver-complete .page-body > .row > .col-lg-5, - #email-ver-complete .page-body > .row > .col-xl-4, + #email-ver-complete .page-body > .row > .col-xl-4, #email-ver-resent .page-body > .row > .col-xs, #email-ver-resent .page-body > .row > .col-sm-8, #email-ver-resent .page-body > .row > .col-md-6, #email-ver-resent .page-body > .row > .col-lg-5, - #email-ver-resent .page-body > .row > .col-xl-4, + #email-ver-resent .page-body > .row > .col-xl-4, #forgot-pwd .page-body > .row > .col-xs, #forgot-pwd .page-body > .row > .col-sm-8, #forgot-pwd .page-body > .row > .col-md-6, @@ -567,7 +719,7 @@ #acct-2fa-enable .page-body > .row > .col-xs-12, #acct-2fa-enable .page-body > .row > .col-sm-12, #acct-2fa-enable .page-body > .row > .col-md-10, - #acct-2fa-enable .page-body > .row > .col-lg-8, + #acct-2fa-enable .page-body > .row > .col-lg-8, #acct-2fa-disable .page-body > .row > .col-xs-12, #acct-2fa-disable .page-body > .row > .col-sm-12, #acct-2fa-disable .page-body > .row > .col-md-10, @@ -578,525 +730,373 @@ #unauthorized-page .page-body > .row > .col-xl-5, #change-pwd .page-body > .row > .col-xs, #change-pwd .page-body > .row > .col-sm-8, - #change-pwd .page-body > .row > .col-md-6, + #change-pwd .page-body > .row > .col-md-6, #change-pwd .page-body > .row > .col-lg-5, #change-pwd .page-body > .row > .col-xl-4, #change-pwd-complete .page-body > .row > .col-xs, #change-pwd-complete .page-body > .row > .col-sm-8, - #change-pwd-complete .page-body > .row > .col-md-6, + #change-pwd-complete .page-body > .row > .col-md-6, #change-pwd-complete .page-body > .row > .col-lg-5, - #change-pwd-complete .page-body > .row > .col-xl-4 { - flex-basis: 33rem; + #change-pwd-complete .page-body > .row > .col-xl-4 { + flex-basis: calc(100% - 30px); width: calc(100% - 30px); max-width: 33rem; } - @media only screen and (max-width: 575px) { - #oauth-register .page-body > .row > .col-xs, - #oauth-register .page-body > .row > .col-sm-8, - #oauth-register .page-body > .row > .col-md-6, - #oauth-register .page-body > .row > .col-lg-5, - #oauth-register .page-body > .row > .col-xl-4, - #oauth-authorize .page-body > .row > .col-xs, - #oauth-authorize .page-body > .row > .col-sm-8, - #oauth-authorize .page-body > .row > .col-md-6, - #oauth-authorize .page-body > .row > .col-lg-5, - #oauth-authorize .page-body > .row > .col-xl-4, - #oauth-passwordless .page-body > .row > .col-xs, - #oauth-passwordless .page-body > .row > .col-sm-8, - #oauth-passwordless .page-body > .row > .col-md-6, - #oauth-passwordless .page-body > .row > .col-lg-5, - #oauth-passwordless .page-body > .row > .col-xl-4, - #oauth-two-factor .page-body > .row > .col-xs, - #oauth-two-factor .page-body > .row > .col-sm-8, - #oauth-two-factor .page-body > .row > .col-md-6, - #oauth-two-factor .page-body > .row > .col-lg-5, - #oauth-two-factor .page-body > .row > .col-xl-4, - #oauth-two-factor-methods .page-body > .row > .col-xs, - #oauth-two-factor-methods .page-body > .row > .col-sm-8, - #oauth-two-factor-methods .page-body > .row > .col-md-6, - #oauth-two-factor-methods .page-body > .row > .col-lg-5, - #oauth-two-factor-methods .page-body > .row > .col-xl-4, - #oauth-logout .page-body > .row > .col-xs, - #oauth-logout .page-body > .row > .col-sm-8, - #oauth-logout .page-body > .row > .col-md-6, - #oauth-logout .page-body > .row > .col-lg-5, - #oauth-logout .page-body > .row > .col-xl-4, - #oauth-device .page-body > .row > .col-xs, - #oauth-device .page-body > .row > .col-sm-8, - #oauth-device .page-body > .row > .col-md-6, - #oauth-device .page-body > .row > .col-lg-5, - #oauth-device .page-body > .row > .col-xl-4, - #oauth-device-complete .page-body > .row > .col-xs, - #oauth-device-complete .page-body > .row > .col-sm-8, - #oauth-device-complete .page-body > .row > .col-md-6, - #oauth-device-complete .page-body > .row > .col-lg-5, - #oauth-device-complete .page-body > .row > .col-xl-4, - #oauth-complete-reg .page-body > .row > .col-xs, - #oauth-complete-reg .page-body > .row > .col-sm-8, - #oauth-complete-reg .page-body > .row > .col-md-6, - #oauth-complete-reg .page-body > .row > .col-lg-5, - #oauth-complete-reg .page-body > .row > .col-xl-4, - #oauth-child-reg .page-body > .row > .col-xs, - #oauth-child-reg .page-body > .row > .col-sm-8, - #oauth-child-reg .page-body > .row > .col-md-6, - #oauth-child-reg .page-body > .row > .col-lg-5, - #oauth-child-reg .page-body > .row > .col-xl-4, - #oauth-child-reg-complete .page-body > .row > .col-xs, - #oauth-child-reg-complete .page-body > .row > .col-sm-8, - #oauth-child-reg-complete .page-body > .row > .col-md-6, - #oauth-child-reg-complete .page-body > .row > .col-lg-5, - #oauth-child-reg-complete .page-body > .row > .col-xl-4, - #oauth-not-registered .page-body > .row > .col-xs, - #oauth-not-registered .page-body > .row > .col-sm-8, - #oauth-not-registered .page-body > .row > .col-md-6, - #oauth-not-registered .page-body > .row > .col-lg-5, - #oauth-not-registered .page-body > .row > .col-xl-4, - #oauth-error .page-body > .row > .col-xs, - #oauth-error .page-body > .row > .col-sm-8, - #oauth-error .page-body > .row > .col-md-6, - #oauth-error .page-body > .row > .col-lg-5, - #oauth-error .page-body > .row > .col-xl-4, - #oauthstart-idp-link .page-body > .row > .col-xs, - #oauthstart-idp-link .page-body > .row > .col-sm-8, - #oauthstart-idp-link .page-body > .row > .col-md-6, - #oauthstart-idp-link .page-body > .row > .col-lg-5, - #oauthstart-idp-link .page-body > .row > .col-xl-4, - #oauth-wait .page-body > .row > .col-xs, - #oauth-wait .page-body > .row > .col-sm-8, - #oauth-wait .page-body > .row > .col-md-6, - #oauth-wait .page-body > .row > .col-lg-5, - #oauth-wait .page-body > .row > .col-xl-4, - #email-verification .page-body > .row > .col-xs, - #email-verification .page-body > .row > .col-sm-8, - #email-verification .page-body > .row > .col-md-6, - #email-verification .page-body > .row > .col-lg-5, - #email-verification .page-body > .row > .col-xl-4, - #email-ver-required .page-body > .row > .col-xs, - #email-ver-required .page-body > .row > .col-sm-8, - #email-ver-required .page-body > .row > .col-md-6, - #email-ver-required .page-body > .row > .col-lg-5, - #email-ver-required .page-body > .row > .col-xl-4, - #email-ver-complete .page-body > .row > .col-xs, - #email-ver-complete .page-body > .row > .col-sm-8, - #email-ver-complete .page-body > .row > .col-md-6, - #email-ver-complete .page-body > .row > .col-lg-5, - #email-ver-complete .page-body > .row > .col-xl-4, - #email-ver-resent .page-body > .row > .col-xs, - #email-ver-resent .page-body > .row > .col-sm-8, - #email-ver-resent .page-body > .row > .col-md-6, - #email-ver-resent .page-body > .row > .col-lg-5, - #email-ver-resent .page-body > .row > .col-xl-4, - #forgot-pwd .page-body > .row > .col-xs, - #forgot-pwd .page-body > .row > .col-sm-8, - #forgot-pwd .page-body > .row > .col-md-6, - #forgot-pwd .page-body > .row > .col-lg-5, - #forgot-pwd .page-body > .row > .col-xl-4, - #forgot-pwd-sent .page-body > .row > .col-xs, - #forgot-pwd-sent .page-body > .row > .col-sm-8, - #forgot-pwd-sent .page-body > .row > .col-md-6, - #forgot-pwd-sent .page-body > .row > .col-lg-5, - #forgot-pwd-sent .page-body > .row > .col-xl-4, - #verify-reg .page-body > .row > .col-xs, - #verify-reg .page-body > .row > .col-sm-8, - #verify-reg .page-body > .row > .col-md-6, - #verify-reg .page-body > .row > .col-lg-5, - #verify-reg .page-body > .row > .col-xl-4, - #verify-reg-complete .page-body > .row > .col-xs, - #verify-reg-complete .page-body > .row > .col-sm-8, - #verify-reg-complete .page-body > .row > .col-md-6, - #verify-reg-complete .page-body > .row > .col-lg-5, - #verify-reg-complete .page-body > .row > .col-xl-4, - #verify-reg-resent .page-body > .row > .col-xs, - #verify-reg-resent .page-body > .row > .col-sm-8, - #verify-reg-resent .page-body > .row > .col-md-6, - #verify-reg-resent .page-body > .row > .col-lg-5, - #verify-reg-resent .page-body > .row > .col-xl-4, - #verify-reg-required .page-body > .row > .col-xs, - #verify-reg-required .page-body > .row > .col-sm-8, - #verify-reg-required .page-body > .row > .col-md-6, - #verify-reg-required .page-body > .row > .col-lg-5, - #verify-reg-required .page-body > .row > .col-xl-4, - #acct-2fa-enable .page-body > .row > .col-xs-12, - #acct-2fa-enable .page-body > .row > .col-sm-12, - #acct-2fa-enable .page-body > .row > .col-md-10, - #acct-2fa-enable .page-body > .row > .col-lg-8, - #acct-2fa-disable .page-body > .row > .col-xs-12, - #acct-2fa-disable .page-body > .row > .col-sm-12, - #acct-2fa-disable .page-body > .row > .col-md-10, - #acct-2fa-disable .page-body > .row > .col-lg-8, - #unauthorized-page .page-body > .row > .col-sm-10, - #unauthorized-page .page-body > .row > .col-md-8, - #unauthorized-page .page-body > .row > .col-lg-7, - #unauthorized-page .page-body > .row > .col-xl-5, - #change-pwd .page-body > .row > .col-xs, - #change-pwd .page-body > .row > .col-sm-8, - #change-pwd .page-body > .row > .col-md-6, - #change-pwd .page-body > .row > .col-lg-5, - #change-pwd .page-body > .row > .col-xl-4, - #change-pwd-complete .page-body > .row > .col-xs, - #change-pwd-complete .page-body > .row > .col-sm-8, - #change-pwd-complete .page-body > .row > .col-md-6, - #change-pwd-complete .page-body > .row > .col-lg-5, - #change-pwd-complete .page-body > .row > .col-xl-4 { - flex-basis: calc(100% - 30px); - width: calc(100% - 30px); - max-width: 33rem; - } - .panel { - padding-left: .5rem; - padding-right: .5rem; - } - } - @media only screen and (min-width: 768px) { - #acct-2fa-index .page-body > .row.center:last-of-type { - width: calc(83.33333333% - 30px); - } - } - @media only screen and (min-width: 992px) { - #acct-2fa-index .page-body > .row > .col-xs12, - #acct-2fa-index .page-body > .row > .col-sm-12, - #acct-2fa-index .page-body > .row > .col-md-10, - #acct-2fa-index .page-body > .row > .col-lg-8 { - flex-basis: 54.125rem; - max-width: 54.125rem; - } - #acct-2fa-index .page-body > .row.center:last-of-type { - width: 54.125rem; - } - } - /* End grid override */ - - - /* Cleaning up spacing */ - #verify-reg-required .link.blue-text, - #verify-reg-required .grecaptcha-msg, - #verify-reg-required .panel > main > .full fieldset, - #verify-reg .grecaptcha-msg, - #verify-reg .panel > main > .full fieldset, - #email-ver-required .grecaptcha-msg, - #email-verification .grecaptcha-msg, - #email-ver-required fieldset, - #email-ver-required .panel > main > #verification-required-resend-code fieldset, - #oauth-two-factor .panel .full > fieldset, - #oauth-two-factor .panel > main > fieldset + .form-row, - #oauth-two-factor-methods .full, - #oauth-two-factor-methods .blue.button, - #oauth-authorize .panel > main > form > .form-row:first-of-type, - #oauth-passwordless .panel > main > .full > .form-row:first-of-type, - #oauth-register .panel > main > .full > .form-row:first-of-type, - #forgot-pwd .panel > main > .full fieldset, - #forgot-pwd .panel .grecaptcha-msg, - #change-pwd .panel > main .full > .form-row:first-of-type, - #acct-2fa-index .panel > main > fieldset { - margin-bottom: 0; - } - /* End spacing */ - - - /* Other page specific styles */ - - #acct-2fa-index .blue.button { - max-width: 25rem; - margin-left: auto; - margin-right: auto; - display: block; - } - #acct-2fa-index table { - margin-bottom: 3rem; - } - #acct-2fa-enable .d-flex { - display: block; - } - #acct-2fa-enable #qrcode { - padding-left: 0; - } - #acct-2fa-enable #qrcode img { - margin-left: auto; - margin-right: auto; - } - #acct-2fa-disable main > fieldset { - margin: 0; - } - #oauth-two-factor .panel form > .form-row:last-of-type a .fa { - display: none; /* hiding icon in button */ - } - #oauth-two-factor .panel > main > fieldset .form-row.mt-4 { - margin-top: 0; - } - #oauth-two-factor-methods input[type="radio"] { - vertical-align: text-top; - } - #oauth-two-factor-methods .full fieldset { - margin-top: 2rem; - margin-bottom: 0; - } - #oauth-two-factor-methods .full fieldset .form-row:last-child label { - padding-bottom: 0; - } - #oauth-two-factor-methods .radio-items .form-row label span:last-of-type { - margin-left: 1.875rem; - } - #oauth-device .push-top { - margin-top: 0; - } - #oauth-device #device-form > p { - text-align: center; - } - #oauth-device #user_code_container input[type="text"] { - color: var(--main-text-color); - } - #index-page ul li a { - font-family: var(--font-stack); - } - #oauth-passwordless .panel form .form-row:last-of-type p, - #oauth-register .panel form .form-row:last-of-type p, - #oauth-two-factor .panel form > .form-row:last-of-type, - #forgot-pwd .panel form > .form-row:last-of-type p, - #forgot-pwd-sent .panel main p:last-of-type, - #oauth-wait .panel main p:last-of-type { - margin-bottom: 0; - text-align: center; - } - - /* Account Index page */ - #acct-index .panel > main { - padding: 0; - } - #acct-index .user-details.mb-5 { - margin-bottom: 0; - } - #acct-index #edit-profile span { - font-size: inherit !important; - } - #acct-index #edit-profile span:after { - content: 'Edit'; - margin-left: .25em; - } - #acct-index .user-details > div { - margin: 0; - width: 100%; - max-width: 100%; - flex-basis: 100%; - } + .panel { + padding-left: .5rem; + padding-right: .5rem; + } +} +@media only screen and (min-width: 768px) { + #acct-2fa-index .page-body > .row.center:last-of-type { + width: calc(83.33333333% - 30px); + } +} +@media only screen and (min-width: 992px) { + #acct-2fa-index .page-body > .row > .col-xs12, + #acct-2fa-index .page-body > .row > .col-sm-12, + #acct-2fa-index .page-body > .row > .col-md-10, + #acct-2fa-index .page-body > .row > .col-lg-8 { + flex-basis: 54.125rem; + max-width: 54.125rem; + } + #acct-2fa-index .page-body > .row.center:last-of-type { + width: 54.125rem; + } +} +/* End grid override */ + + +/* Cleaning up spacing */ +#verify-reg-required .link.blue-text, +#verify-reg-required .grecaptcha-msg, +#verify-reg-required .panel > main > .full fieldset, +#verify-reg .grecaptcha-msg, +#verify-reg .panel > main > .full fieldset, +#email-ver-required .grecaptcha-msg, +#email-verification .grecaptcha-msg, +#email-ver-required fieldset, +#email-ver-required .panel > main > #verification-required-resend-code fieldset, +#oauth-two-factor .panel .full > fieldset, +#oauth-two-factor .panel > main > fieldset + .form-row, +#oauth-two-factor-methods .full, +#oauth-two-factor-methods .blue.button, +#oauth-authorize .panel > main > form > .form-row:first-of-type, +#oauth-passwordless .panel > main > .full > .form-row:first-of-type, +#oauth-register .panel > main > .full > .form-row:first-of-type, +#forgot-pwd .panel > main > .full fieldset, +#forgot-pwd .panel .grecaptcha-msg, +#change-pwd .panel > main .full > .form-row:first-of-type, +#acct-2fa-index .panel > main > fieldset { + margin-bottom: 0; +} +/* End spacing */ + + +/* Other page specific styles */ + +#acct-2fa-index .blue.button { + max-width: 25rem; + margin-left: auto; + margin-right: auto; + display: block; +} +#acct-2fa-index table { + margin-bottom: 3rem; +} +#acct-2fa-enable .d-flex { + display: block; +} +#acct-2fa-enable #qrcode { + padding-left: 0; +} +#acct-2fa-enable #qrcode img { + margin-left: auto; + margin-right: auto; +} +#acct-2fa-disable main > fieldset { + margin: 0; +} +#oauth-two-factor .panel form > .form-row:last-of-type a .fa { + display: none; /* hiding icon in button */ +} +#oauth-two-factor .panel > main > fieldset .form-row.mt-4 { + margin-top: 0; +} +#oauth-two-factor-methods input[type="radio"] { + vertical-align: text-top; +} +#oauth-two-factor-methods .full fieldset { + margin-top: 2rem; + margin-bottom: 0; +} +#oauth-two-factor-methods .full fieldset .form-row:last-child label { + padding-bottom: 0; +} +#oauth-two-factor-methods .radio-items .form-row label span:last-of-type { + margin-left: 1.875rem; +} +#oauth-device .push-top { + margin-top: 0; +} +#oauth-device #device-form > p { + text-align: center; +} +#oauth-device #user_code_container input[type="text"] { + color: var(--main-text-color); +} +#index-page ul li a { + font-family: var(--font-stack); +} +#oauth-passwordless .panel form .form-row:last-of-type p, +#oauth-register .panel form .form-row:last-of-type p, +#oauth-two-factor .panel form > .form-row:last-of-type, +#forgot-pwd .panel form > .form-row:last-of-type p, +#forgot-pwd-sent .panel main p:last-of-type, +#oauth-wait .panel main p:last-of-type { + margin-bottom: 0; + text-align: center; +} + +/* Account Index page */ +#acct-index .panel > main { + padding: 0; +} +#acct-index .user-details.mb-5 { + margin-bottom: 0; +} +#acct-index #edit-profile span { + font-size: inherit !important; +} +#acct-index #edit-profile span:after { + content: 'Edit'; + margin-left: .25em; +} +#acct-index .user-details > div { + margin: 0; + width: 100%; + max-width: 100%; + flex-basis: 100%; +} +#acct-index .user-details dl { + display: flex; + align-items: flex-start; + justify-content: space-between; + margin: 1.25rem 0; +} +#acct-index .user-details dt { + float: none; + font-weight: 500; + width: 40%; + margin: 0; +} +#acct-index .user-details dd { + width: 60%; + margin: 0; +} +#acct-index .panel { + padding-left: 1.5rem; + padding-right: 1.5rem; +} +#acct-index .panel:before { + content: ''; + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 4rem; + background-color: var(--main-accent-color); + border-radius: .625rem .625rem 0 0; +} +#acct-index .user-details .avatar > div:last-of-type { + color: var(--main-accent-color); + font-weight: 500; + font-size: 1.5rem; +} +#acct-index .user-details .avatar { + top: -2.25rem; + position: relative; + z-index: 2; + padding: 0; +} +#acct-index .user-details .avatar > div:first-of-type { + max-width: 7.5rem; + padding: 0; +} +#acct-index .user-details .avatar > div:first-of-type img { + border: .625rem solid #ffffff; +} +#acct-index .user-details > div:nth-of-type(2) > div { + padding: 0; +} +#acct-index .user-details > div:nth-of-type(2) > div > div { + margin: 0; + flex-basis: 100%; + width: 100%; + max-width: 100%; +} +#acct-index .user-details .panel-actions { + top: 3.5rem; + right: .25rem; +} +@media only screen and (max-width: 450px) { #acct-index .user-details dl { - display: flex; - align-items: flex-start; - justify-content: space-between; - margin: 1.25rem 0; - } - #acct-index .user-details dt { - float: none; - font-weight: 500; - width: 40%; - margin: 0; + flex-direction: column; } + #acct-index .user-details dt, #acct-index .user-details dd { - width: 60%; - margin: 0; - } - #acct-index .panel { - padding-left: 1.5rem; - padding-right: 1.5rem; + width: 100%; + margin-bottom: .5em; } +} +@media only screen and (min-width: 768px) { #acct-index .panel:before { - content: ''; + width: 4rem; + height: 100%; + border-radius: .625rem 0 0 .625rem; + } + #acct-index .user-details { display: block; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 4rem; - background-color: var(--main-accent-color); - border-radius: .625rem .625rem 0 0; + margin-left: 8rem; } - #acct-index .user-details .avatar > div:last-of-type { - color: var(--main-accent-color); - font-weight: 500; - font-size: 1.5rem; + #acct-index .user-details > div { + margin: 0; + width: 80%; + max-width: 80%; } #acct-index .user-details .avatar { - top: -2.25rem; - position: relative; - z-index: 2; - padding: 0; + position: static; } #acct-index .user-details .avatar > div:first-of-type { - max-width: 7.5rem; - padding: 0; + position: absolute; + left: .75rem; + top: calc(50% - 3.25rem); + width: 6.5rem; } #acct-index .user-details .avatar > div:first-of-type img { - border: .625rem solid #ffffff; - } - #acct-index .user-details > div:nth-of-type(2) > div { - padding: 0; + border-width: .5rem; } - #acct-index .user-details > div:nth-of-type(2) > div > div { - margin: 0; - flex-basis: 100%; - width: 100%; - max-width: 100%; + #acct-index .user-details .avatar > div:last-of-type { + text-align: left; } #acct-index .user-details .panel-actions { - top: 3.5rem; - right: .25rem; + top: -0.25rem; + right: .5rem; } - @media only screen and (max-width: 450px) { - #acct-index .user-details dl { - flex-direction: column; - } - #acct-index .user-details dt, - #acct-index .user-details dd { - width: 100%; - margin-bottom: .5em; - } + #acct-index .page-body > .row.center:last-of-type { + width: calc(83.33333333% - 30px); } - @media only screen and (min-width: 768px) { - #acct-index .panel:before { - width: 4rem; - height: 100%; - border-radius: .625rem 0 0 .625rem; - } - #acct-index .user-details { - display: block; - margin-left: 8rem; - } - #acct-index .user-details > div { - margin: 0; - width: 80%; - max-width: 80%; - } - #acct-index .user-details .avatar { - position: static; - } - #acct-index .user-details .avatar > div:first-of-type { - position: absolute; - left: .75rem; - top: calc(50% - 3.25rem); - width: 6.5rem; - } - #acct-index .user-details .avatar > div:first-of-type img { - border-width: .5rem; - } - #acct-index .user-details .avatar > div:last-of-type { - text-align: left; - } - #acct-index .user-details .panel-actions { - top: -0.25rem; - right: .5rem; - } - #acct-index .page-body > .row.center:last-of-type { - width: calc(83.33333333% - 30px); - } +} +@media only screen and (min-width: 992px) { + #acct-index .page-body > .row:first-of-type > .col-xs-12, + #acct-index .page-body > .row:first-of-type > .col-sm-12, + #acct-index .page-body > .row:first-of-type > .col-md-10, + #acct-index .page-body > .row:first-of-type > .col-lg-8 { + flex-basis: 54.125rem; + max-width: 54.125rem; } - @media only screen and (min-width: 992px) { - #acct-index .page-body > .row:first-of-type > .col-xs-12, - #acct-index .page-body > .row:first-of-type > .col-sm-12, - #acct-index .page-body > .row:first-of-type > .col-md-10, - #acct-index .page-body > .row:first-of-type > .col-lg-8 { - flex-basis: 54.125rem; - max-width: 54.125rem; - } - #acct-index .page-body > .row.center:last-of-type { - width: 54.125rem; - } - #acct-index .panel:before { - width: 6.25rem; - } - #acct-index .user-details { - margin-left: 13rem; - } - #acct-index .user-details .panel-actions { - padding: 0; - top: 2.25rem; - right: 2.25rem; - } - #acct-index .user-details .panel-actions .status, - #acct-index .user-details .panel-actions #edit-profile { - margin: 0; - } - #acct-index .user-details > div:first-of-type { - border: none; - width: auto; - flex-basis: auto; - } - #acct-index .user-details .avatar { - left: -.25rem; - } - #acct-index .user-details .avatar > div:first-of-type { - width: 8.75rem; - max-width: 8.75rem; - top: calc(50% - 4.5rem); - left: 1.875rem; - } - #acct-index .user-details .avatar > div:first-of-type img { - border-width: .75rem; - } + #acct-index .page-body > .row.center:last-of-type { + width: 54.125rem; } - /*End Account Index page */ - - - /* specific page button/link overrides */ - #acct-2fa-enable .gray.button { - color: var(--main-accent-color) !important; - padding: .5em .75em !important; - border: 1px solid var(--main-accent-color) !important; - border-radius: .25em; - font-size: .75rem !important; - margin: 1rem auto; - display: block; - line-height: normal !important; - background: transparent !important; + #acct-index .panel:before { + width: 6.25rem; } - #email-ver-required .link.blue-text { - display: block; - margin: 1rem auto; - text-decoration: underline; + #acct-index .user-details { + margin-left: 13rem; } - #oauth-two-factor .panel form > .form-row:last-of-type a, - #verify-reg-required .panel .link.blue-text { - display: block; - margin: 1rem auto 0 auto; - text-decoration: underline; - } - #email-ver-required .link.blue-text .fa, - #verify-reg-required .panel .link.blue-text .fa { - display: none; /* hiding icon in link */ + #acct-index .user-details .panel-actions { + padding: 0; + top: 2.25rem; + right: 2.25rem; } - #oauth-passwordless .panel form .form-row:last-of-type a, - #oauth-register .panel form .form-row:last-of-type a, - #forgot-pwd .panel form > .form-row:last-of-type a, - #forgot-pwd-sent .panel main p:last-of-type a, - #oauth-wait .panel main p:last-of-type a { - color: var(--main-accent-color) !important; - padding: .5em .75em; - border: 1px solid var(--main-accent-color) !important; - border-radius: .25em; - font-size: .75rem; - margin: 1rem auto 0 auto; - display: inline-block; - line-height: normal; - text-decoration: none; + #acct-index .user-details .panel-actions .status, + #acct-index .user-details .panel-actions #edit-profile { + margin: 0; } - #forgot-pwd-sent .panel main p:last-of-type a { - color: var(--main-accent-color) !important; - padding: .5em .75em; - border: 1px solid var(--main-accent-color) !important; - border-radius: .25em; - font-size: .75rem; - margin: 0 auto; - display: inline-block; - line-height: normal; - text-decoration: none; + #acct-index .user-details > div:first-of-type { + border: none; + width: auto; + flex-basis: auto; } - #oauthstart-idp-link .blue.button { - height: auto !important; - margin-top: 0; + #acct-index .user-details .avatar { + left: -.25rem; } - #oauthstart-idp-link .panel main div:last-of-type a { - display: block; - border: none; - margin-top: 0; - padding: 0; + #acct-index .user-details .avatar > div:first-of-type { + width: 8.75rem; + max-width: 8.75rem; + top: calc(50% - 4.5rem); + left: 1.875rem; } - /* End page specific buttons and links */ - + #acct-index .user-details .avatar > div:first-of-type img { + border-width: .75rem; + } +} +/*End Account Index page */ + + +/* specific page button/link overrides */ +#acct-2fa-enable .gray.button { + color: var(--main-accent-color) !important; + padding: .5em .75em !important; + border: 1px solid var(--main-accent-color) !important; + border-radius: .25em; + font-size: .75rem !important; + margin: 1rem auto; + display: block; + line-height: normal !important; + background: transparent !important; +} +#email-ver-required .link.blue-text { + display: block; + margin: 1rem auto; + text-decoration: underline; +} +#oauth-two-factor .panel form > .form-row:last-of-type a, +#verify-reg-required .panel .link.blue-text { + display: block; + margin: 1rem auto 0 auto; + text-decoration: underline; +} +#email-ver-required .link.blue-text .fa, +#verify-reg-required .panel .link.blue-text .fa { + display: none; /* hiding icon in link */ +} +#oauth-passwordless .panel form .form-row:last-of-type a, +#oauth-register .panel form .form-row:last-of-type a, +#forgot-pwd .panel form > .form-row:last-of-type a, +#forgot-pwd-sent .panel main p:last-of-type a, +#oauth-wait .panel main p:last-of-type a { + color: var(--main-accent-color) !important; + padding: .5em .75em; + border: 1px solid var(--main-accent-color) !important; + border-radius: .25em; + font-size: .75rem; + margin: 1rem auto 0 auto; + display: inline-block; + line-height: normal; + text-decoration: none; +} +#forgot-pwd-sent .panel main p:last-of-type a { + color: var(--main-accent-color) !important; + padding: .5em .75em; + border: 1px solid var(--main-accent-color) !important; + border-radius: .25em; + font-size: .75rem; + margin: 0 auto; + display: inline-block; + line-height: normal; + text-decoration: none; +} +#oauthstart-idp-link .blue.button { + height: auto !important; + margin-top: 0; +} +#oauthstart-idp-link .panel main div:last-of-type a { + display: block; + border: none; + margin-top: 0; + padding: 0; +} +/* End page specific buttons and links */ + diff --git a/kickstart/kickstart.json b/kickstart/kickstart.json index 4e4c031..11cf4d9 100644 --- a/kickstart/kickstart.json +++ b/kickstart/kickstart.json @@ -109,9 +109,64 @@ "method": "POST", "url": "/api/theme/#{newThemeId}", "body": { - "sourceThemeId": "75a068fd-e94b-451a-9aeb-3ddb9a3b5987", "theme": { - "name": "React theme" + "name": "Thymeleaf theme", + "defaultMessages": "@{templates/defaultMessages.txt}", + "stylesheet": "@{css/styles.css}", + "templates": { + "accountEdit": "@{templates/accountEdit.ftl}", + "accountIndex": "@{templates/accountIndex.ftl}", + "accountTwoFactorDisable": "@{templates/accountTwoFactorDisable.ftl}", + "accountTwoFactorEnable": "@{templates/accountTwoFactorEnable.ftl}", + "accountTwoFactorIndex": "@{templates/accountTwoFactorIndex.ftl}", + "accountWebAuthnAdd": "@{templates/accountWebAuthnAdd.ftl}", + "accountWebAuthnDelete": "@{templates/accountWebAuthnDelete.ftl}", + "accountWebAuthnIndex": "@{templates/accountWebAuthnIndex.ftl}", + "confirmationRequired": "@{templates/confirmationRequired.ftl}", + "emailComplete": "@{templates/emailComplete.ftl}", + "emailSend": "@{templates/emailSend.ftl}", + "emailSent": "@{templates/emailSent.ftl}", + "emailVerificationRequired": "@{templates/emailVerificationRequired.ftl}", + "emailVerify": "@{templates/emailVerify.ftl}", + "helpers": "@{templates/helpers.ftl}", + "index": "@{templates/index.ftl}", + "oauth2Authorize": "@{templates/oauth2Authorize.ftl}", + "oauth2AuthorizedNotRegistered": "@{templates/oauth2AuthorizedNotRegistered.ftl}", + "oauth2ChildRegistrationNotAllowed": "@{templates/oauth2ChildRegistrationNotAllowed.ftl}", + "oauth2ChildRegistrationNotAllowedComplete": "@{templates/oauth2ChildRegistrationNotAllowedComplete.ftl}", + "oauth2CompleteRegistration": "@{templates/oauth2CompleteRegistration.ftl}", + "oauth2Consent": "@{templates/oauth2Consent.ftl}", + "oauth2Device": "@{templates/oauth2Device.ftl}", + "oauth2DeviceComplete": "@{templates/oauth2DeviceComplete.ftl}", + "oauth2Error": "@{templates/oauth2Error.ftl}", + "oauth2Logout": "@{templates/oauth2Logout.ftl}", + "oauth2Passwordless": "@{templates/oauth2Passwordless.ftl}", + "oauth2Register": "@{templates/oauth2Register.ftl}", + "oauth2StartIdPLink": "@{templates/oauth2StartIdPLink.ftl}", + "oauth2TwoFactor": "@{templates/oauth2TwoFactor.ftl}", + "oauth2TwoFactorEnable": "@{templates/oauth2TwoFactorEnable.ftl}", + "oauth2TwoFactorEnableComplete": "@{templates/oauth2TwoFactorEnableComplete.ftl}", + "oauth2TwoFactorMethods": "@{templates/oauth2TwoFactorMethods.ftl}", + "oauth2Wait": "@{templates/oauth2Wait.ftl}", + "oauth2WebAuthn": "@{templates/oauth2WebAuthn.ftl}", + "oauth2WebAuthnReauth": "@{templates/oauth2WebAuthnReauth.ftl}", + "oauth2WebAuthnReauthEnable": "@{templates/oauth2WebAuthnReauthEnable.ftl}", + "passwordChange": "@{templates/passwordChange.ftl}", + "passwordComplete": "@{templates/passwordComplete.ftl}", + "passwordForgot": "@{templates/passwordForgot.ftl}", + "passwordSent": "@{templates/passwordSent.ftl}", + "phoneComplete": "Phone complete template", + "phoneSent": "Phone sent template", + "phoneVerificationRequired": "Phone verification required template", + "phoneVerify": "Phone verify template", + "registrationComplete": "@{templates/registrationComplete.ftl}", + "registrationSend": "@{templates/registrationSend.ftl}", + "registrationSent": "@{templates/registrationSent.ftl}", + "registrationVerificationRequired": "@{templates/registrationVerificationRequired.ftl}", + "registrationVerify": "@{templates/registrationVerify.ftl}", + "samlv2Logout": "@{templates/samlv2Logout.ftl}", + "unauthorized" : "@{templates/unauthorized.ftl}" + } } } }, diff --git a/kickstart/templates/accountEdit.ftl b/kickstart/templates/accountEdit.ftl new file mode 100644 index 0000000..f144f87 --- /dev/null +++ b/kickstart/templates/accountEdit.ftl @@ -0,0 +1,83 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="fields" type="java.util.Map>" --] +[#-- @ftlvariable name="user" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="passwordSet" type="boolean" --] + +[#import "../_helpers.ftl" as helpers/] + +[#function generateSectionLabel sectionNumber tenantId] + [#-- Tenant specific, not tenant specific, then default --] + [#local sectionLabel = theme.optionalMessage("[${tenantId}]{self-service-form}${sectionNumber}")/] + [#local resolvedLabel = sectionLabel != "[${tenantId}]{self-service-form}${sectionNumber}"/] + [#if !resolvedLabel] + [#local sectionLabel = theme.optionalMessage("{self-service-form}${sectionNumber}")/] + [#local resolvedLabel = sectionLabel != "{self-service-form}${sectionNumber}"/] + [/#if] + [#if !resolvedLabel] + [#return ""/] + [#else] + [#return sectionLabel /] + [/#if] +[/#function] + +[@helpers.html] + [@helpers.head title=theme.message("account")/] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + + [/@helpers.header] + + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL="/account/" actionText=theme.message("cancel-go-back")] + [@helpers.accountPanel title="" tenant=tenant user=currentUser action="edit" showEdit=true] +
+
+
+ [@helpers.hidden name="client_id" /] + [@helpers.hidden name="tenantId" /] + [#if fields?has_content] +
+ [#list fields as fieldKey, fieldValues] + + [#-- Section labels --] + [#assign sectionNumber = fieldKey + 1/] + [#assign sectionLabel = generateSectionLabel(sectionNumber, tenantId) /] + [#if sectionLabel?has_content] + ${sectionLabel} + [/#if] + + [#list fieldValues as field] + [#if field.key == "user.password"] + [@helpers.passwordField field=field + showCurrentPasswordField=(passwordSet && application.formConfiguration.selfServiceFormConfiguration.requireCurrentPasswordOnPasswordChange)/] + [#else] + [#assign key = field.key] + [@helpers.customField field key field?is_first field.key /] + + [#if field.confirm] + [@helpers.customField field "confirm.${key}" false "[confirm]${field.key}" /] + [/#if] + [/#if] + [/#list] + [/#list] +
+ [/#if] +
+ [@helpers.button icon="save" text=theme.message("submit")/] +
+
+
+
+ [/@helpers.accountPanel] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/accountIndex.ftl b/kickstart/templates/accountIndex.ftl new file mode 100644 index 0000000..b5d4a89 --- /dev/null +++ b/kickstart/templates/accountIndex.ftl @@ -0,0 +1,54 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="formConfigured" type="boolean" --] +[#-- @ftlvariable name="multiFactorAvailable" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="user" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="webauthnAvailable" type="boolean" --] + +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("account")] + [#-- Custom header code goes here --] + + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [#assign actionURLs = multiFactorAvailable?then(["/account/two-factor/"], [])/] + [#assign actionURLs = actionURLs + webauthnAvailable?then(["/account/webauthn/"], [])/] + + [#assign actionTexts = multiFactorAvailable?then([theme.message("manage-two-factor")], [])/] + [#assign actionTexts = actionTexts + webauthnAvailable?then([theme.message("manage-webauthn-passkeys")], [])/] + + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL=actionURLs actionText=actionTexts actionDirection="forward"] + [@helpers.accountPanel title="" tenant=tenant user=user action="view" showEdit=formConfigured] +
+
+ [#-- Example landing page. This can be customized and different values can be displayed from the user. --] +
+
${theme.message("user.email")}
+
+ [#if user.verified ] [/#if] + ${helpers.display(user, "email")} +
+
+
+
${theme.message("user.phoneNumber")}
+
${fusionAuth.phone_format(user.phoneNumber!"\x2013")}
+
+
+
+ [/@helpers.accountPanel] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/accountTwoFactorDisable.ftl b/kickstart/templates/accountTwoFactorDisable.ftl new file mode 100644 index 0000000..03763a9 --- /dev/null +++ b/kickstart/templates/accountTwoFactorDisable.ftl @@ -0,0 +1,78 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="method" type="java.lang.String" --] +[#-- @ftlvariable name="methodId" type="java.lang.String" --] +[#-- @ftlvariable name="email" type="java.lang.String" --] +[#-- @ftlvariable name="mobilePhone" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="user" type="io.fusionauth.domain.User" --] + +[#import "../../_helpers.ftl" as helpers/] + +[#macro instructions method] +
+
+ [#if method == "authenticator"] +

${theme.message("authenticator-disable-step-1")}

+ [#elseif method == "email" || method == "sms"] +

${theme.message("${method}-disable-step-1", (method == "email")?then(email, mobilePhone))}

+
+ [@helpers.hidden name="action" value="send" /] + [@helpers.hidden name="client_id" /] + [@helpers.hidden name="tenantId" /] + [@helpers.hidden name="methodId" /] + [#-- Send a code --] + [@helpers.button icon="arrow-circle-right" color="gray" text="${theme.message('send-one-time-code')}"/] +
+ [/#if] +
+
+[/#macro] + +[@helpers.html] + [@helpers.head title=theme.message("authenticator-configuration")/] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL="/account/two-factor/" actionText=theme.message("cancel-go-back")] + [@helpers.accountPanelFull] + +
+ [#-- Heading --] + ${theme.message("disable-instructions")} + + [#-- Instructions --] + [@instructions method/] + +

+ ${theme.message('note')} ${theme.message('{description}two-factor-recovery-code-note')} +

+
+ +
+ [@helpers.hidden name="client_id" /] + [@helpers.hidden name="tenantId" /] + [@helpers.hidden name="methodId" /] + +
+ [@helpers.input type="text" name="code" id="verification-code" label=theme.message("verification-code") placeholder="${theme.message('{placeholder}two-factor-code')}" autofocus=true autocapitalize="none" autocomplete="one-time-code" autocorrect="off" required=true/] +
+ +
+ [@helpers.button icon="save" text=theme.message("disable")/] +
+
+ [/@helpers.accountPanelFull] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + + [/@helpers.body] +[/@helpers.html] \ No newline at end of file diff --git a/kickstart/templates/accountTwoFactorEnable.ftl b/kickstart/templates/accountTwoFactorEnable.ftl new file mode 100644 index 0000000..1b8a203 --- /dev/null +++ b/kickstart/templates/accountTwoFactorEnable.ftl @@ -0,0 +1,155 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="availableMethods" type="java.util.List" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="email" type="java.lang.String" --] +[#-- @ftlvariable name="method" type="java.lang.String" --] +[#-- @ftlvariable name="mobilePhone" type="java.lang.String" --] +[#-- @ftlvariable name="recoveryCodes" type="java.util.List" --] +[#-- @ftlvariable name="secret" type="java.lang.String" --] +[#-- @ftlvariable name="secretBase32Encoded" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="user" type="io.fusionauth.domain.User" --] + +[#import "../../_helpers.ftl" as helpers/] + +[#macro instructions method] +
+
+ [#if method == "authenticator"] + + [#-- Authenticator Instructions --] +

${theme.message("authenticator-enable-step-1", secretBase32Encoded)?no_esc}

+

${theme.message("authenticator-enable-step-2")}

+ + [#elseif method == "email" || method == "sms"] + + [#-- Email or SMS Instructions --] +

${theme.message("${method}-enable-step-1", helpers.display(user, (method == "email")?then("email", "mobilePhone")))}

+ +
+ [@helpers.hidden name="action" value="send" /] + [@helpers.hidden name="client_id" /] + [@helpers.hidden name="tenantId" /] + [@helpers.hidden name="method" /] + [#-- 'secret' and 'twoFactorSecretBase32' are required for authenticator. --] + [@helpers.hidden name="secret" /] + [@helpers.hidden name="secretBase32Encoded" /] + + [#-- Send a code --] + [#if method == "email"] + [@helpers.input type="text" id="email" name="email" label="Email" required=true/] + [#elseif method == "sms"] + [@helpers.input type="text" id="mobilePhone" name="mobilePhone" label="Mobile phone" required=true/] + [/#if] + + [@helpers.button icon="arrow-circle-right" color="gray" text="${theme.message('send-one-time-code')}"/] +
+ [/#if] +
+ + [#-- QR Code for Authenticator app --] + [#if method == "authenticator"] +
+ [/#if] + +
+[/#macro] + +[@helpers.html] + [@helpers.head title=theme.message("authenticator-configuration")] + [#-- JavaScript is used for rendering authenticator QR code --] + + + + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [#assign textKey = recoveryCodes?has_content?then("done", "go-back")/] + [#assign actionDirection = recoveryCodes?has_content?then("forward", "back")/] + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL="/account/two-factor/" actionText=theme.message(textKey) actionDirection=actionDirection] + [@helpers.accountPanelFull] + + [#-- The first time a user enables a two-factor code, they will be presented with recovery codes. --] + [#if recoveryCodes?has_content] + [#-- Display Recovery codes to the user. --] + +
+
+
+

${theme.message("{description}recovery-codes-1", recoveryCodes?size)}

+
+
+
+ [#list recoveryCodes as code]
${code}
[/#list] +
+
+
+

${theme.message("{description}recovery-codes-2")}

+
+
+
+ + [#else] + [#-- Show the Enable Two-Factor form --] + +
+ [#-- Heading --] + ${theme.message("enable-instructions")} +
+ [@helpers.select name="method" id="select-method" options=availableMethods label="${theme.message('select-two-factor-method')}" required=true/] +
+
+ + [#list availableMethods as method] +
+ [#-- Instructions --] + [@instructions method/] +
+ [/#list] + + [#-- Enable Two Factor Form --] +
+ [@helpers.hidden name="client_id" /] + [@helpers.hidden name="tenantId" /] + [@helpers.hidden name="email" /] + [@helpers.hidden name="method" /] + [@helpers.hidden name="mobilePhone" /] + [#-- 'secret' and 'twoFactorSecretBase32' are required for authenticator. --] + [@helpers.hidden name="secret" /] + [@helpers.hidden name="secretBase32Encoded" /] +
+ [@helpers.input type="text" name="code" id="verification-code" label=theme.message("verification-code") placeholder="${theme.message('{placeholder}two-factor-code')}" autocapitalize="none" autocomplete="one-time-code" autocorrect="off" required=true/] +
+
+ [@helpers.button icon="save" text=theme.message("enable")/] +
+
+ [/#if] + + [/@helpers.accountPanelFull] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/accountTwoFactorIndex.ftl b/kickstart/templates/accountTwoFactorIndex.ftl new file mode 100644 index 0000000..6859cd1 --- /dev/null +++ b/kickstart/templates/accountTwoFactorIndex.ftl @@ -0,0 +1,71 @@ +[#ftl/] +[#setting url_escaping_charset="UTF-8"] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="user" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] + +[#import "../../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("multi-factor-configuration")/] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL="/account/" actionText=theme.message("go-back")] + [@helpers.accountPanelFull] + +
+ ${theme.message("two-factor-authentication")} +

${theme.message("{description}two-factor-authentication")}

+ + + + + + + + + + + [#list user.twoFactor.methods as method] + + + + + + [#else] + + + + [/#list] + +
${theme.message("method")}${theme.message("value")}${theme.message("action")}
${theme.message(method.method)} + [#if method.method == "email"]${helpers.display(method, "email")} + [#elseif method.method == "sms"]${helpers.display(method, "mobilePhone")} + [#else]– + [/#if] + + +
${theme.message("no-two-factor-methods-configured")}
+ + + +
+ + [/@helpers.accountPanelFull] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/accountWebAuthnAdd.ftl b/kickstart/templates/accountWebAuthnAdd.ftl new file mode 100644 index 0000000..a6938cc --- /dev/null +++ b/kickstart/templates/accountWebAuthnAdd.ftl @@ -0,0 +1,71 @@ +[#ftl/] +[#setting url_escaping_charset="UTF-8"] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="user" type="io.fusionauth.domain.User" --] + +[#import "../../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("add-webauthn-passkey")] + + + + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL="/account/webauthn/" actionText=theme.message("go-back")] + [@helpers.accountPanelFull] + +
+ ${theme.message("add-webauthn-passkey")} +

${theme.message("{description}add-webauthn")}

+ +
+ +
+ [@helpers.hidden name="client_id" /] + [@helpers.hidden name="tenantId" /] + + [@helpers.hidden name="webAuthnRegisterRequest" /] + +
+ [#-- Default the displayName on initial render if not alread set. --] + [#if !(displayName??) && request.method == "GET"] + [#global displayName = theme.message('unnamed')/] + [/#if] + [@helpers.input type="text" id="displayName" name="displayName" autocapitalize="off" autocomplete="off" autofocus=true/] +
+ +
+ [@helpers.button text=theme.message("submit")/] +
+
+ + [/@helpers.accountPanelFull] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/accountWebAuthnDelete.ftl b/kickstart/templates/accountWebAuthnDelete.ftl new file mode 100644 index 0000000..d42aea3 --- /dev/null +++ b/kickstart/templates/accountWebAuthnDelete.ftl @@ -0,0 +1,61 @@ +[#ftl/] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="credential" type="io.fusionauth.domain.WebAuthnCredential" --] + +[#import "../../_helpers.ftl" as helpers/] + +[#macro row name value] + + ${name} ${theme.message("propertySeparator")} + ${value} + +[/#macro] + +[@helpers.html] + [@helpers.head title=theme.message("delete-webauthn-passkey")] + [#-- Custom head/script code goes here --] + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL="/account/webauthn/" actionText=theme.message("go-back")] + [@helpers.accountPanelFull] +
+ ${theme.message("delete-webauthn-passkey")} +

${theme.message("{description}delete-webauthn-passkey")}

+ + + + [@row name=theme.message("name") value=helpers.display(credential, "displayName") /] + [@row name=theme.message("identifier") value=helpers.display(credential, "name") /] + [@row name=theme.message("id") value=helpers.display(credential, "id") /] + [@row name=theme.message("created") value=theme.formatZoneDateTime(credential.insertInstant, theme.message('date-time-format'), zoneId) /] + [@row name=theme.message("last-used") value=theme.formatZoneDateTime(credential.lastUseInstant, theme.message('date-time-format'), zoneId) /] + [@row name=theme.message("relying-party-id") value=helpers.display(credential, "relyingPartyId") /] + [@row name=theme.message("signature-count") value=helpers.display(credential, "signCount") /] + +
+
+ +
+ [@helpers.hidden name="id"/] + [@helpers.hidden name="client_id"/] + [@helpers.hidden name="tenantId"/] + +
+ [@helpers.button icon="trash" color="red" text=theme.message("delete")/] +
+
+ [/@helpers.accountPanelFull] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] + + diff --git a/kickstart/templates/accountWebAuthnIndex.ftl b/kickstart/templates/accountWebAuthnIndex.ftl new file mode 100644 index 0000000..98b6fdc --- /dev/null +++ b/kickstart/templates/accountWebAuthnIndex.ftl @@ -0,0 +1,85 @@ +[#ftl/] +[#setting url_escaping_charset="UTF-8"] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="user" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="webAuthnCredentials" type="java.util.List" --] + +[#import "../../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("passkeys")] + + + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.accountMain rowClass="row center" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-8" actionURL="/account/" actionText=theme.message("go-back")] + [@helpers.accountPanelFull] + +
+ ${theme.message("passkeys")} +

${theme.message("{description}webauthn-passkeys")}

+ + + + + + + + + + + + + [#list webAuthnCredentials![] as cred] + + + + + + + [#else] + + + + [/#list] + +
${theme.message("display-name")}${theme.message("created")}${theme.message("last-used")}${theme.message("action")}
${helpers.display(cred, "displayName")}${theme.formatZoneDateTime(cred.insertInstant, theme.message('date-time-format'), zoneId)}${theme.formatZoneDateTime(cred.lastUseInstant, theme.message('date-time-format'), zoneId)} + + + +
${theme.message("no-webauthn-passkeys")}
+ + + +
+ [/@helpers.accountPanelFull] + [/@helpers.accountMain] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/confirmationRequired.ftl b/kickstart/templates/confirmationRequired.ftl new file mode 100644 index 0000000..6684d08 --- /dev/null +++ b/kickstart/templates/confirmationRequired.ftl @@ -0,0 +1,48 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="confirmationRequiredReason" type="java.lang.String" --] +[#-- @ftlvariable name="csrfToken" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("confirmation-required")] + [#-- Custom code goes here --] + [/@helpers.head ] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("confirmation-required")] + + [#-- Message specific to the reason the user is being required to confirm. + - Adding ?no_esc to allow the message to include
(line breaks) + --] + [#if confirmationRequiredReason?has_content] +

${theme.message("{description}confirmation-required-${confirmationRequiredReason}")?no_esc}

+ [/#if] + + [#-- Generic detail about what to do next --] +

${theme.message("{description}confirmation-required-ignore")}

+ +
+ + [#list request.parameters as key,value] + [#list value as v] + + [/#list] + [/#list] +
+ [@helpers.button text=theme.message('continue') /] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/defaultMessages.txt b/kickstart/templates/defaultMessages.txt new file mode 100644 index 0000000..c78e20a --- /dev/null +++ b/kickstart/templates/defaultMessages.txt @@ -0,0 +1,707 @@ +# +# Date and Time formats +# +date-format=M/d/yyyy +date-time-format=M/d/yyyy hh:mm a z +date-time-seconds-format=M/d/yyyy hh:mm:ss a z + +# +# Text used on the page (inside the HTML). You can create new key-value pairs here and use them in the templates. +# +access-denied=Access denied +account=Account +action=Action +add-two-factor=Add two-factor +add-webauthn-passkey=Add passkey +back-to-login=Return to Login +cancel=Cancel +captcha-google-branding=This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply. +created=Created +customize=Customize +authorized-not-registered=Registration is required to access this application and your account has not been registered for this application. Please complete your registration and try again. +authorized-not-registered-title=Registration Required +cancel-link=Cancel link request +child-registration-not-allowed=We cannot create an account for you. Your parent or guardian can create an account for you. Enter their email address and we will ask them to create your account. +click-here-to-logout=Click here to logout +complete=Complete +complete-registration=Complete registration +configure=Configure +configured=Configured +confirmation-required=Confirmation required +create-an-account=Create an account +complete-external-login=Complete login on your external device\u2026 +completed-link=You have successfully linked your %s account. +completed-links=You have successfully linked your %s and %s account. +confirm=Confirm +consent-required=Consent required +consent-required-intro=%s would like to +delete-webauthn-passkey=Delete passkey +device-form-title=Device login +device-login-complete=Successfully connected device +device-title=Connect Your Device +device-link-count-exceeded-next-step=To continue, click the button below. You will be logged out and then redirected here to continue the device login. +device-link-count-exceeded-pending-logout=You are logged in as %s. No additional links may be made to %s. +device-logged-in-as-not-you=You are logged in as %s. If you continue, the device login will be completed without an additional prompt. If this is not you, click logout before continuing. +disable=Disable +display-name=Display name +done=Done +dont-ask-again=Don't ask me again on this device +dont-have-an-account=Don't have an account? +edit=Edit +email-verification-complete=Thank you. Your email has been verified. +email-verification-complete-title=Email verification complete +email-verification-form=Complete the form to request a new verification email. +email-verification-form-title=Email verification +email-verification-sent=We have sent an email to %s with your verification code. Follow the instructions in the email to verify your email address. +email-verification-sent-title=Verification sent +email-verification-required-title=Verification required +email-verification-required-send-another=Send me another email +enabled=Enabled +enable=Enable +forgot-password=Forgot your password? Enter your login in the form below to reset your password. +forgot-password-message-sent=We have sent a message to %s containing a link that will allow you to reset your password. Once you receive the message follow the instructions to change your password. +forgot-password-message-sent-title=Message sent +forgot-password-title=Forgot password +forgot-your-password=Forgot your password? +help=Help +instructions=Instructions +id=Id +ip-address=IP address +link-to-existing-user=Link to an existing user +link-to-new-user=Create a new user +last-used=Last used +link-count-exceeded-next-step=To continue, click the button below. You will be logged out and then redirected here to link to an existing user or create a new user. +link-count-exceeded-next-step-no-registration=To continue, click the button below. You will be logged out and then redirect here to link to an existing user. +link-count-exceeded-pending-logout=You have already linked to %s and no additional links are allowed. +logged-in-as=You are logged in as %s. +login=Login +login-cancel-link=Or, cancel the link request. +login-with-passkey=Login with passkey +logout=Logout +logout-and-continue=Logout and continue\u2026 +logging-out=Logging out\u2026 +logout-title=Logging out +manage-webauthn-passkeys=Manage passkeys +method=Method +multi-factor-configuration=Two-Factor configuration +next=Next +none-selected=Select\u2026 +no-password=No password +no-webauthn-passkeys=No passkeys have been registered +no-webauthn-support=This browser does not support WebAuthn passkeys. You may still manage existing passkeys. +not-configured=Not configured +not-now=Not now +note=Note: +or=Or +parent-notified=We've sent an email to your parent. They can set up an account for you once they receive it. +parent-notified-title=Parent notified +passkeys=Passkeys +password-alpha-constraint=Must contain at least one non-alphanumeric character +password-case-constraint=Must contain both upper and lower case characters +password-change-title=Update your password +password-changed=Your password has been updated successfully. +password-changed-title=Password updated +password-constraints-intro=Password must meet the following constraints: +password-length-constraint=Must be between %s and %s characters in length +password-number-constraint=Must contain at least one number +password-previous-constraint=Must not match the previous %s passwords +passwordless-login=Passwordless login +passwordless-button-text=Login with a magic link +pending-link-info=You have successfully authenticated using %s. +pending-link-next-step=To complete this request you may link to an existing user or create a new user. +pending-link-next-step-no-registration=To complete this request you must link to an existing user. +pending-link-login-to-complete=Login to complete your link to %s. +pending-links-login-to-complete=Login to complete your link to %s and %s. +pending-device-link=Continue to complete your link to %s. +pending-device-links=Continue to complete your link to %s and %s. +pending-link-register-to-complete=Register to complete your link to %s. +pending-links-register-to-complete=Register to complete your link to %s and %s. + +phone-verification-complete=Thank you. Your phone number has been verified. +phone-verification-complete-title=Phone number verification complete +phone-verification-form=Complete the form to request a new verification message. +phone-verification-form-title=Phone number verification +phone-verification-required-title=Verification required +phone-verification-required-send-another=Send me another message +phone-verification-sent=We have sent a message to %s with your verification code. Follow the instructions in the message to verify your phone number. +phone-verification-sent-title=Verification sent + +profile=User Profile +provide-parent-email=Provide parent email +register-cancel-link=Or, cancel the link request. +registration-verification-complete=Thank you. Your registration has been verified. +registration-verification-complete-title=Registration verification complete +registration-verification-form=Complete the form to request a new verification email. +registration-verification-form-title=Registration verification +registration-verification-sent=We have sent an email to %s with your verification code. Follow the instructions in the email to verify your registration address. +registration-verification-sent-title=Verification sent +registration-verification-required-title=Verification required +registration-verification-required-send-another=Send me another email +relying-party-id=Relying party Id +return-to-login=Return to login +return-to-normal-login=Return to the normal login +return-to-webauthn-reauth=Return to passkey authentication +send-another-code=Send another code +send-code-to-phone=Send a code to your mobile phone +set-up=Set up +signature-count=Signature count +sms=SMS +sign-in-as-different-user=Sign in as a different user +start-idp-link-title=Link your account +two-factor-challenge=Authentication challenge +two-factor-challenge-options=Authentication challenge +two-factor-recovery-code=Recovery code +two-factor-recovery-codes=Recovery codes +two-factor-select-method=Didn't receive a code? Try another option +two-factor-use-one-of-n-recover-codes=Use one of your %d recovery codes +trust-computer=Trust this computer for %s days +unauthorized=Unauthorized +unauthorized-message=You are not authorized to make this request. +unauthorized-message-blocked-ip=The owner of this website (%s) has blocked your IP address. +undefined=Undefined +unnamed=Unnamed +value=Value +wait-title=Complete login on your external device +waiting=Waiting +warning=Warning +webauthn-button-text=Fingerprint, device or key +webauthn-reauth-return-to-login=If you don't recognize the passkeys(s) above click "Return to normal login" below. +webauthn-reauth-select-passkey=Welcome back, click on a passkey to continue. +allow=Allow + +# Locale Specific separators, etc +# - list separator - comma and a space +listSeparator=,\u0020 +propertySeparator=: + +# +# Success messages displayed at the top of the page. These are hard-coded in the FusionAuth code and the keys cannot be changed. You can +# still change the values though. +# +sent-code=Code successfully sent + + +# +# Labels for form fields. You can change the key names to anything you like but ensure that you don't change the name of the form fields. +# +birthDate=Birth date +code=Enter your verification or recovery code +passwordless-code=Enter your passwordless login code +email=Email +firstName=First name +fullName=Full name +lastName=Last name +loginId=Login +middleName=Middle name +mobilePhone=Mobile phone +password=Password +passwordConfirm=Confirm password +parentEmail=Parent's email +phoneNumber=Phone number +preferredLanguage=Language +preferredLanguages=Languages +register=Register +register-step=Step %d of %d +remember-device=Keep me signed in +send=Send +submit=Submit +update=Update +username=Username +userCode=Enter your user code +verify=Verify + +# +# Custom Registration forms. These must match the domain names. +# +registration.preferredLanguages=Languages +registration.timezone=Timezone +registration.username=Username +user.birthDate=Birthdate +user.email=Email +user.firstName=First name +user.fullName=Full name +user.imageUrl=Image URL +user.lastName=Last name +user.mobilePhone=Mobile phone +user.middleName=Middle name +user.password=Password +confirm.user.password=Confirm password +user.phoneNumber=Phone number +user.preferredLanguages=Languages +user.timezone=Timezone +user.username=Username + +# +# Self-service account management +# +cancel-go-back=Cancel and go back +change-password=Change password +current-password=Current password +disable-instructions=Disable two-factor +disable-two-factor=Disable two-factor +edit-profile=Edit profile +enable-instructions=Enable two-factor +enable-two-factor=Enable two-factor +go-back=Go back +send-one-time-code=Send a one-time code + +# +# Self-service two-factor configuration +# +no-two-factor-methods-configured=No methods have been configured +select-two-factor-method=Select a method +two-factor-authentication=Two-factor authentication +two-factor-method=Method +two-factor-method-authenticator=Authenticator +two-factor-method-email=Email message +two-factor-method-sms=Text message +two-factor-get-code-at-authenticator=Get a code from your authenticator app +two-factor-get-code-at-email=Get a code at %s\u2026 +two-factor-get-code-at-sms=Get a code at (***) ***-**%s + +# Form input place-holders +{placeholder}two-factor-code=Enter the one-time code + +# +# Multi-factor configuration text +# +authenticator=Authenticator app + +# Authenticator Enable / Disable +authenticator-disable-step-1=Enter the code from your authenticator app in the verification code field below to disable this two-factor method. +authenticator-enable-step-1=Open your authentication app and add your account by scanning the QR code to the right or by manually entering the Base32 encoded secret %s. +authenticator-enable-step-2=Once you have completed the first step, enter the code from your authenticator app in the verification code field below. +oauth2-authenticator-enable-step-1=Open your authentication app and scan the QR code. Then enter the code from your authenticator app in the form below. + +# Email Enable / Disable +email-disable-step-1=To disable two-factor using email, click the button to send a one-time use code to %s. Once you receive the code, enter it in the form below. +email-enable-step-1=To enable two-factor using email, enter an email address and click the button to send a one-time use code. Once you receive the code, enter it in the form below. +oauth2-email-enable-step-1=To enable two-factor using email, enter an email address and click the button to send a one-time use code. Once you receive the code, enter it in the form below. + +# SMS Enable / Disable +sms-disable-step-1=To disable two-factor using SMS, click the button to send a one-time use code to %s. Once you receive the code, enter it in the form below. +sms-enable-step-1=To enable two-factor using SMS, enter a mobile phone and click the button to send a one-time use code. Once you receive the code, enter it in the form below. +oauth2-sms-enable-step-1=To enable two-factor using SMS, enter a mobile phone and click the button to send a one-time use code. Once you receive the code, enter it in the form below. + +authenticator-configuration=Authenticator configuration +verification-code=Verification code + +manage-two-factor=Manage two-factor +go-back-to-send=Go back to send + +# +# Confirmation required +# +{description}confirmation-required-verifyEmail=To confirm you wish to verify your email address, click continue. +{description}confirmation-required-verifyPhone=To confirm you wish to verify your phone number, click continue. +{description}confirmation-required-verifyRegistration=To confirm you wish to verify your registration, click continue. +{description}confirmation-required-changePasswordMultiFactor=Because you have enabled two-factor authentication, you must first complete an authentication challenge prior to changing your password.

To confirm you wish to start a two-factor challenge, click continue. +{description}confirmation-required-passwordlessLogin=To confirm you wish to complete a passwordless login, click continue. +{description}confirmation-required-ignore=If you did not initiate this request, you can safely close the browser. +# +# Multi-factor configuration descriptions +# +{description}two-factor-authentication=Two-factor authentication adds an additional layer of security to your account by requiring more than just a password to login. Configure one or more methods to utilize during login. +{description}two-factor-methods-selection=A second step is required to complete sign in. Select one of the following methods to complete login. +{description}two-factor-recovery-code-note=If you no longer have access to the device or application to obtain a verification code, you may use a recovery code to disable this two-factor method. Warning, when you use a recovery code to disable any two-factor method, all two-factor methods will be removed and all of your recovery codes will be cleared. +{description}recovery-codes-1=Because this is the first time you have enabled two-factor, we have generated you %d recovery codes. These codes will not be shown again, so record them right now and store them in a safe place. These codes can be used to complete a two-factor login if you lose your device, and they can be used to disable two-factor authentication as well. +{description}recovery-codes-2=Once you have recorded the codes, click Done to return to two-factor management. +{description}oauth2-recovery-codes-1=Record these recovery codes, they will not be shown again. Recovery codes can be used to complete a two-factor login or disable two-factor authentication if you lose your device. +{description}oauth2-recovery-codes-2=Once you have recorded the codes, click Done to continue. + +{description}email-verification-required-change-email=Confirm your email address is correct and update it if you mis-typed it during registration. Updating your address will also send you a new email to the new address. +{description}email-verification-required=You must verify your email address before you continue. +{description}email-verification-required-non-interactive=Email verification is configured to be completed outside of this request. Once you have verified your email, retry this request. + +{description}passwordless-login-form-field=You must enter the code from your message before you continue. + +{description}phone-verification-required-change-phone=Confirm your phone number is correct and update it if you mis-typed it during registration. Updating your phone number will also send you a new message to the new number. +{description}phone-verification-required=You must verify your phone number before you continue. +{description}phone-verification-required-non-interactive=Phone number verification is configured to be completed outside of this request. Once you have verified your phone number, retry this request. + +{description}registration-verification-required=You must verify your registration before you continue. +{description}registration-verification-required-non-interactive=Registration verification is configured to be completed outside of this request. Once you have verified your registration, retry this request. + +# WebAuthn +{description}add-webauthn=Enter a name for this passkey. This name may be used to identify the passkey during a login attempt, or when multiple passkeys exist. +{description}delete-webauthn-passkey=Click delete to remove the passkey. Once removed, you will no longer be able to use this passkey to complete authentication. +{description}webauthn-bootstrap-retrieve-credential=Retrieve your previously configured passkeys by entering your login. +{description}webauthn-passkeys=Passkeys allow you to securely authenticate without a password. Configure one or more passkeys in order to complete authentication. +{description}webauthn-reauth=Do you want to skip the password next time? +{description}webauthn-reauth-existing-credential=You can select an existing passkey from the list below and skip the password on your next login. +{description}webauthn-reauth-add-credential=Register a new passkey. Enter a display name to uniquely identify this key. For example, "Chrome Touch ID". + +# +# Custom Self-service User form sections. +# +# - Names are optional, and if not provided they will be labeled 'Section 1', 'Section 2', etc. +# - The first section label will be omitted unless you specify a named label below. For your convenience, these +# sections are configured below and commented out as 'Optionally name me!'. +# +# - By default, all section labels will be used for all tenants and all applications that are using this theme. +# +# - If you want a section title that is specific to a tenant in a user form, you may optionally prefix the key with the Tenant Id. +# +# For example, if the tenant Id is equal to: cbeaf8fe-f4a7-4a27-9f77-c609f1b01856 +# +# [cbeaf8fe-f4a7-4a27-9f77-c609f1b01856]{self-service-form}2=Tenant specific label for section 2 +# + +# {self-service-form}1=Optionally name me! +# {self-service-form}2= + +# +# Custom Admin User and Registration form sections. +# +# - Names are optional, and if not provided they will be labeled 'Section 1', 'Section 2', etc. +# - The first section label on the User and Registration form in the admin UI will be omitted unless +# you specify a named label below. For your convenience, these sections are configured below and commented out as 'Optionally name me!'. +# +# - By default, all section labels will be used for all tenants, and all applications respectively. +# +# - If you want a section title that is specific to a tenant in a user form, you may optionally prefix the key with the Tenant Id. +# +# For example, if the tenant Id is equal to: cbeaf8fe-f4a7-4a27-9f77-c609f1b01856 +# +# [cbeaf8fe-f4a7-4a27-9f77-c609f1b01856]{user-form-section}2=Tenant specific label for section 2 +# +# - If you want a section title that is specific to an Application in a registration form, you may optionally prefix the key with the Application Id. +# +# For example, if the application Id is equal to: de2f91c7-c27a-4ad6-8be2-cfb36996cc89 +# +# [de2f91c7-c27a-4ad6-8be2-cfb36996cc89]{registration-form-section}2=Application specific label for section 2 + +# {user-form-section}1=Optionally name me! +{user-form-section}2=Options + +# {registration-form-section}1=Optionally name me! +{registration-form-section}2=Options + +# +# Custom OAuth Consent Prompt options +# +# - The consent messaging and detail provided on the consent prompt page for a given scope can be overridden +# +# - By default, the consent message/detail being overridden will apply to all scopes with that name +# +# For example, when given a scope name of data:write +# +# {scope-message}data\:write:Access to write data +# {scope-detail}data\:write:By approving this scope, you are allowing the requesting application to write data +# +# - Consent message/detail overrides can be applied at the tenant or application level as well +# +# Tenant level, if the tenant Id is equal to cbeaf8fe-f4a7-4a27-9f77-c609f1b01856: +# +# [{tenant}cbeaf8fe-f4a7-4a27-9f77-c609f1b01856]{scope-message}data\:write=Access to write data +# [{tenant}cbeaf8fe-f4a7-4a27-9f77-c609f1b01856]{scope-detail}data\:write=By approving this scope, you are allowing the requesting application to write data +# +# Application level, if the application Id is equal to de2f91c7-c27a-4ad6-8be2-cfb36996cc89: +# +# [{application}de2f91c7-c27a-4ad6-8be2-cfb36996cc89]{scope-message}data\:write=Access to write data +# [{application}de2f91c7-c27a-4ad6-8be2-cfb36996cc89]{scope-detail}data\:write=By approving this scope, you are allowing the requesting application to write data +# +# +# NOTE: Colons found in a scope name will need to be escaped with backslash (e.g. data\:write) + +# Default consent messaging for OpenID Connect Scopes +{scope-message}address=Access your street address +{scope-message}email=Access your email address +{scope-message}phone=Access your phone number +{scope-message}profile=Access details about your profile + +scope-consent-optional=One or more of the requests are optional and can be deselected before allowing the application to proceed. +scope-consent-agreement=Click Allow to grant the selected requests to %s, or Cancel to deny this request. + +# +# Custom Admin User and Registration tooltips +# +{tooltip}registration.preferredLanguages=Select one or more preferred languages +{tooltip}user.preferredLanguages=Select one or more preferred languages + +# +# Custom Registration form validation errors. +# +[confirm]user.password=Confirm password + +# +# Self-service account validation errors +# +[invalid]currentPassword=Current password is incorrect + +# +# Default validation errors. Add custom messages by adding field messages. +# For example, to provide a custom message for a string field named user.data.companyName, add the +# following message key: [blank]user.data.companyName=Company name is required +# +[blank]=Required +[blocked]=Not allowed +[confirm]=Confirm +[configured]=Already configured +[couldNotConvert]=Invalid +[doNotMatch]=Values do not match +[duplicate]=Already exists +[empty]=Required +[inUse]=In use +[invalid]=Invalid +[invalidPhone]=Invalid +[missing]=Required +[mismatch]=Unexpected value +[notEmail]=Invalid email +[notConfigured]=Not configured +[previouslyUsed]=Previously used +[tooLong]=Too long +[tooMany]=Too many +[tooShort]=Too short +[type]=Invalid type + +# +# Tooltips. You can change the key names and values to anything you like. +# +{tooltip}remember-device=Check this to stay signed into FusionAuth for the configured duration, do not select this on a public computer or when this device is shared with multiple users +{tooltip}trustComputer=Check this to bypass two-factor authentication for the configured duration, do not select this on a public computer or when this device is shared with multiple users + + +# +# Validation errors when forms are invalid. The format is []. These are hard-coded in the FusionAuth code and the +# keys cannot be changed. You can still change the values though. +# +[invalid]applicationId=The provided application Id is invalid. +[blank]code=Required +[invalid]code=Invalid code +[blank]email=Required +[duplicate]email=An account already exists for that email +[blank]loginId=Required +[blank]methodId=Select a two-factor method +[blank]oneTimeCode=Required +[invalid]oneTimeCode=Invalid code +[blank]parentEmail=Required +[blank]password=Required +[blank]user_code=Required +[blank]captcha_token=Required +[invalid]captcha_token=Invalid challenge, try again +[cannotSend]method=A message cannot be sent to an authenticator +[disabled]method=Not enabled +[invalid]user_code=Invalid user code +[notEqual]password=Passwords don't match +[onlyAlpha]password=Password requires a non-alphanumeric character +[previouslyUsed]password=Password has been recently used +[requireNumber]password=Password requires at least one number +[singleCase]password=Password requires upper and lower case characters +[tooYoung]password=Password was changed too recently, try again later +[tooShort]password=Password does not meet the minimum length requirement +[tooLong]password=Password exceeds the maximum length requirement +[blank]passwordConfirm=Required +[missing]user.birthDate=Required +[couldNotConvert]user.birthDate=Invalid +[blank]user.email=Required +[blocked]user.email=Email address not allowed +[notEmail]user.email=Invalid email +[duplicate]user.email=An account already exists for that email +[inactive]user.email=An account already exists for that email but is locked. Contact the administrator for assistance +[blank]user.firstName=Required +[blank]user.fullName=Required +[blank]user.lastName=Required +[blank]user.middleName=Required +[blank]user.mobilePhone=Required +[invalid]user.mobilePhone=Invalid +[blank]user.parentEmail=Required +[blank]user.password=Required +[doNotMatch]user.password=Passwords don't match +[singleCase]user.password=Password must use upper and lowercase characters +[onlyAlpha]user.password=Password must contain a punctuation character +[previouslyUsed]user.password=Password has been recently used +[requireNumber]user.password=Password must contain a number character +[tooShort]user.password=Password does not meet the minimum length requirement +[tooLong]user.password=Password exceeds the maximum length requirement +[tooYoung]user.password=Password was changed too recently, try again later + +[blank]user.phoneNumber=Required +[duplicate]user.phoneNumber=An account already exists for that phone number +[invalidPhone]user.phoneNumber=Invalid +[blank]phoneNumber=Required +[duplicate]phoneNumber=An account already exists for that phone number +[invalidPhone]phoneNumber=Invalid + +[blank]user.username=Required +[duplicate]user.username=An account already exists for that username +[inactive]user.username=An account already exists for that username but is locked. Contact the administrator for assistance +[mismatch]email=The requested email does not match where the code was sent +[mismatch]mobilePhone=The requested phone number does not match where the code was sent +[moderationRejected]registration.username=That username is not allowed. Please select a new one +[moderationRejected]user.username=That username is not allowed. Please select a new one + +# +# Breached password messages +# +# - ExactMatch The password and email or username combination was found in a breached data set. +# - SubAddressMatch The password and email or username, or email sub-address was found in a breached data set. +# - PasswordOnly The password was found in a breached data set. +# - CommonPassword The password is one of the most commonly known breached passwords. +# +[breachedExactMatch]password=This password was found in the list of vulnerable passwords, and is no longer secure. Select a different password. +[breachedExactMatch]user.password=This password was found in the list of vulnerable passwords, and is no longer secure. Select a different password. +[breachedSubAddressMatch]password=This password was found in the list of vulnerable passwords, and is no longer secure. Select a different password. +[breachedSubAddressMatch]user.password=This password was found in the list of vulnerable passwords, and is no longer secure. Select a different password. +[breachedPasswordOnly]password=This password was found in the list of vulnerable passwords, and is no longer secure. Select a different password. +[breachedPasswordOnly]user.password=This password was found in the list of vulnerable passwords, and is no longer secure. Select a different password. +[breachedCommonPassword]password=This password is a commonly known vulnerable password. Select a more secure password. +[breachedCommonPassword]user.password=This password is a commonly known vulnerable password. Select a more secure password. + +# +# Error messages displayed at the top of the page. These are always inside square brackets. These are hard-coded in the FusionAuth code and +# the keys cannot be changed. You can still change the values though. +# +[APIError]=An unexpected error occurred. +[AdditionalFieldsRequired]=Additional fields are required to complete your registration. +[EmailVerificationEmailUpdated]=Your email address has been updated and another email is on the way. +[EmailVerificationSent]=A verification email is on the way. +[EmailVerificationDisabled]=Email verification functionality is currently disabled. Contact your FusionAuth administrator for assistance. +[ErrorException]=An unexpected error occurred. +[ExternalAuthenticationExpired]=Your external authentication request has expired, please re-attempt authentication. +[ForgotPasswordDisabled]=Forgot password handling is not enabled. Please contact your system administrator for assistance. +[IdentityProviderDoesNotSupportRedirect]=This identity provider does not support this redirect workflow. +[InvalidChangePasswordId]=Your password reset code has expired or is invalid. Please retry your request. +[InvalidConfirmation]=Invalid request. This request requires user confirmation. +[InvalidEmail]=FusionAuth was unable to find a user with that email address. +[InvalidIdentityProviderId]=Invalid request. Unable to handle the identity provider login. Please contact your system administrator or support for assistance. +[InvalidLogin]=Invalid login credentials. +[InvalidPasswordlessLoginId]=Your link has expired or is invalid. Please retry your request. +[InvalidVerificationId]=Sorry. The request contains an invalid or expired verification Id. You may need to request another verification to be sent. +[InvalidPendingIdPLinkId]=Your link has expired or is invalid. Please retry your login request. +[InvalidWebAuthnAuthenticatorResponse]=The response from the WebAuthn authenticator could not be parsed or failed validation. +[InvalidWebAuthnBrowserResponse]=The WebAuthn response from the browser could not be parsed or failed validation. +[InvalidWebAuthnLoginId]=Your signature has expired or is invalid. Please retry your request. +[LinkCountExceeded]=You have reached the configured link limit of %d for this identity provider. +[LoginPreventedException]=Your account has been locked. +[LoginPreventedExceptionTooManyTwoFactorAttempts]=You have exceeded the number of allowed attempts. Your account has been locked. +[MissingApplicationId]=An applicationId is required and is missing from the request. +[MissingChangePasswordId]=A changePasswordId is required and is missing from the request. +[MissingEmail]=Your email address is required and is missing from the request. +[MissingEmailAddressException]=You must have an email address to utilize passwordless login. +[MissingPendingIdPLinkId]=You must first log into a 3rd party identity provider to complete an account link. +[MissingPKCECodeVerifier]=The code_verifier could not be determined, this request likely did not originate from FusionAuth. Unable to complete this login request. +[MissingVerificationId]=A verification Id was not sent in the request. +[NotFoundException]=The requested OAuth configuration is invalid. +[OAuthv1TokenMismatch]=Invalid request. The token provided on the OAuth v1 callback did not match the one sent during authorization. Unable to handle the identity provider login. Please contact your system administrator or support for assistance. +[Oauthv2Error]=An invalid request was made to the Authorize endpoint. %s +[PasswordlessRequestSent]=A message is on the way. +[PasswordChangeRequired]=You must change your password in order to continue. +[PasswordChangeReasonExpired]=Your password has expired and must be changed. +[PasswordChangeReasonBreached]=Your password was found in the list of vulnerable passwords and must be changed. +[PasswordChangeReasonValidation]=Your password does not meet password validation rules and must be changed. +[PasswordlessDisabled]=Passwordless login is not currently configured. +[PhoneVerificationDisabled]=Phone number verification functionality is currently disabled. Contact your FusionAuth administrator for assistance. +[PhoneVerificationPhoneNumberUpdated]=Your phone number has been updated and another message is on the way. +[PhoneVerificationSent]=A verification message is on the way. +[PushTwoFactorFailed]=Failed to send a verification code using the configured push service. +[RegistrationVerificationSent]=A verification email is on the way. +[SSOSessionDeletedOrExpired]=You have been logged out of FusionAuth. +[TenantIdRequired]=FusionAuth is unable to determine which tenant to use for this request. Please add the tenantId to the URL as a request parameter. +[TwoFactorEnableFailed]=Oops. Something didn't go as planned. Try to complete login again. +[TwoFactorRequired]=You must configure two-factor in order to continue. +[TwoFactorTimeout]=You did not complete the two-factor challenge in time. Please restart your request. +[UserAuthorizedNotRegisteredException]=Your account has not been registered for this application. +[UserExpiredException]=Your account has expired. Please contact your system administrator. +[UserLockedException]=Your account has been locked. Please contact your system administrator. +[UserUnauthenticated]=Oops. It looks like you've gotten here by accident. Please return to your application and log in to begin the authorization sequence. +[WebAuthnDisabled]=WebAuthn is not currently enabled. +[WebAuthnCredentialSelectionCanceled]=Passkey selection canceled. +[WebAuthnFailed]=Unable to complete the WebAuthn workflow. + +# External authentication errors +# - Some of these errors are development time issues. But it is possible they could be shown to an end user depending upon your configuration. +[ExternalAuthenticationException]AppleIdToken=The id_token returned from Apple is invalid or cannot be verified. Unable to complete this login request. +[ExternalAuthenticationException]AppleTokenEndpoint=A request to the Apple Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]AppleUserObject=Failed to read the user details provided by Apple. Unable to complete this login request. +[ExternalAuthenticationException]EpicGamesAccount=A request to the Epic Games Account API has failed. Unable to complete this login request. +[ExternalAuthenticationException]EpicGamesToken=A request to the Epic Games Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]ExistingUserAlreadyLinked=This account is already linked to another user. Unable to complete this login request. +[ExternalAuthenticationException]FacebookAccessToken=A request to the Facebook Access Token Info API has failed. Unable to complete this login request. +[ExternalAuthenticationException]FacebookMe=A request to the Facebook Me API has failed. Unable to complete this login request. +[ExternalAuthenticationException]FacebookMePicture=A request to the Facebook Picture API has failed. Unable to complete this login request. +[ExternalAuthenticationException]GoogleToken=A request to the Google Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]GoogleTokenInfo=A request to the Google Token Info API has failed. Unable to complete this login request. +[ExternalAuthenticationException]InvalidApplication=The requested application does not exist or is currently disabled. Unable to complete this login request. +[ExternalAuthenticationException]InvalidIdentityProviderId=The requested identityProviderId is invalid. Unable to complete this login request. +[ExternalAuthenticationException]LinkedInEmail=A request to the LinkedIn Email API has failed. Unable to complete this login request. +[ExternalAuthenticationException]LinkedInMe=A request to the LinkedIn Me API has failed. Unable to complete this login request. +[ExternalAuthenticationException]LinkedInToken=A request to the LinkedIn Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]LinkedInUserInfo=A request to the LinkedIn User Info API has failed. Unable to complete this login request. +[ExternalAuthenticationException]MissingEmail=An email address was not provided for the user. This account cannot be used to log in, unable to complete this login request. +[ExternalAuthenticationException]MissingUniqueId=A unique identifier was not provided for the user. This account cannot be used to log in, unable to complete this login request. +[ExternalAuthenticationException]MissingUser=An authentication request cannot be completed because the user that started the request no longer exists. This account cannot be used to log in, unable to complete this login request. +[ExternalAuthenticationException]MissingUsername=A username was not returned by the identity provider. This account cannot be used to log in, unable to complete this login request. +[ExternalAuthenticationException]NintendoToken=A request to the Nintendo Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]OpenIDConnectToken=A request to the OpenID Connect Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]OpenIDConnectUserinfo=A request to the OpenID Connect Userinfo API has failed. Unable to complete this login request. +[ExternalAuthenticationException]SAMLIdPInitiatedIssuerVerificationFailed=The SAML issuer failed validation. Unable to complete this login request. +[ExternalAuthenticationException]SAMLIdPInitiatedResponseSolicited=The SAML AuthNResponse contained an InResponseTo attribute. In an IdP Initiated Login this is un-expected. +[ExternalAuthenticationException]SAMLResponse=The SAML AuthnResponse object could not be parsed or verified. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseAudienceNotBeforeVerificationFailed=The SAML audience is not yet available to be confirmed. Unable to complete this request. +[ExternalAuthenticationException]SAMLResponseAudienceNotOnOrAfterVerificationFailed=The SAML audience is no longer eligible to be confirmed. Unable to complete this request. +[ExternalAuthenticationException]SAMLResponseAudienceVerificationFailed=The SAML audience failed validation. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseDestinationVerificationFailed=The SAML destination failed validation. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseMismatchedAssertions=The SAML AuthnResponse object contained multiple Assertions that were incompatible. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseMissingAssertion=The SAML AuthnResponse object did not contain any Assertions. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseStatus=The SAML AuthnResponse status indicated the request has failed. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseSubjectNoOnOrAfterVerificationFailed=The SAML subject is no longer eligible to be confirmed. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseSubjectNotBeforeVerificationFailed=The SAML subject is not yet available to be confirmed. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseUnexpectedOrReplayed=The SAML response has not been requested or has already been processed. Unable to complete this login request. +[ExternalAuthenticationException]SAMLResponseUnsolicited=The SAML response was unsolicited. Unable to complete this login request. +[ExternalAuthenticationException]SonyPSNToken=A request to the Sony PlayStation Network Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]SonyPSNUserInfo=A request to the Sony PlayStation Network User Info API has failed. Unable to complete this login request. +[ExternalAuthenticationException]SteamPlayerSummary=A request to the Steam Player summary API has failed. Unable to complete this login request. +[ExternalAuthenticationException]SteamAuthenticateUserTicket=A request to the Steam Authenticate User Ticket API has failed. Unable to complete this login request. +[ExternalAuthenticationException]SteamToken=A request to the Steam Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]TwitchToken=A request to the Twitch Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]TwitchUserInfo=A request to the Twitch User Info API has failed. Unable to complete this login request. +[ExternalAuthenticationException]TwitterAccessToken=A request to the Twitter Access Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]TwitterCallbackUnconfirmed=The Twitter callback URL has not been confirmed. Unable to complete this login request. +[ExternalAuthenticationException]TwitterRequestToken=A request to the Twitter Request Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]TwitterVerifyCredentials=A request to Twitter Verify Credentials API has failed. Unable to complete this login request. +[ExternalAuthenticationException]UserDoesNotExistByEmail=You must first create a user with the same email address in order to complete this login request. +[ExternalAuthenticationException]UserDoesNotExistByUsername=You must first create a user with the same username in order to complete this login request. +[ExternalAuthenticationException]XboxSecurityTokenService=A request to the Xbox Security Token Service API has failed. Unable to complete this login request. +[ExternalAuthenticationException]XboxToken=A request to the Xbox Token API has failed. Unable to complete this login request. +[ExternalAuthenticationException]XboxUserInfo=A request to the Xbox User Info API has failed. Unable to complete this login request. +[ExternalAuthenticationException]MissingFederatedCSRFToken=The request origin could not be verified. Unable to complete this login request. +[ExternalAuthenticationException]InvalidFederatedCSRFToken=The request origin could not be verified. Unable to complete this login request. +[ExternalAuthenticationException]UnverifiedEmail=The provided email address has not yet been verified. This account cannot be used to log in, unable to complete this login request. + +# OAuth token endpoint and callback errors +[TokenExchangeFailed]=An unexpected error occurred while completing your login attempt. Please attempt the request again. +[TokenExchangeException]=We were unable to complete your login attempt. Please attempt the request again. + +# Webhook transaction failure +[WebhookTransactionException]=One or more webhooks returned an invalid response or were unreachable. Based on your transaction configuration, your action cannot be completed. + +# Self-service +[SelfServiceCustomValidationException]=Extended verification has failed. Self-service registration cannot be completed. +[SelfServiceFormNotConfigured]=Configuration is incomplete. The FusionAuth administrator must configure a form for this application. +[SelfServiceUserNotRegisteredException]=You are not registered for this application. Not all features will be available. +[TwoFactorAuthenticationMethodDisabled]=Two-factor authentication has been disabled +[TwoFactorAuthenticationMethodEnabled]=Two-factor authentication has been enabled +[TwoFactorSendFailed]=A request to send a one-time code for two-factor configuration code has failed. +[TwoFactorMessageSent]=A one-time use code was sent + +# General messages +[UserWillBeLoggedIn]=You will be logged in after you complete this request. + +[TrustTokenExpired]=Your trust expired, please retry. +[TrustTokenRequired]=Please complete this step-up authentication request to complete this request. +[TrustTokenRequiredToChangePassword]=Please complete this challenge prior to changing your password. + + +[InvalidOrMissingCSRFToken]=You are not authorized to make this request. Ensure you complete this form in a browser. +[RateLimitedException]=Your request has been rate limited. Please wait a few minutes before making another request. + +[MessengerError]=An error occurred while trying to send the message. Please contact your system administrator. + +# 1.62.0 messages +verificationCode=Verification code +user.parentEmail=Parent's email +{description}email-verification-required-non-interactive-registration=Email verification is required to register. Check your inbox for the verification email and follow the instructions. +{description}phone-verification-required-non-interactive-registration=Phone number verification is required to register. Check your device for the verification message and follow the instructions. +{description}-registration-ready=Ready to complete your registration. Click the Register button below. +[VerificationTimeout]=You did not complete the registration process in time. Please restart your request. diff --git a/kickstart/templates/emailComplete.ftl b/kickstart/templates/emailComplete.ftl new file mode 100644 index 0000000..9663e00 --- /dev/null +++ b/kickstart/templates/emailComplete.ftl @@ -0,0 +1,27 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("email-verification-complete-title")] +

+ ${theme.message("email-verification-complete")} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/emailSend.ftl b/kickstart/templates/emailSend.ftl new file mode 100644 index 0000000..d01dff9 --- /dev/null +++ b/kickstart/templates/emailSend.ftl @@ -0,0 +1,29 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="email" type="java.lang.String" --] +[#-- @ftlvariable name="emailSent" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("email-verification-sent-title")] +

+ ${theme.message("email-verification-sent", email)} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/emailSent.ftl b/kickstart/templates/emailSent.ftl new file mode 100644 index 0000000..d01dff9 --- /dev/null +++ b/kickstart/templates/emailSent.ftl @@ -0,0 +1,29 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="email" type="java.lang.String" --] +[#-- @ftlvariable name="emailSent" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("email-verification-sent-title")] +

+ ${theme.message("email-verification-sent", email)} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/emailVerificationRequired.ftl b/kickstart/templates/emailVerificationRequired.ftl new file mode 100644 index 0000000..0ac78c7 --- /dev/null +++ b/kickstart/templates/emailVerificationRequired.ftl @@ -0,0 +1,94 @@ +[#ftl/] +[#-- @ftlvariable name="allowEmailChange" type="boolean" --] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="collectVerificationCode" type="boolean" --] +[#-- @ftlvariable name="email" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="verificationId" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("email-verification-required-title")] + [#-- The user does not have a verified email. Add optional messaging here with instruction to the user. --] + + [#-- Let the user know why they ended up here --] +

+ ${theme.message("{description}email-verification-required")} +

+ + [#-- If configured, collect the verification code on this form, this means the user sits here until they verify their email. --] + [#if collectVerificationCode] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="verify"/] + [@helpers.hidden name="allowEmailChange"/] + [@helpers.hidden name="collectVerificationCode"/] + [@helpers.hidden name="email"/] + [@helpers.hidden name="verificationId"/] +
+ [@helpers.input type="text" name="oneTimeCode" id="otp" autocapitalize="none" autofocus=true autocomplete="one-time-code" autocorrect="off" placeholder="${theme.message('code')}" leftAddon="lock"/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+
+ [@helpers.button text=theme.message("submit")/] +
+
+ [#else] +

${theme.message("{description}email-verification-required-non-interactive")}

+ [/#if] + + [#-- Resend a verification email --] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="resend"/] + [@helpers.hidden name="allowEmailChange"/] + [@helpers.hidden name="collectVerificationCode"/] + [@helpers.hidden name="email"/] +
+ +
+
+ + [#-- If configured to allow an email change, present the user with a form. This is intended to assist the user if they mis-typed their email address previously. --] + [#if allowEmailChange] +
+
+
${theme.message("or")}
+
+
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="changeEmail"/] + [@helpers.hidden name="allowEmailChange"/] + [@helpers.hidden name="collectVerificationCode"/] +

+ ${theme.message("{description}email-verification-required-change-email")} +

+
+ [@helpers.input type="text" name="email" id="email" autocapitalize="none" autocomplete="on" autocorrect="off" placeholder="${theme.message('email')}" leftAddon="user"/] +
+
+ [@helpers.button text=theme.message("submit")/] +
+
+ [/#if] + + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/emailVerify.ftl b/kickstart/templates/emailVerify.ftl new file mode 100644 index 0000000..94b8077 --- /dev/null +++ b/kickstart/templates/emailVerify.ftl @@ -0,0 +1,42 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="verificationId" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("email-verification-form-title")] + [#-- FusionAuth automatically handles errors that occur during email verification and outputs them in the HTML --] +
+ [@helpers.hidden name="captcha_token"/] + [@helpers.hidden name="client_id"/] + [@helpers.hidden name="tenantId"/] +

+ ${theme.message("email-verification-form")} +

+
+ [@helpers.input type="text" name="email" id="email" autocapitalize="none" autofocus=true autocomplete="on" autocorrect="off" placeholder="${theme.message('email')}" leftAddon="user"/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+
+ [@helpers.button text=theme.message("submit")/] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/helpers.ftl b/kickstart/templates/helpers.ftl new file mode 100644 index 0000000..68ad945 --- /dev/null +++ b/kickstart/templates/helpers.ftl @@ -0,0 +1,1344 @@ +[#ftl/] +[#setting url_escaping_charset="UTF-8"] +[#-- Below are the main blocks for all of the themeable pages --] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="bypassTheme" type="boolean" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="code_challenge" type="java.lang.String" --] +[#-- @ftlvariable name="code_challenge_method" type="java.lang.String" --] +[#-- @ftlvariable name="consents" type="java.util.Map>" --] +[#-- @ftlvariable name="editPasswordOption" type="java.lang.String" --] +[#-- @ftlvariable name="locale" type="java.util.Locale" --] +[#-- @ftlvariable name="loginTheme" type="io.fusionauth.domain.Theme.Templates" --] +[#-- @ftlvariable name="max_age" type="java.lang.Long" --] +[#-- @ftlvariable name="metaData" type="io.fusionauth.domain.jwt.RefreshToken.MetaData" --] +[#-- @ftlvariable name="nonce" type="java.lang.String" --] +[#-- @ftlvariable name="passwordValidationRules" type="io.fusionauth.domain.PasswordValidationRules" --] +[#-- @ftlvariable name="pendingIdPLinkId" type="java.lang.String" --] +[#-- @ftlvariable name="prompt" type="java.lang.String" --] +[#-- @ftlvariable name="redirect_uri" type="java.lang.String" --] +[#-- @ftlvariable name="response_mode" type="java.lang.String" --] +[#-- @ftlvariable name="response_type" type="java.lang.String" --] +[#-- @ftlvariable name="scope" type="java.lang.String" --] +[#-- @ftlvariable name="state" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="theme" type="io.fusionauth.domain.Theme" --] +[#-- @ftlvariable name="timezone" type="java.lang.String" --] +[#-- @ftlvariable name="user_code" type="java.lang.String" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] + +[#macro html] + + + [#nested/] + +[/#macro] + +[#macro head title="Login | FusionAuth" author="FusionAuth" description="User Management Redefined. A Single Sign-On solution for your entire enterprise."] + + ${title} + + + + + + + + [#-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy --] + + + [#-- Browser Address bar color --] + + + [#-- Begin Favicon Madness + You can check if this is working using this site https://realfavicongenerator.net/ + Questions about icon names and sizes? https://realfavicongenerator.net/faq#.XrBnPJNKg3g --] + + [#-- Apple & iOS --] + + + + + + + + + + + [#-- Android Icons --] + + + [#-- IE 11+ configuration --] + + + [#-- Windows 8 Compatible --] + + + + [#-- Standard Favicon Fare --] + + + + + + [#-- End Favicon Madness --] + + + + [#if theme.type == "simple"] + + [/#if] + + [#-- Theme Stylesheet, only Authorize defines this boolean. + Using the ?no_esc on the stylesheet to allow selectors that contain a > symbols. + Once insde of a style tag we are safe and the stylesheet is validated not to contain an end style tag --] + [#if !(bypassTheme!false)] + + [/#if] + + + + + + + [#-- The nested, page-specific head HTML goes here --] + [#nested/] + + +[/#macro] + +[#macro body] + +
+ [#nested/] +
+ +[/#macro] + +[#macro header] + [#if theme.type != 'simple' || request.requestURI == "/" || request.requestURI?starts_with("/account")] +
+
+ +
+
+ [/#if] + + [#nested/] +[/#macro] + +[#macro alternativeLoginsScript clientId identityProviders] + [#if identityProviders["EpicGames"]?has_content || identityProviders["Facebook"]?has_content || identityProviders["Google"]?has_content || + identityProviders["LinkedIn"]?has_content || identityProviders["Nintendo"]?has_content || identityProviders["OpenIDConnect"]?has_content || + identityProviders["SAMLv2"]?has_content || identityProviders["SonyPSN"]?has_content || identityProviders["Steam"]?has_content || + identityProviders["Twitch"]?has_content || identityProviders["Xbox"]?has_content || identityProviders["Apple"]?has_content || + identityProviders["Twitter"]?has_content] + [#-- Include Helper.js instead of loading dynamically from other IdP JS. IdP JS files will still load the script if it has not already been loaded --] + + [/#if] + [#if identityProviders["Apple"]?has_content] + + + [/#if] + [#if identityProviders["Facebook"]?has_content] + + + [/#if] + [#if identityProviders["Google"]?has_content] + [#list identityProviders["Google"] as idp] + [#if idp.lookupLoginMethod(clientId) != "UseRedirect"] + [#-- Only one Google IdP can use the GSI APIs on a page. Assign the IdP for later use and load scripts. --] + [#assign gsiIdentityProvider = idp/] + + + [#break] + [/#if] + [/#list] + [/#if] + [#if identityProviders["Twitter"]?has_content] + + [/#if] + [#if identityProviders["EpicGames"]?has_content || identityProviders["Facebook"]?has_content || identityProviders["Google"]?has_content || + identityProviders["LinkedIn"]?has_content || identityProviders["Nintendo"]?has_content || identityProviders["OpenIDConnect"]?has_content || + identityProviders["SAMLv2"]?has_content || identityProviders["SonyPSN"]?has_content || identityProviders["Steam"]?has_content || + identityProviders["Twitch"]?has_content || identityProviders["Xbox"]?has_content] + + [/#if] +[/#macro] + +[#macro main title="Login" rowClass="row center-xs" colClass="col-xs col-sm-8 col-md-6 col-lg-5 col-xl-4"] +
+ [@printErrorAlerts rowClass colClass/] + [@printInfoAlerts rowClass colClass/] +
+
+
+
+ +
+ [#if title?has_content] +

${title}

+ [/#if] +
+ [#nested/] +
+
+
+
+
+
+ [@localSelector/] +
+
+
+[/#macro] + +[#macro accountMain rowClass="row center-xs" colClass="col-xs col-sm-8 col-md-6 col-lg-5 col-xl-4" actionURL="" actionText="Go back" actionDirection="back"] +
+ [@printErrorAlerts rowClass colClass/] + [@printInfoAlerts rowClass colClass/] +
+
+ [#nested/] +
+
+ [@accountFooter rowClass "col-xs-6 col-sm-6 col-md-5 col-lg-4" actionURL actionText actionDirection/] +
+[/#macro] + +[#macro localSelector] + +[/#macro] + +[#macro accountFooter rowClass colClass actionURL actionText actionDirection] +
+
+ [@localSelector/] +
+
+ + [#-- actionURL and actionText may be an array. For backwards compatibility, allow a string + or an array. If not an array yet, convert to one now. --] + [#if !actionURL?is_sequence] + [#local actionURLs = [actionURL]/] + [#else] + [#local actionURLs = actionURL/] + [/#if] + + [#if !actionText?is_sequence] + [#local actionTexts = [actionText]/] + [#else] + [#local actionTexts = actionText/] + [/#if] + + [#list actionURLs as url] + [#local actionURL = url/] + [#if actionURL?has_content] + [#if !actionURL?contains("client_id")] + [#if actionURL?contains("?")] + [#local actionURL = actionURL + "&client_id=${client_id}"/] + [#else] + [#local actionURL = actionURL + "?client_id=${client_id}"/] + [/#if] + [/#if] + [#if !actionURL?contains("tenantId")] + [#if actionURL?contains("?")] + [#local actionURL = actionURL + "&tenantId=${tenantId}"/] + [#else] + [#local actionURL = actionURL + "?tenantId=${tenantId}"/] + [/#if] + [/#if] + [#if actionDirection == "back"] + ${actionTexts[url_index]} + [#else] + ${actionTexts[url_index]} + [/#if] + [#sep]
[/#sep] + [/#if] + [/#list] +
+
+[/#macro] + +[#macro accountPanelFull title=""] +
+ [#if title?has_content] +

${title}

+ [/#if] +
+ [#nested/] +
+
+[/#macro] + +[#macro accountPanel title tenant user action showEdit] +
+ [#if title?has_content] +

${title}

+ [/#if] +
+
+ [#-- Column 1 --] +
+
+
+ [#if user.imageUrl??] + profile image + [#elseif user.lookupEmail()??] + profile image + [#else] + profile image + [/#if] +
+
${display(user, "name")}
+
+
+ [#-- Column 2 --] +
+ [#nested/] +
+ [#if action == "view"] +
+
+ [#if showEdit] + + + + + + [/#if] +
+
+ [/#if] +
+
+
+[/#macro] + +[#macro footer] + [#nested/] + +[#-- Powered by FusionAuth branding. This backlink helps FusionAuth web ranking so more + people can find us! However, we always want to give the developer choice, remove this if you like. --] + +[/#macro] + +[#-- Below are the social login buttons and helpers --] +[#macro appleButton identityProvider clientId] +[#-- https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/ --] + +[/#macro] + +[#macro epicButton identityProvider clientId] + +[/#macro] + +[#macro facebookButton identityProvider clientId] + +[/#macro] + +[#macro googleButton identityProvider clientId idpRedirectState=""] + [#-- When using this loginMethod - the Google JavaScript API is not used at all. --] + [#if identityProvider.lookupLoginMethod(clientId) == "UseRedirect"] + + [/#if] +[/#macro] + +[#macro googleGsiButton identityProvider clientId idpRedirectState=""] + [#-- UsePopup or UseVendorJavaScript --] + [#-- + Use the Google Identity Service (GIS) API. + https://developers.google.com/identity/gsi/web/reference/html-reference + --] +
+
+ [#-- This the Google Signin button. If only using One tap, you can delete or comment out this element --] + +[/#macro] + +[#macro linkedInButton identityProvider clientId] + +[/#macro] + +[#macro nintendoButton identityProvider clientId] + +[/#macro] + +[#macro twitterButton identityProvider clientId] + +[/#macro] + +[#macro openIDConnectButton identityProvider clientId] + +[/#macro] + +[#macro samlv2Button identityProvider clientId] + +[/#macro] + +[#macro sonypsnButton identityProvider clientId] + +[/#macro] + +[#macro steamButton identityProvider clientId] + +[/#macro] + +[#macro twitchButton identityProvider clientId] + +[/#macro] + +[#macro xboxButton identityProvider clientId] + +[/#macro] + +[#macro alternativeLogins clientId identityProviders passwordlessEnabled bootstrapWebauthnEnabled=false idpRedirectState="" federatedCSRFToken=""] + [#if identityProviders?has_content || passwordlessEnabled || bootstrapWebauthnEnabled] + + [/#if] +[/#macro] + +[#-- Below are the helpers for errors and alerts --] + +[#macro printErrorAlerts rowClass colClass] + [#if errorMessages?size > 0] + [#list errorMessages as m] + [@alert message=m type="error" icon="exclamation-circle" rowClass=rowClass colClass=colClass/] + [/#list] + [/#if] +[/#macro] + +[#macro printInfoAlerts rowClass colClass] + [#if infoMessages?size > 0] + [#list infoMessages as m] + [@alert message=m type="info" icon="info-circle" rowClass=rowClass colClass=colClass/] + [/#list] + [/#if] +[/#macro] + +[#macro alert message type icon includeDismissButton=true rowClass="row center-xs" colClass="col-xs col-sm-8 col-md-6 col-lg-5 col-xl-4"] +
+
+
+ +

+ ${message} +

+ [#if includeDismissButton] + + [/#if] +
+
+
+[/#macro] + +[#-- Below are the input helpers for hidden, text, buttons, labels and form errors. + These fields are general purpose and can be used on any form you like. --] + +[#-- Hidden Input --] +[#macro hidden name value="" dateTimeFormat=""] + [#if !value?has_content] + [#local value=("((" + name + ")!'')")?eval?string/] + [/#if] + + [#if dateTimeFormat != ""] + + [/#if] +[/#macro] + +[#-- Input field of type. --] +[#macro input type name id autocapitalize="none" autocomplete="on" autocorrect="off" autofocus=false spellcheck="false" label="" placeholder="" leftAddon="" required=false tooltip="" disabled=false class="" dateTimeFormat="" value="" uncheckedValue=""] +
+ [#if type == "checkbox"] + [@_input_checkbox name=name value=value uncheckedValue=uncheckedValue label=label tooltip=tooltip] + [#nested] + [/@_input_checkbox] + [#else] + [@_input_text type=type name=name id=id autocapitalize=autocapitalize autocomplete=autocomplete autocorrect=autocorrect autofocus=autofocus spellcheck=spellcheck label=label placeholder=placeholder leftAddon=leftAddon required=required tooltip=tooltip disabled=disabled class=class dateTimeFormat=dateTimeFormat/] + [/#if] + [@errors field=name/] +
+[/#macro] + +[#macro _input_text type name id autocapitalize autocomplete autocorrect autofocus spellcheck label placeholder leftAddon required tooltip disabled class dateTimeFormat ] + [#if label?has_content] + [#compress] + + [/#compress] + [/#if] + [#if leftAddon?has_content] +
+ + [/#if] + [#local value=("((" + name + ")!'')")?eval/] + [#if (placeholder?has_content) && (type == "date") && (value == "")] + [#-- If the value is empty, we want to show the placeholder. This is a workaround for the date picker. --] + [#assign the_type="text" /] + [#assign the_class=class + " date-picker" /] + [#-- it is possible that this element is the first in the form list. We want it to focus on something else so that the placeholder shows. --] + + [#else ] + [#assign the_type=type /] + [#assign the_class=class /] + [/#if] + + [#if dateTimeFormat != ""] + + [#elseif type == "date"] + + [/#if] + [#if leftAddon?has_content] +
+ [/#if] +[/#macro] + +[#macro _input_checkbox name value uncheckedValue label tooltip] + +[/#macro] + +[#-- Select --] +[#macro select name id autocapitalize="none" autofocus=false label="" required=false tooltip="" disabled=false class="select" options=[]] +
+ [#if label?has_content] + [#compress] + + [/#compress] + [/#if] + + [@errors field=name/] +
+[/#macro] + +[#-- Text Area --] +[#macro textarea name id autocapitalize="none" autofocus=false label="" required=false tooltip="" disabled=false class="textarea" placeholder=""] +
+ + [@errors field=name/] +
+[/#macro] + +[#-- Begin : Used for Advanced Registration. + The following form controls require a 'field' argument which is only available during registration. --] + +[#-- Radio List --] +[#macro radio_list field name id autocapitalize="none" autofocus=false label="" required=false tooltip="" disabled=false class="radio-list" options=[]] +
+ [#if label?has_content] + [#compress] + + [/#compress] + [/#if] + [#local value=("((" + name + ")!'')")?eval/] +
+ [#list options as option] + [#local checked = value == option/] + [#if field.type == "consent"] + [#local checked = consents(field.consentId)?? && consents(field.consentId)?contains(option)] + [/#if] + + [/#list] +
+ [@errors field=name/] +
+[/#macro] + +[#macro checkbox field name id autocapitalize="none" autofocus=false label="" required=false tooltip="" disabled=false class="checkbox"] +
+ + [@errors field=name/] +
+[/#macro] + +[#macro checkbox_list field name id autocapitalize="none" autofocus=false label="" required=false tooltip="" disabled=false class="checkbox-list" options=[]] +
+ [#if label?has_content][#t/] + [#t/] + [/#if] +
+ [#list options as option] + [#local value=("((" + name + ")!'')")?eval/] + [#local checked = value?is_sequence && value?seq_contains(option)/] + [#if field.type == "consent"] + [#local checked = consents(field.consentId)?? && consents(field.consentId)?contains(option)] + [/#if] + + [/#list] +
+ [@errors field=name/] +
+[/#macro] + +[#macro locale_select field name id autofocus=false label="" required=false tooltip="" class="select"] +[#-- Note: This is a simple imlementation that does not support selecting more than one locale. + You may wish to use a multi-select or some other JavaScript widget to allow for more than one selection and to improve UX --] + [#local value=("((" + name + ")!'')")?eval/] +
+ [#if label?has_content][#t/] + [#t/] + [/#if] + + [@errors field=name/] +
+[/#macro] + +[#-- End : Used for Advanced Registration. --] + +[#macro oauthHiddenFields] + [@hidden name="captcha_token"/] + [@hidden name="client_id"/] + [@hidden name="code_challenge"/] + [@hidden name="code_challenge_method"/] + [@hidden name="metaData.device.name"/] + [@hidden name="metaData.device.type"/] + [@hidden name="nonce"/] + [@hidden name="oauth_context"/] + [@hidden name="max_age"/] + [@hidden name="pendingIdPLinkId"/] + [@hidden name="prompt"/] + [@hidden name="redirect_uri"/] + [@hidden name="response_mode"/] + [@hidden name="response_type"/] + [@hidden name="scope"/] + [@hidden name="state"/] + [@hidden name="tenantId"/] + [@hidden name="timezone"/] + [@hidden name="user_code"/] +[/#macro] + +[#macro errors field] + [#if fieldMessages[field]?has_content] + [#list fieldMessages[field] as message]${message?no_esc}[#if message_has_next], [/#if][/#list] + [/#if] +[/#macro] + +[#macro button text icon="arrow-right" color="blue" disabled=false name="" value=""] + +[/#macro] + +[#macro link url extraParameters=""] + + [#nested/] + +[/#macro] + +[#macro logoutLink redirectURI extraParameters=""] +[#-- Note that in order for the post_logout_redirect_uri to be correctly URL escaped, you must use this syntax for assignment --] + [#local post_logout_redirect_uri]${redirectURI}?tenantId=${(tenantId)!''}&client_id=${(client_id)!''}&nonce=${(nonce?url)!''}&pendingIdPLinkId=${(pendingIdPLinkId)!''}&redirect_uri=${(redirect_uri?url)!''}&response_mode=${(response_mode?url)!''}&response_type=${(response_type?url)!''}&scope=${(scope?url)!''}&state=${(state?url)!''}&timezone=${(timezone?url)!''}&metaData.device.name=${(metaData.device.name?url)!''}&metaData.device.type=${(metaData.device.type?url)!''}${(extraParameters?no_esc)!''}&code_challenge=${(code_challenge?url)!''}&code_challenge_method=${(code_challenge_method?url)!''}&user_code=${(user_code?url)!''}&prompt=${(prompt?url)!''}&max_age=${(max_age?url)!''}[/#local] + [#t] + [#nested/][#t] + [#t] +[/#macro] + +[#macro defaultIfNull text default] + ${text!default} +[/#macro] + +[#macro passwordRules passwordValidationRules] +
+ + ${theme.message('password-constraints-intro')} + +
    +
  • ${theme.message('password-length-constraint', passwordValidationRules.minLength, passwordValidationRules.maxLength)}
  • + [#if passwordValidationRules.requireMixedCase] +
  • ${theme.message('password-case-constraint')}
  • + [/#if] + [#if passwordValidationRules.requireNonAlpha] +
  • ${theme.message('password-alpha-constraint')}
  • + [/#if] + [#if passwordValidationRules.requireNumber] +
  • ${theme.message('password-number-constraint')}
  • + [/#if] + [#if passwordValidationRules.rememberPreviousPasswords.enabled] +
  • ${theme.message('password-previous-constraint', passwordValidationRules.rememberPreviousPasswords.count)}
  • + [/#if] +
+
+[/#macro] + +[#macro customField field key autofocus=false placeholder="" label="" leftAddon="true"] + [#assign fieldId = field.key?replace(".", "_") /] + [#local leftAddon = (leftAddon == "true")?then(field.data.leftAddon!'info', "") /] + + [#if field.key == "user.preferredLanguages" || field.key == "registration.preferredLanguages"] + [@locale_select field=field id="${fieldId}" name="${field.key}" required=field.required autofocus=autofocus label=label /] + [#elseif field.control == "checkbox"] + [#if field.options?has_content] + [@checkbox_list field=field id="${fieldId}" name="${key}" required=field.required autofocus=autofocus label=label options=field.options /] + [#else] + [@checkbox field=field id="${fieldId}" name="${key}" required=field.required autofocus=autofocus label=label /] + [/#if] + [#elseif field.control == "number"] + [@input id="${fieldId}" type="number" name="${key}" leftAddon="${leftAddon}" required=field.required autofocus=autofocus label=label placeholder=theme.optionalMessage(placeholder) /] + [#elseif field.control == "password"] + [@input id="${fieldId}" type="password" name="${key}" leftAddon="lock" autocomplete="new-password" autofocus=autofocus label=label placeholder=theme.optionalMessage(placeholder)/] + [#elseif field.control == "radio"] + [@radio_list field=field id="${fieldId}" name="${key}" required=field.required autofocus=autofocus label=label options=field.options /] + [#elseif field.control == "select"] + [@select id="${fieldId}" name="${key}" required=field.required autofocus=autofocus label=label options=field.options /] + [#elseif field.control == "textarea"] + [@textarea id="${fieldId}" name="${key}" required=field.required autofocus=autofocus label=label placeholder=theme.optionalMessage(placeholder) /] + [#elseif field.control == "text"] + [#if field.type == "date"] + [@input id="${fieldId}" name="${key}" type="date" leftAddon="${leftAddon}" required=field.required autofocus=autofocus label=label placeholder=theme.optionalMessage(placeholder) /] + [#else] + [@input id="${fieldId}" type="text" name="${key}" leftAddon="${leftAddon}" required=field.required autofocus=autofocus label=label placeholder=theme.optionalMessage(placeholder)/] + [/#if] + [/#if] +[/#macro] + +[#function display object propertyName default="\x2013" ] + [#assign value=("((object." + propertyName + ")!'')")?eval/] +[#-- ?has_content is false for boolean types, check it first --] + [#if value?has_content] + [#if value?is_number] + [#return value?string('#,###')] + [#else] + [#return (value == default?is_markup_output?then(default?markup_string, default))?then(value, value?string)] + [/#if] + [#else] + [#return default] + [/#if] +[/#function] + +[#macro passwordField field showCurrentPasswordField=false] +[#-- Render checkbox used to determine whether the form submit should update password--] +
+ + + +
+
+ [#-- See if the application requires the current password --] + [#if showCurrentPasswordField] + [@customField field=field key="currentPassword" autofocus=false label=theme.optionalMessage("current-password")/] + [/#if] + + [#-- Show the Password Validation Rules if there is a field error for 'user.password' --] + [#if (fieldMessages?keys?seq_contains("user.password")!false) && passwordValidationRules??] + [@passwordRules passwordValidationRules/] + [/#if] + + [#-- Render password field--] + [@customField field=field key=field.key autofocus=false placeholder=field.key label=theme.optionalMessage(field.key) leftAddon="false"/] + + [#-- Render confirm if set to true on the field --] + [#if field.confirm] + [@customField field "confirm.${field.key}" false "[confirm]${field.key}" /] + [/#if] +
+[/#macro] + +[#macro captchaScripts showCaptcha captchaMethod siteKey=""] + [#if showCaptcha] + [#if captchaMethod == "GoogleRecaptchaV2"] + + [/#if] + [#if captchaMethod == "GoogleRecaptchaV3"] + + [/#if] + [#if captchaMethod == "HCaptcha" || captchaMethod == "HCaptchaEnterprise"] + + [/#if] + + + [/#if] +[/#macro] + +[#macro captchaBadge showCaptcha captchaMethod siteKey=""] +[#-- If you want to remove captcha from the page, also ensure you disable it in the tenant configruation. --] + [#if showCaptcha] + [#if captchaMethod == "GoogleRecaptchaV2"] +
+ [#elseif captchaMethod == "GoogleRecaptchaV3"] + [#-- This is the replacement Terms and Conditions messaging that is required by Google when hiding the + standard badge. If you want to remove this you will also need to remove or edit the CSS above. --] +
+ ${theme.message('captcha-google-branding')?no_esc} +
+ [#elseif captchaMethod == "HCaptcha" || captchaMethod == "HCaptchaEnterprise"] +
+ [/#if] + [@errors field="captcha_token"/] + [/#if] +[/#macro] + +[#macro scopeConsentField application scope type] +[#-- Resolve the consent message and detail for the provided scope --] + [#if type != "unknown"] + [#local scopeMessage = resolveScopeMessaging('message', application, scope.name, scope.defaultConsentMessage!scope.name) /] + [#local scopeDetail = resolveScopeMessaging('detail', application, scope.name, scope.defaultConsentDetail!'') /] + [/#if] + + [#if type == "required"] + [#-- Required scopes should use a hidden form field with a value of "true". The user cannot change this selection, --] + [#-- but there should be a display element to inform the user that they must consent to the scopes to continue. --] + + [#elseif type == "optional"] + [#-- Optional scopes should render a checkbox to allow a user to change their selection. The available values should be "true" and "false" --] + + [#elseif type == "unknown"] + [#-- Unknown scopes and the reserved "openid" and "offline_access" scopes are considered required and do not have an associated display element. --] + [@hidden name="scopeConsents['${scope}']" value="true" /] + [/#if] +[/#macro] + +[#function resolveScopeMessaging messageType application scopeName default] +[#-- Application specific, tenant specific, not application/tenant specific, then default --] + [#local message = theme.optionalMessage("[{application}${application.id}]{scope-${messageType}}${scopeName}") /] + [#local resolvedMessage = message != "[{application}${application.id}]{scope-${messageType}}${scopeName}" /] + [#if !resolvedMessage] + [#local message = theme.optionalMessage("[{tenant}${application.tenantId}]{scope-${messageType}}${scopeName}") /] + [#local resolvedMessage = message != "[{tenant}${application.tenantId}]{scope-${messageType}}${scopeName}" /] + [/#if] + [#if !resolvedMessage] + [#local message = theme.optionalMessage("{scope-${messageType}}${scopeName}") /] + [#local resolvedMessage = message != "{scope-${messageType}}${scopeName}" /] + [/#if] + [#if !resolvedMessage] + [#return default /] + [#else] + [#return message /] + [/#if] +[/#function] diff --git a/kickstart/templates/index.ftl b/kickstart/templates/index.ftl new file mode 100644 index 0000000..d7b0ccc --- /dev/null +++ b/kickstart/templates/index.ftl @@ -0,0 +1,46 @@ +[#ftl/] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="theme" type="io.fusionauth.domain.Theme" --] +[#import "_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title="FusionAuth"/] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [#if theme.type != "simple"] + [#-- + Example landing page. You can use a meta refresh (or via JS) to redirect users who land here to your primary site, + or add some links here to help direct them to different applications. + + For additional details on performing a redirect. + https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections#alternative_way_of_specifying_redirections + --] + [@helpers.main title="" rowClass="row center-xs" colClass="col-xs-12 col-sm-12 col-md-10 col-lg-10 col-xl-9"] +
+
+ +
+

Welcome!

+

+ If you are looking for the FusionAuth admin login, you'll find a lock icon in the top right hand side which will take you there. If you don't have an admin account to FusionAuth, no need to click there you won't get very far. You'll want to theme this page to either redirect to your site, or provide links for your end users to find their applications. +

+

Here are some links to help you get started! Welcome to the FusionAuth community, we're glad to have you!

+ +
+ [/@helpers.main] + [/#if] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Authorize.ftl b/kickstart/templates/oauth2Authorize.ftl new file mode 100644 index 0000000..e8772d8 --- /dev/null +++ b/kickstart/templates/oauth2Authorize.ftl @@ -0,0 +1,122 @@ +[#ftl/] +[#setting url_escaping_charset="UTF-8"] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="bootstrapWebauthnEnabled" type="boolean" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="code_challenge" type="java.lang.String" --] +[#-- @ftlvariable name="code_challenge_method" type="java.lang.String" --] +[#-- @ftlvariable name="devicePendingIdPLink" type="io.fusionauth.domain.provider.PendingIdPLink" --] +[#-- @ftlvariable name="federatedCSRFToken" type="java.lang.String" --] +[#-- @ftlvariable name="hasDomainBasedIdentityProviders" type="boolean" --] +[#-- @ftlvariable name="identityProviders" type="java.util.Map>>" --] +[#-- @ftlvariable name="idpRedirectState" type="java.lang.String" --] +[#-- @ftlvariable name="loginId" type="java.lang.String" --] +[#-- @ftlvariable name="metaData" type="io.fusionauth.domain.jwt.RefreshToken.MetaData" --] +[#-- @ftlvariable name="nonce" type="java.lang.String" --] +[#-- @ftlvariable name="passwordlessEnabled" type="boolean" --] +[#-- @ftlvariable name="pendingIdPLink" type="io.fusionauth.domain.provider.PendingIdPLink" --] +[#-- @ftlvariable name="redirect_uri" type="java.lang.String" --] +[#-- @ftlvariable name="rememberDevice" type="boolean" --] +[#-- @ftlvariable name="response_type" type="java.lang.String" --] +[#-- @ftlvariable name="scope" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="showPasswordField" type="boolean" --] +[#-- @ftlvariable name="showWebAuthnReauthLink" type="boolean" --] +[#-- @ftlvariable name="state" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="timezone" type="java.lang.String" --] +[#-- @ftlvariable name="user_code" type="java.lang.String" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + + + [@helpers.alternativeLoginsScript clientId=client_id identityProviders=identityProviders/] + + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("login")] + [#-- During a linking work flow, optionally indicate to the user which IdP is being linked. --] + [#if devicePendingIdPLink?? || pendingIdPLink??] +

+ [#if devicePendingIdPLink?? && pendingIdPLink??] + ${theme.message('pending-links-login-to-complete', devicePendingIdPLink.identityProviderName, pendingIdPLink.identityProviderName)} + [#elseif devicePendingIdPLink??] + ${theme.message('pending-link-login-to-complete', devicePendingIdPLink.identityProviderName)} + [#else] + ${theme.message('pending-link-login-to-complete', pendingIdPLink.identityProviderName)} + [/#if] + [#-- A pending link can be cancled. If we also have a device link in progress, this cannot be canceled. --] + [#if pendingIdPLink??] + [@helpers.link url="" extraParameters="&cancelPendingIdpLink=true"]${theme.message("login-cancel-link")}[/@helpers.link] + [/#if] +

+ [/#if] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="showPasswordField"/] + [@helpers.hidden name="userVerifyingPlatformAuthenticatorAvailable"/] + [#if showPasswordField && hasDomainBasedIdentityProviders] + [@helpers.hidden name="loginId"/] + [/#if] + +
+ [@helpers.input type="text" name="loginId" id="loginId" autocomplete="username" autocapitalize="none" autocomplete="on" autocorrect="off" spellcheck="false" autofocus=(!loginId?has_content) placeholder=theme.message("loginId") leftAddon="user" disabled=(showPasswordField && hasDomainBasedIdentityProviders)/] + [#if showPasswordField] + [@helpers.input type="password" name="password" id="password" autocomplete="current-password" autofocus=loginId?has_content placeholder=theme.message("password") leftAddon="lock"/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [/#if] +
+ + [@helpers.input id="rememberDevice" type="checkbox" name="rememberDevice" label=theme.message("remember-device") value="true" uncheckedValue="false"] + [#t/] + [/@helpers.input] + +
+ [#if showPasswordField] + [@helpers.button icon="key" text=theme.message("submit")/] + [@helpers.link url="${request.contextPath}/password/forgot"]${theme.message("forgot-your-password")}[/@helpers.link] + [#else] + [@helpers.button icon="arrow-right" text=theme.message("next")/] + [/#if] +
+
+
+ [#if showPasswordField && hasDomainBasedIdentityProviders] + [@helpers.link url="" extraParameters="&showPasswordField=false"]${theme.message("sign-in-as-different-user")}[/@helpers.link] + [/#if] +
+ [#if application.registrationConfiguration.enabled] +
+ ${theme.message("dont-have-an-account")} + [@helpers.link url="${request.contextPath}/oauth2/register"]${theme.message("create-an-account")}[/@helpers.link] +
+ [/#if] + + [#if showWebAuthnReauthLink] + [@helpers.link url="${request.contextPath}/oauth2/webauthn-reauth"] ${theme.message("return-to-webauthn-reauth")} [/@helpers.link] + [/#if] + [@helpers.alternativeLogins clientId=client_id identityProviders=identityProviders passwordlessEnabled=passwordlessEnabled bootstrapWebauthnEnabled=bootstrapWebauthnEnabled idpRedirectState=idpRedirectState federatedCSRFToken=federatedCSRFToken/] + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2AuthorizedNotRegistered.ftl b/kickstart/templates/oauth2AuthorizedNotRegistered.ftl new file mode 100644 index 0000000..e3b2089 --- /dev/null +++ b/kickstart/templates/oauth2AuthorizedNotRegistered.ftl @@ -0,0 +1,27 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("authorized-not-registered-title")] + ${theme.message("authorized-not-registered")} + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2ChildRegistrationNotAllowed.ftl b/kickstart/templates/oauth2ChildRegistrationNotAllowed.ftl new file mode 100644 index 0000000..cdcc4d7 --- /dev/null +++ b/kickstart/templates/oauth2ChildRegistrationNotAllowed.ftl @@ -0,0 +1,38 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("provide-parent-email")] +
+ [@helpers.hidden name="client_id"/] + [@helpers.hidden name="tenantId"/] +

+ ${theme.message("child-registration-not-allowed")} +

+
+ [@helpers.input type="text" name="parentEmail" id="parentEmail" placeholder=theme.message("parentEmail") leftAddon="user" required=true/] +
+ +
+ [@helpers.button icon="left-arrow" text=theme.message("submit")/] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2ChildRegistrationNotAllowedComplete.ftl b/kickstart/templates/oauth2ChildRegistrationNotAllowedComplete.ftl new file mode 100644 index 0000000..bec1855 --- /dev/null +++ b/kickstart/templates/oauth2ChildRegistrationNotAllowedComplete.ftl @@ -0,0 +1,27 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("parent-notified-title")] +

+ ${theme.message("parent-notified")} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2CompleteRegistration.ftl b/kickstart/templates/oauth2CompleteRegistration.ftl new file mode 100644 index 0000000..d6a4b81 --- /dev/null +++ b/kickstart/templates/oauth2CompleteRegistration.ftl @@ -0,0 +1,109 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="fields" type="java.util.List" --] +[#-- @ftlvariable name="step" type="int" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="totalSteps" type="int" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("complete-registration")] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="step"/] + [@helpers.hidden name="registrationState"/] + [@helpers.hidden name="userVerifyingPlatformAuthenticatorAvailable"/] + + [#-- Begin Self Service Custom Registration Form Steps --] + [#if fields?has_content] +
+ [#list fields as field] + [@helpers.customField field field.key field?is_first?then(true, false) field.key /] + [#if field.confirm] + [@helpers.customField field "confirm.${field.key}" false "[confirm]${field.key}" /] + [/#if] + [/#list] +
+ +
+ [#if step == totalSteps] + [@helpers.button icon="key" text=theme.message("register")/] + [#else] + [@helpers.button icon="arrow-right" text="Next"/] + [/#if] +
+ [#-- End Custom Self Service Registration Form Steps --] + [#else] + [#-- Begin Basic Self Service Registration Form --] +
+ [#if application.registrationConfiguration.firstName.enabled] + [@helpers.input type="text" name="user.firstName" id="firstName" placeholder=theme.message("firstName") leftAddon="user" required=application.registrationConfiguration.firstName.required/] + [/#if] + [#if application.registrationConfiguration.fullName.enabled] + [@helpers.input type="text" name="user.fullName" id="fullName" placeholder=theme.message("fullName") leftAddon="user" required=application.registrationConfiguration.fullName.required/] + [/#if] + [#if application.registrationConfiguration.middleName.enabled] + [@helpers.input type="text" name="user.middleName" id="middleName" placeholder=theme.message("middleName") leftAddon="user" required=application.registrationConfiguration.middleName.required/] + [/#if] + [#if application.registrationConfiguration.lastName.enabled] + [@helpers.input type="text" name="user.lastName" id="lastName" placeholder=theme.message("lastName") leftAddon="user" required=application.registrationConfiguration.lastName.required/] + [/#if] + [#if application.registrationConfiguration.birthDate.enabled] + [@helpers.input type="date" name="user.birthDate" id="birthDate" placeholder=theme.message("birthDate") leftAddon="calendar" class="date-picker" required=application.registrationConfiguration.birthDate.required/] + [/#if] + [#if application.registrationConfiguration.mobilePhone.enabled] + [@helpers.input type="text" name="user.mobilePhone" id="mobilePhone" placeholder=theme.message("mobilePhone") leftAddon="phone" required=application.registrationConfiguration.mobilePhone.required/] + [/#if] + [#if application.registrationConfiguration.preferredLanguages.enabled] + [@helpers.locale_select field="" name="user.preferredLanguages" id="preferredLanguages" label=theme.message("preferredLanguage") required=application.registrationConfiguration.preferredLanguages.required /] + [/#if] +
+ +
+ [@helpers.button icon="key" text=theme.message("submit")/] +
+ [/#if] + [#-- End Basic Self Service Registration Form --] + + [#-- Begin Self Service Custom Registration Form Step Counter --] + [#if step > 0] +
+
${theme.message('register-step', step, totalSteps)}
+
+ [/#if] + [#-- End Self Service Custom Registration Form Step Counter --] + +
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Consent.ftl b/kickstart/templates/oauth2Consent.ftl new file mode 100644 index 0000000..ce862ff --- /dev/null +++ b/kickstart/templates/oauth2Consent.ftl @@ -0,0 +1,56 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="requiredScopes" type="java.util.List" --] +[#-- @ftlvariable name="optionalScopes" type="java.util.List" --] +[#-- @ftlvariable name="theme" type="io.fusionauth.domain.Theme" --] +[#-- @ftlvariable name="unknownScopes" type="java.util.List" --] + +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('consent-required')] +

${theme.message('consent-required-intro', application.name?esc?markup_string)?no_esc}${theme.message("propertySeparator")}

+ + + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Device.ftl b/kickstart/templates/oauth2Device.ftl new file mode 100644 index 0000000..8787c67 --- /dev/null +++ b/kickstart/templates/oauth2Device.ftl @@ -0,0 +1,131 @@ +[#ftl/] +[#-- @ftlvariable name="activationComplete" type="boolean" --] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="devicePendingIdPLink" type="io.fusionauth.domain.provider.PendingIdPLink" --] +[#-- @ftlvariable name="theme" type="io.fusionauth.domain.Theme" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="userCodeLength" type="int" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("device-title")] + + + + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [#-- If a pending link will cause us to exceed our linking limit, the next step will be to logout. --] + [#assign logoutToContinue = devicePendingIdPLink?? && devicePendingIdPLink.linkLimitExceeded /] + + [@helpers.main title=theme.message("device-form-title")] + [#setting url_escaping_charset='UTF-8'] + + [#-- During a linking work flow, optionally indicate to the user which IdP is being linked. --] + [#if devicePendingIdPLink?? && !logoutToContinue] +

+ ${theme.message('pending-device-link', devicePendingIdPLink.identityProviderName)} +

+ [/#if] + + [#-- If there is an active SSO session, give the user the option to logout of the SSO session + that does not belong to them. If a link count has been exceeded provide a logout button. + --] + [#if currentUser??] +
+ [#-- You may wish to obfuscate a portion of this value for anonymity.. --] + [#assign currentLoginId = currentUser.login /] + [#if logoutToContinue] + [#-- The user must logout before continuing because the currently logged in user has exceeded the number of allowed links to this IdP. --] +

${theme.message('device-link-count-exceeded-pending-logout', currentLoginId, devicePendingIdPLink.identityProviderName)}

+

${theme.message("device-link-count-exceeded-next-step")}

+
+
+ [@helpers.logoutLink redirectURI="/oauth2/device"] + + [/@helpers.logoutLink] +
+
+ [#else] +

${theme.message('device-logged-in-as-not-you', currentLoginId)}

+
+
+ [@helpers.logoutLink redirectURI="/oauth2/device"] + + [/@helpers.logoutLink] +
+
+ [/#if] +
+ [/#if] + + [#-- Not showing the form if the user must logout first. --] + [#if !logoutToContinue] +
+ [@helpers.oauthHiddenFields/] +

${theme.message("userCode")}

+
+
+ [#list 0.. + + + [#if i == (userCodeLength/2)?floor - 1]-[/#if] +
+ [/#list] + + +
+ +
+ [@helpers.errors field="user_code" /] +
+ +
+ [@helpers.button text=theme.message('submit')/] +
+
+ [/#if] + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2DeviceComplete.ftl b/kickstart/templates/oauth2DeviceComplete.ftl new file mode 100644 index 0000000..bab8f2d --- /dev/null +++ b/kickstart/templates/oauth2DeviceComplete.ftl @@ -0,0 +1,35 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="completedLinks" type="java.util.List" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("device-title")/] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("device-form-title")] + [#if completedLinks?has_content] + [#if completedLinks?size == 1] + ${theme.message('completed-link', completedLinks.get(0).identityProviderType)} + [#elseif completedLinks?size == 2] + ${theme.message('completed-links', completedLinks.get(0).identityProviderType.name(), completedLinks.get(1).identityProviderType.name())} + [/#if] + [/#if] +

+ ${theme.message('device-login-complete')} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Error.ftl b/kickstart/templates/oauth2Error.ftl new file mode 100644 index 0000000..6f4ce3a --- /dev/null +++ b/kickstart/templates/oauth2Error.ftl @@ -0,0 +1,33 @@ +[#ftl/] +[#-- @ftlvariable name="oauthJSONError" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title="Error"] +

+ We're sorry, your request was malformed or was unable to be completed for some reason. Try hitting the back button and restarting the process to see if it fixes the problem. +

+ + [#if oauthJSONError?has_content] + If you want the nerdy explanation, review the following JSON body. +
${oauthJSONError}
+ [/#if] + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Logout.ftl b/kickstart/templates/oauth2Logout.ftl new file mode 100644 index 0000000..3219523 --- /dev/null +++ b/kickstart/templates/oauth2Logout.ftl @@ -0,0 +1,46 @@ +[#ftl/] +[#-- @ftlvariable name="allLogoutURLs" type="java.util.Set" --] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="registeredLogoutURLs" type="java.util.Set" --] +[#-- @ftlvariable name="redirectURL" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[#-- You may adjust the duration before we redirect the user --] +[#assign logoutDurationInSeconds = 2 /] + +[@helpers.html] + [@helpers.head title=theme.message("logout-title")] + [#if redirectURL?has_content] + + [/#if] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("logging-out")] +
+
+
+
+ [/@helpers.main] + + [#-- Use allLogoutURLs to call the logout URL of all applications in the tenant, or use registeredLogoutURLs to log out of just the applications the user is currently registered. + Note, that just because a user does not currently have a registration, does not necessarily mean the user does not hold a session with an application. It is possible the user has been un-registered + recently, or an application may have created a session for a user regardless of their registration. In most cases it is safest to simply call all applications and ensure that the Single Logout + URL can handle logout requests for users that may or may not have a session with that application. + --] + [#list allLogoutURLs![] as logoutURL] + + [/#list] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Passwordless.ftl b/kickstart/templates/oauth2Passwordless.ftl new file mode 100644 index 0000000..010d38d --- /dev/null +++ b/kickstart/templates/oauth2Passwordless.ftl @@ -0,0 +1,56 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="code" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="formField" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("passwordless-login")] + [#setting url_escaping_charset='UTF-8'] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="code"/] + [@helpers.hidden name="formField"/] + +
+ [#if formField] + [@helpers.input type="text" name="oneTimeCode" id="otp" autocapitalize="none" autofocus=true autocomplete="one-time-code" autocorrect="off" placeholder="${theme.message('passwordless-code')}" leftAddon="lock"/] + [#else] + [@helpers.input type="text" name="loginId" id="loginId" autocomplete="username" autocapitalize="none" autocomplete="on" autocorrect="off" spellcheck="false" autofocus=true placeholder=theme.message("loginId") leftAddon="user" required=true/] + [/#if] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+ + [@helpers.input id="rememberDevice" type="checkbox" name="rememberDevice" label=theme.message("remember-device") value="true" uncheckedValue="false"] + [#t/] + [/@helpers.input] + +
+ [#if formField] + [@helpers.button text=theme.message('submit')/] + [#else] + [@helpers.button icon="send" text=theme.message('send')/] + [/#if] +

[@helpers.link url="/oauth2/authorize"]${theme.message('return-to-login')}[/@helpers.link]

+
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Register.ftl b/kickstart/templates/oauth2Register.ftl new file mode 100644 index 0000000..a828b74 --- /dev/null +++ b/kickstart/templates/oauth2Register.ftl @@ -0,0 +1,194 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="collectBirthDate" type="boolean" --] +[#-- @ftlvariable name="devicePendingIdPLink" type="io.fusionauth.domain.provider.PendingIdPLink" --] +[#-- @ftlvariable name="federatedCSRFToken" type="java.lang.String" --] +[#-- @ftlvariable name="fields" type="java.util.List" --] +[#-- @ftlvariable name="hideBirthDate" type="boolean" --] +[#-- @ftlvariable name="identityProviders" type="java.util.Map>>" --] +[#-- @ftlvariable name="idpRedirectState" type="java.lang.String" --] +[#-- @ftlvariable name="passwordValidationRules" type="io.fusionauth.domain.PasswordValidationRules" --] +[#-- @ftlvariable name="parentEmailRequired" type="boolean" --] +[#-- @ftlvariable name="pendingIdPLink" type="io.fusionauth.domain.provider.PendingIdPLink" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="step" type="int" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="totalSteps" type="int" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("register")] + + [@helpers.alternativeLoginsScript clientId=client_id identityProviders=identityProviders/] + [#if step == totalSteps] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [/#if] + + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("register")] + [#-- During a linking work flow, optionally indicate to the user which IdP is being linked. --] + [#if devicePendingIdPLink?? || pendingIdPLink??] +

+ [#if devicePendingIdPLink?? && pendingIdPLink??] + ${theme.message('pending-links-register-to-complete', devicePendingIdPLink.identityProviderName, pendingIdPLink.identityProviderName)} + [#elseif devicePendingIdPLink??] + ${theme.message('pending-link-register-to-complete', devicePendingIdPLink.identityProviderName)} + [#else] + ${theme.message('pending-link-register-to-complete', pendingIdPLink.identityProviderName)} + [/#if] + [#-- A pending link can be cancled. If we also have a device link in progress, this cannot be canceled. --] + [#if pendingIdPLink??] + [@helpers.link url="" extraParameters="&cancelPendingIdpLink=true"]${theme.message("register-cancel-link")}[/@helpers.link] + [/#if] +

+ [/#if] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="step"/] + [@helpers.hidden name="registrationState"/] + [@helpers.hidden name="parentEmailRequired"/] + [@helpers.hidden name="userVerifyingPlatformAuthenticatorAvailable"/] + + [#-- Show the Password Validation Rules if there is a field error for 'user.password' --] + [#if (fieldMessages?keys?seq_contains("user.password")!false) && passwordValidationRules??] + [@helpers.passwordRules passwordValidationRules/] + [/#if] + + [#-- Begin Self Service Custom Registration Form Steps --] + [#if fields?has_content] +
+ [@helpers.hidden name="collectBirthDate"/] + [#list fields as field] + [#assign key = field.key] + [@helpers.customField field key field?is_first field.key /] + [#if field.confirm] + [@helpers.customField field "confirm.${key}" false "[confirm]${field.key}" /] + [/#if] + [/#list] + [#-- If this is the last step of the form, optionally show a captcha. --] + [#if step == totalSteps] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [/#if] +
+ + [#if step == totalSteps] + [@helpers.input id="rememberDevice" type="checkbox" name="rememberDevice" label=theme.message("remember-device") value="true" uncheckedValue="false"] + [#t/] + [/@helpers.input] +
+ [@helpers.button icon="key" text=theme.message('register')/] +
+ [#else] +
+ [@helpers.button icon="arrow-right" text=theme.message('next')/] +
+ [/#if] + [#-- End Custom Self Service Registration Form Steps --] + [#else] + [#-- Begin Basic Self Service Registration Form --] +
+ [@helpers.hidden name="collectBirthDate"/] + [#if !collectBirthDate && (!application.registrationConfiguration.birthDate.enabled || hideBirthDate)] + [@helpers.hidden name="user.birthDate" dateTimeFormat="yyyy-MM-dd"/] + [/#if] + [#if collectBirthDate] + [@helpers.input type="date" name="user.birthDate" id="birthDate" placeholder=theme.message('birthDate') leftAddon="calendar" class="date-picker" required=true/] + [#else] + [#if application.registrationConfiguration.loginIdType == 'email'] + [@helpers.input type="text" name="user.email" id="email" autocomplete="username" autocapitalize="none" autocorrect="off" spellcheck="false" autofocus=true placeholder=theme.message('email') leftAddon="user" required=true/] + [#elseif application.registrationConfiguration.loginIdType == 'phoneNumber'] + [@helpers.input type="text" name="user.phoneNumber" id="phoneNumber" autocomplete="mobile" autocapitalize="none" autocorrect="off" spellcheck="false" autofocus=true placeholder=theme.message('phoneNumber') leftAddon="mobile" required=true/] + [#else] + [@helpers.input type="text" name="user.username" id="username" autocomplete="username" autocapitalize="none" autocorrect="off" spellcheck="false" autofocus=true placeholder=theme.message('username') leftAddon="user" required=true/] + [/#if] + [@helpers.input type="password" name="user.password" id="password" autocomplete="new-password" placeholder=theme.message('password') leftAddon="lock" required=true/] + [#if application.registrationConfiguration.confirmPassword] + [@helpers.input type="password" name="passwordConfirm" id="passwordConfirm" autocomplete="new-password" placeholder=theme.message('passwordConfirm') leftAddon="lock" required=true/] + [/#if] + [#if parentEmailRequired] + [@helpers.input type="text" name="user.parentEmail" id="parentEmail" placeholder=theme.message('parentEmail') leftAddon="user" required=true/] + [/#if] + [#if application.registrationConfiguration.birthDate.enabled || + application.registrationConfiguration.firstName.enabled || + application.registrationConfiguration.fullName.enabled || + application.registrationConfiguration.middleName.enabled || + application.registrationConfiguration.lastName.enabled || + application.registrationConfiguration.mobilePhone.enabled || + application.registrationConfiguration.preferredLanguages.enabled ] +
+ [#if application.registrationConfiguration.firstName.enabled] + [@helpers.input type="text" name="user.firstName" id="firstName" placeholder=theme.message('firstName') leftAddon="user" required=application.registrationConfiguration.firstName.required/] + [/#if] + [#if application.registrationConfiguration.fullName.enabled] + [@helpers.input type="text" name="user.fullName" id="fullName" placeholder=theme.message('fullName') leftAddon="user" required=application.registrationConfiguration.fullName.required/] + [/#if] + [#if application.registrationConfiguration.middleName.enabled] + [@helpers.input type="text" name="user.middleName" id="middleName" placeholder=theme.message('middleName') leftAddon="user" required=application.registrationConfiguration.middleName.required/] + [/#if] + [#if application.registrationConfiguration.lastName.enabled] + [@helpers.input type="text" name="user.lastName" id="lastName" placeholder=theme.message('lastName') leftAddon="user" required=application.registrationConfiguration.lastName.required/] + [/#if] + [#if application.registrationConfiguration.birthDate.enabled && !hideBirthDate] + [@helpers.input type="date" name="user.birthDate" id="birthDate" placeholder=theme.message('birthDate') leftAddon="calendar" class="date-picker" required=application.registrationConfiguration.birthDate.required/] + [/#if] + [#if application.registrationConfiguration.mobilePhone.enabled] + [@helpers.input type="text" name="user.mobilePhone" id="mobilePhone" placeholder=theme.message('mobilePhone') leftAddon="phone" required=application.registrationConfiguration.mobilePhone.required/] + [/#if] + [#if application.registrationConfiguration.preferredLanguages.enabled] + [@helpers.locale_select field="" name="user.preferredLanguages" id="preferredLanguages" label=theme.message("preferredLanguage") required=application.registrationConfiguration.preferredLanguages.required /] + [/#if] + [/#if] + [/#if] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+ + [@helpers.input id="rememberDevice" type="checkbox" name="rememberDevice" label=theme.message('remember-device') value="true" uncheckedValue="false"] + [#t/] + [/@helpers.input] + +
+ [@helpers.button icon="key" text=theme.message('register')/] +

[@helpers.link url="/oauth2/authorize"]${theme.message('return-to-login')}[/@helpers.link]

+
+ [/#if] + [#-- End Basic Self Service Registration Form --] + + [#-- Begin Self Service Custom Registration Form Step Counter --] + [#if step > 0] +
+
${theme.message('register-step', step, totalSteps)}
+
+ [/#if] + [#-- End Self Service Custom Registration Form Step Counter --] + + [#-- Identity Provider Buttons (if you want to include these, remove the if-statement) --] + [#if true] + [@helpers.alternativeLogins clientId=client_id identityProviders=identityProviders![] passwordlessEnabled=false bootstrapWebauthnEnabled=false idpRedirectState=idpRedirectState federatedCSRFToken=federatedCSRFToken/] + [/#if] + [#-- End Identity Provider Buttons --] + +
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2StartIdPLink.ftl b/kickstart/templates/oauth2StartIdPLink.ftl new file mode 100644 index 0000000..5f3bf11 --- /dev/null +++ b/kickstart/templates/oauth2StartIdPLink.ftl @@ -0,0 +1,104 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="devicePendingIdPLink" type="io.fusionauth.domain.provider.PendingIdPLink" --] +[#-- @ftlvariable name="pendingIdPLink" type="io.fusionauth.domain.provider.PendingIdPLink" --] +[#-- @ftlvariable name="registrationEnabled" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[#-- Note in most cases, the currentUser reference will not be available. In the case where the user exceeds the number of + links allowed for an IdP, the user will be returned here while having an SSO session. In this case, currentUser will + be available. +--] +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [#-- If a pending link will cause us to exceed our linking limit, the next step will be to lgoout. --] + [#assign logoutToContinue = (devicePendingIdPLink?? && devicePendingIdPLink.linkLimitExceeded) || (pendingIdPLink?? && pendingIdPLink.linkLimitExceeded) /] + + [@helpers.main title=theme.message("start-idp-link-title")] + [#if pendingIdPLink??] + ${theme.message('pending-link-info', pendingIdPLink.identityProviderName)} + [/#if] + + [#if logoutToContinue] + [#-- You may wish to obfuscate a portion of this value for anonymity.. --] + [#assign currentLoginId = currentUser.login /] + ${theme.message('logged-in-as', currentLoginId)} + [#if devicePendingIdPLink?? && devicePendingIdPLink.linkLimitExceeded] +

${theme.message('link-count-exceeded-pending-logout', devicePendingIdPLink.identityProviderName)}

+ [/#if] + [#if pendingIdPLink?? && pendingIdPLink.linkLimitExceeded] +

${theme.message('link-count-exceeded-pending-logout', pendingIdPLink.identityProviderName)}

+ [/#if] +

+ ${theme.message("link-count-exceeded-next-step${registrationEnabled?then('', '-no-registration')}")} +

+ [#else] +

+ [#if devicePendingIdPLink?? && pendingIdPLink??] + ${theme.message('pending-device-links', devicePendingIdPLink.identityProviderName, pendingIdPLink.identityProviderName)} + [#elseif devicePendingIdPLink??] + ${theme.message('pending-device-link', devicePendingIdPLink.identityProviderName)} + [/#if] + ${theme.message("pending-link-next-step${registrationEnabled?then('', '-no-registration')}")} +

+ [/#if] + +
+
+ [#if logoutToContinue] + [@helpers.logoutLink redirectURI="/oauth2/start-idp-link"] + + [/@helpers.logoutLink] + [#else] + [@helpers.link url="/oauth2/authorize"] + + [/@helpers.link] + [/#if] +
+
+ + [#-- If self service registration is enabled, we can also provide an option to register. --] + [#if registrationEnabled && !logoutToContinue] +
+
+ [@helpers.link url="/oauth2/register"] + + [/@helpers.link] +
+
+ [/#if] + + [#if pendingIdPLink??] +
+
+
${theme.message("or")}
+
+ +
+
+ [@helpers.link url="/oauth2/authorize" extraParameters="&cancelPendingIdpLink=true"] + + [/@helpers.link] +
+
+ [/#if] + + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2TwoFactor.ftl b/kickstart/templates/oauth2TwoFactor.ftl new file mode 100644 index 0000000..eae299f --- /dev/null +++ b/kickstart/templates/oauth2TwoFactor.ftl @@ -0,0 +1,73 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="method" type="io.fusionauth.domain.TwoFactorMethod" --] +[#-- @ftlvariable name="methodId" type="java.lang.String" --] +[#-- @ftlvariable name="showResendOrSelectMethod" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="trustComputer" type="boolean" --] +[#-- @ftlvariable name="twoFactorId" type="java.lang.String" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + + + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("two-factor-challenge")] + [#setting url_escaping_charset='UTF-8'] +
+ [@helpers.input type="text" name="code" id="code" autocapitalize="none" autocomplete="one-time-code" autocorrect="off" autofocus=true leftAddon="lock" placeholder=theme.message("code")/] + + [@helpers.oauthHiddenFields/] + [@helpers.hidden name="methodId"/] + [@helpers.hidden name="twoFactorId"/] + [@helpers.hidden name="userVerifyingPlatformAuthenticatorAvailable"/] +
+
+ +
+
+
+ [@helpers.button text=theme.message("verify")/] +
+ + [#-- If more than one option was available, allow the user to change their mind, or go back and request another code. --] + [#if showResendOrSelectMethod] +
+ [@helpers.link url="/oauth2/two-factor-methods" extraParameters="&twoFactorId=${twoFactorId?url}&methodId=${(methodId?url)!''}&selectMethod=true"] + + ${theme.message("two-factor-select-method")} + [/@helpers.link] +
+ [/#if] + +
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2TwoFactorEnable.ftl b/kickstart/templates/oauth2TwoFactorEnable.ftl new file mode 100644 index 0000000..dfa24e1 --- /dev/null +++ b/kickstart/templates/oauth2TwoFactorEnable.ftl @@ -0,0 +1,124 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="availableMethods" type="java.util.List" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="method" type="io.fusionauth.domain.TwoFactorMethod" --] +[#-- @ftlvariable name="methodId" type="java.lang.String" --] +[#-- @ftlvariable name="showResendOrSelectMethod" type="boolean" --] +[#-- @ftlvariable name="secret" type="java.lang.String" --] +[#-- @ftlvariable name="secretBase32Encoded" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="trustComputer" type="boolean" --] +[#-- @ftlvariable name="twoFactorId" type="java.lang.String" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[#macro instructions method] + [#if method == "authenticator"] + + [#-- Authenticator Instructions --] +

${theme.message("oauth2-authenticator-enable-step-1")}

+ [#-- QR Code for Authenticator app --] + [#if method == "authenticator"] + [#-- This is initialized using qrcode-*.js by the element Id --] +
+ [/#if] + + [#elseif method == "email" || method == "sms"] + + [#-- Email or SMS Instructions --] +

${theme.message("oauth2-${method}-enable-step-1")}

+ +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="send" /] + [@helpers.hidden name="method" /] + [#-- 'secret' and 'twoFactorSecretBase32' are required for authenticator. --] + [@helpers.hidden name="secret" /] + [@helpers.hidden name="secretBase32Encoded" /] + [@helpers.hidden name="twoFactorId"/] + + [#-- Send a code --] + [#if method == "email"] + [@helpers.input type="text" id="email" name="email" label="Email" required=true/] + [#elseif method == "sms"] + [@helpers.input type="text" id="mobilePhone" name="mobilePhone" label="Mobile phone" required=true/] + [/#if] + + [@helpers.button icon="arrow-circle-right" color="gray" text="${theme.message('send-one-time-code')}"/] +
+ [/#if] +[/#macro] + +[@helpers.html] + [@helpers.head] + [#-- JavaScript is used for rendering authenticator QR code --] + + + + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("enable-instructions")] + [#setting url_escaping_charset='UTF-8'] + [#-- Heading --] +
+ [#-- The 'select-method' id is used to detect value changes in OAuth2TwoFactorEnable.js --] + [@helpers.select name="method" id="select-method" options=availableMethods label="${theme.message('select-two-factor-method')}" required=true/] +
+ + [#list availableMethods as method] +
+ [#-- Instructions --] + [@instructions method/] +
+ [/#list] + + [#-- Enable Two Factor Form --] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="email" /] + [@helpers.hidden name="method" /] + [@helpers.hidden name="mobilePhone" /] + [#-- 'secret' and 'twoFactorSecretBase32' are required for authenticator. --] + [@helpers.hidden name="secret" /] + [@helpers.hidden name="secretBase32Encoded" /] + [@helpers.hidden name="twoFactorId"/] +
+ [@helpers.input type="text" name="code" id="verification-code" label=theme.message("verification-code") placeholder="${theme.message('{placeholder}two-factor-code')}" autocapitalize="none" autocomplete="one-time-code" autocorrect="off" required=true/] +
+
+ [@helpers.button icon="save" text=theme.message("enable")/] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2TwoFactorEnableComplete.ftl b/kickstart/templates/oauth2TwoFactorEnableComplete.ftl new file mode 100644 index 0000000..717cb9c --- /dev/null +++ b/kickstart/templates/oauth2TwoFactorEnableComplete.ftl @@ -0,0 +1,42 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="recoveryCodes" type="java.util.List" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("two-factor-recovery-codes")] + [#setting url_escaping_charset='UTF-8'] +
+ [@helpers.oauthHiddenFields/] +

${theme.message("{description}oauth2-recovery-codes-1")}

+
+
+ [#list recoveryCodes as code]
${code}
[/#list] +
+

${theme.message("{description}oauth2-recovery-codes-2")}

+
+
+ [@helpers.button text=theme.message("done")/] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2TwoFactorMethods.ftl b/kickstart/templates/oauth2TwoFactorMethods.ftl new file mode 100644 index 0000000..5395ad5 --- /dev/null +++ b/kickstart/templates/oauth2TwoFactorMethods.ftl @@ -0,0 +1,100 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="availableMethodsMap" type="java.util.Map" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="methodId" type="java.lang.String" --] +[#-- @ftlvariable name="recoverCodesAvailable" type="int" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="twoFactorId" type="java.lang.String" --] +[#-- @ftlvariable name="version" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[#macro methodOption id method] +
+ +
+[/#macro] + +[#macro recoveryCodeOption] +
+ +
+[/#macro] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('two-factor-challenge-options')] + [#setting url_escaping_charset='UTF-8'] +
+ + [@helpers.oauthHiddenFields/] + [@helpers.hidden name="twoFactorId"/] + + [#-- Panel description --] + ${theme.message('{description}two-factor-methods-selection')} + + [#-- Available methods --] +
+ + [#list availableMethodsMap as id, method] + [@methodOption id method/] + [/#list] + + [#-- Optionally show an option for recovery codes. A recovery code can always be used to login, so selecting this is not + required to allow the user to enter a recovery code. But it is a cue to the user that they have this option. + Feel free to remove it if you do not want to show it, it will not affect the user's ability to use a recovery code. + --] + [#if recoverCodesAvailable gt 0] + [@recoveryCodeOption/] + [/#if] + + [#-- Show the methodId error here sinc we will have more than one radio button. This can be moved to suit you. --] + [@helpers.errors "methodId"/] +
+ + [#-- Continue to the next step to enter your code. --] + [@helpers.button text=theme.message('continue')/] +
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2Wait.ftl b/kickstart/templates/oauth2Wait.ftl new file mode 100644 index 0000000..6bf4e7c --- /dev/null +++ b/kickstart/templates/oauth2Wait.ftl @@ -0,0 +1,30 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="code" type="java.lang.String" --] +[#-- @ftlvariable name="identityProviderId" type="java.util.UUID" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="waitURL" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("wait-title")] + + [/@helpers.head ] + + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("waiting")] + ${theme.message("complete-external-login")} +

[@helpers.link url="/oauth2/authorize"]${theme.message("return-to-login")}[/@helpers.link]

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2WebAuthn.ftl b/kickstart/templates/oauth2WebAuthn.ftl new file mode 100644 index 0000000..250bd4b --- /dev/null +++ b/kickstart/templates/oauth2WebAuthn.ftl @@ -0,0 +1,54 @@ +[#ftl/] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + + + + [/@helpers.head] + + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + [@helpers.main title=theme.message("no-password")] + [#setting url_escaping_charset='UTF-8'] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="webAuthnRequest" /] + [@helpers.hidden name="workflow" value="bootstrap"/] + [@helpers.hidden name="userVerifyingPlatformAuthenticatorAvailable" /] + +

${theme.message("{description}webauthn-bootstrap-retrieve-credential")}

+
+ [@helpers.input type="text" name="loginId" id="loginId" autocomplete="username" autocapitalize="none" autocomplete="on" autocorrect="off" spellcheck="false" autofocus=true placeholder=theme.message("loginId") leftAddon="user" required=true/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+ + [@helpers.input id="rememberDevice" type="checkbox" name="rememberDevice" label=theme.message("remember-device") value="true" uncheckedValue="false"] + [#t/] + [/@helpers.input] + +
+ [@helpers.button text=theme.message("submit")/] +

[@helpers.link url="/oauth2/authorize" extraParameters="&skipWebAuthnReauth=true"]${theme.message("return-to-normal-login")}[/@helpers.link]

+
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2WebAuthnReauth.ftl b/kickstart/templates/oauth2WebAuthnReauth.ftl new file mode 100644 index 0000000..5e2b4fc --- /dev/null +++ b/kickstart/templates/oauth2WebAuthnReauth.ftl @@ -0,0 +1,72 @@ +[#ftl/] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="webAuthnCredentials" type="java.util.List" --] +[#import "../_helpers.ftl" as helpers/] + +[#-- Contents of the passkey button --] +[#macro passKey user] + [#if user.name??] + ${user.name} + [#elseif user.uniqueUsername??] + ${user.uniqueUsername} + [#else] + ${helpers.display(user, "loginId")} + [/#if] +[/#macro] + +[@helpers.html] + [@helpers.head] + + + + [/@helpers.head] + + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + [@helpers.main title=theme.message("login-with-passkey")] + [#setting url_escaping_charset='UTF-8'] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="webAuthnRequest" /] + [@helpers.hidden name="workflow" value="reauthentication"/] + [@helpers.hidden name="userVerifyingPlatformAuthenticatorAvailable" /] + +

${theme.message("webauthn-reauth-select-passkey")}

+
+ [#list webAuthnCredentials![] as credential] + + [/#list] +
+ +

${theme.message("webauthn-reauth-return-to-login")}

+ + [@helpers.input id="rememberDevice" type="checkbox" name="rememberDevice" label=theme.message("remember-device") value="true" uncheckedValue="false"] + [#t/] + [/@helpers.input] + +
+

[@helpers.link url="/oauth2/authorize" extraParameters="&skipWebAuthnReauth=true"]${theme.message("return-to-normal-login")}[/@helpers.link]

+
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/oauth2WebAuthnReauthEnable.ftl b/kickstart/templates/oauth2WebAuthnReauthEnable.ftl new file mode 100644 index 0000000..46eabe7 --- /dev/null +++ b/kickstart/templates/oauth2WebAuthnReauthEnable.ftl @@ -0,0 +1,101 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="webAuthnCredentials" type="java.util.List" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + + + + + + [/@helpers.head] + + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + [@helpers.main title=theme.message("no-password")] + [#setting url_escaping_charset='UTF-8'] +
+

${theme.message("{description}webauthn-reauth")}

+
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="webAuthnLoginRequest"/] + [@helpers.hidden name="workflow" value="reauthentication"/] + + [#if webAuthnCredentials?has_content] +

${theme.message("{description}webauthn-reauth-existing-credential")}

+
+ [#list webAuthnCredentials![] as credential] + + [/#list] +
+ [/#if] + +
+ [@helpers.input id="doNotAskAgain" type="checkbox" name="doNotAskAgain" label=theme.message('dont-ask-again') value="true" uncheckedValue="false"/] +
+ [@helpers.button icon="check" name="action" value="skip" text=theme.message("not-now") /] +
+
+ +
+ + [#-- Description for adding a new credential during login. --] +

+ + [#if webAuthnCredentials?has_content] + ${theme.message("or")} ${theme.message("{description}webauthn-reauth-add-credential")?uncap_first} + [#else] + ${theme.message("{description}webauthn-reauth-add-credential")} + [/#if] + +

+ +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="webAuthnRegisterRequest"/] + [@helpers.hidden name="workflow" value="reauthentication"/] + +
+ [#-- Default the displayName on initial render if not alread set. --] + [#if !(displayName??) && request.method == "GET"] + [#global displayName = theme.message('unnamed')/] + [/#if] + + [@helpers.input type="text" name="displayName" id="displayName" label="${theme.message('display-name')}" autocomplete="off" autofocus=true required=true/] +
+ +
+ [@helpers.button icon="key" name="action" value="register" text=theme.message("register") /] +
+ +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/passwordChange.ftl b/kickstart/templates/passwordChange.ftl new file mode 100644 index 0000000..f45f8e7 --- /dev/null +++ b/kickstart/templates/passwordChange.ftl @@ -0,0 +1,53 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.util.UUID" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="passwordValidationRules" type="io.fusionauth.domain.PasswordValidationRules" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('password-change-title')] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="changePasswordId"/] + + [#-- Show the Password Validation Rules if there is a field error for 'password' --] + [#if (fieldMessages?keys?seq_contains("password")!false) && passwordValidationRules??] + [@helpers.passwordRules passwordValidationRules/] + [/#if] +
+ [@helpers.input type="password" name="password" autocomplete="new-password" id="password" placeholder=theme.message('password') leftAddon="lock" autofocus=true required=true/] + [@helpers.input type="password" name="passwordConfirm" autocomplete="new-password" id="passwordConfirm" placeholder=theme.message('passwordConfirm') leftAddon="lock" required=true/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+ + [#-- Show checkbox for remember me - we are in an OAuth2 workflow --] + [#if client_id?has_content] + [@helpers.input id="rememberDevice" type="checkbox" name="rememberDevice" label=theme.message('remember-device') value="true" uncheckedValue="false"] + [#t/] + [/@helpers.input] + [/#if] + +
+ [@helpers.button text=theme.message('submit')/] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/passwordComplete.ftl b/kickstart/templates/passwordComplete.ftl new file mode 100644 index 0000000..6e7b112 --- /dev/null +++ b/kickstart/templates/passwordComplete.ftl @@ -0,0 +1,28 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('password-changed-title')] +

+ ${theme.message('password-changed')} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/passwordForgot.ftl b/kickstart/templates/passwordForgot.ftl new file mode 100644 index 0000000..e9bd1c0 --- /dev/null +++ b/kickstart/templates/passwordForgot.ftl @@ -0,0 +1,41 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('forgot-password-title')] +
+ [@helpers.oauthHiddenFields/] + +

+ ${theme.message('forgot-password')} +

+
+ [@helpers.input type="text" name="loginId" id="loginId" autocapitalize="none" autofocus=true autocomplete="on" autocorrect="off" placeholder=theme.message('loginId') leftAddon="user" required=true/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+
+ [@helpers.button text=theme.message('submit')/] +

[@helpers.link url="/oauth2/authorize"]${theme.message('return-to-login')}[/@helpers.link]

+
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/passwordSent.ftl b/kickstart/templates/passwordSent.ftl new file mode 100644 index 0000000..ca4a616 --- /dev/null +++ b/kickstart/templates/passwordSent.ftl @@ -0,0 +1,29 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="loginId" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('forgot-password-message-sent-title')] +

+ ${theme.message('forgot-password-message-sent', loginId)} +

+

[@helpers.link url="/oauth2/authorize"]${theme.message('return-to-login')}[/@helpers.link]

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/phoneComplete.ftl b/kickstart/templates/phoneComplete.ftl new file mode 100644 index 0000000..116b8a0 --- /dev/null +++ b/kickstart/templates/phoneComplete.ftl @@ -0,0 +1,27 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("phone-verification-complete-title")] +

+ ${theme.message("phone-verification-complete")} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/phoneSent.ftl b/kickstart/templates/phoneSent.ftl new file mode 100644 index 0000000..fcb3794 --- /dev/null +++ b/kickstart/templates/phoneSent.ftl @@ -0,0 +1,28 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="phoneNumber" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("phone-verification-sent-title")] +

+ ${theme.message("phone-verification-sent", phoneNumber)} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/phoneVerificationRequired.ftl b/kickstart/templates/phoneVerificationRequired.ftl new file mode 100644 index 0000000..40b4dc0 --- /dev/null +++ b/kickstart/templates/phoneVerificationRequired.ftl @@ -0,0 +1,91 @@ +[#ftl/] +[#-- @ftlvariable name="allowPhoneNumberChange" type="boolean" --] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="collectVerificationCode" type="boolean" --] +[#-- @ftlvariable name="phoneNumber" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="verificationId" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("phone-verification-required-title")] + [#-- The user does not have a verified phone number. Add optional messaging here with instruction to the user. --] + + [#-- Let the user know why they ended up here --] +

+ ${theme.message("{description}phone-verification-required")} +

+ + [#-- If configured, collect the verification code on this form, this means the user sits here until they verify their phone number. --] + [#if collectVerificationCode] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="verify"/] + [@helpers.hidden name="collectVerificationCode"/] + [@helpers.hidden name="phoneNumber"/] + [@helpers.hidden name="verificationId"/] +
+ [@helpers.input type="text" name="oneTimeCode" id="otp" autocapitalize="none" autofocus=true autocomplete="one-time-code" autocorrect="off" placeholder="${theme.message('code')}" leftAddon="lock"/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+
+ [@helpers.button text=theme.message("submit")/] +
+
+ [#else] +

${theme.message("{description}phone-verification-required-non-interactive")}

+ [/#if] + + [#-- Resend a verification SMS --] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="resend"/] + [@helpers.hidden name="collectVerificationCode"/] + [@helpers.hidden name="phoneNumber"/] +
+ +
+
+ + [#-- If configured to allow a phone number change, present the user with a form. This is intended to assist the user if they mis-typed their phone number previously. --] + [#if allowPhoneNumberChange] +
+
+
${theme.message("or")}
+
+
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="changePhoneNumber"/] + [@helpers.hidden name="allowPhoneNumberChange"/] + [@helpers.hidden name="collectVerificationCode"/] +

+ ${theme.message("{description}phone-verification-required-change-phone")} +

+
+ [@helpers.input type="text" name="phoneNumber" id="phone" autocapitalize="none" autofocus=true autocomplete="on" autocorrect="off" placeholder="${theme.message('phone')}" leftAddon="user"/] +
+
+ [@helpers.button text=theme.message("submit")/] +
+
+ [/#if] + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/phoneVerify.ftl b/kickstart/templates/phoneVerify.ftl new file mode 100644 index 0000000..bc7052f --- /dev/null +++ b/kickstart/templates/phoneVerify.ftl @@ -0,0 +1,42 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="verificationId" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("phone-verification-form-title")] + [#-- FusionAuth automatically handles errors that occur during phone verification and outputs them in the HTML --] +
+ [@helpers.hidden name="captcha_token"/] + [@helpers.hidden name="client_id"/] + [@helpers.hidden name="tenantId"/] +

+ ${theme.message("phone-verification-form")} +

+
+ [@helpers.input type="text" name="phoneNumber" id="phone" autocapitalize="none" autofocus=true autocomplete="on" autocorrect="off" placeholder="${theme.message('phone')}" leftAddon="user"/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+
+ [@helpers.button text=theme.message("submit")/] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/registrationComplete.ftl b/kickstart/templates/registrationComplete.ftl new file mode 100644 index 0000000..4397530 --- /dev/null +++ b/kickstart/templates/registrationComplete.ftl @@ -0,0 +1,27 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('registration-verification-complete-title')] +

+ ${theme.message('registration-verification-complete')} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/registrationSend.ftl b/kickstart/templates/registrationSend.ftl new file mode 100644 index 0000000..81f3eec --- /dev/null +++ b/kickstart/templates/registrationSend.ftl @@ -0,0 +1,29 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="email" type="java.lang.String" --] +[#-- @ftlvariable name="emailSent" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('registration-verification-sent-title')] +

+ ${theme.message('registration-verification-sent', email)} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/registrationSent.ftl b/kickstart/templates/registrationSent.ftl new file mode 100644 index 0000000..81f3eec --- /dev/null +++ b/kickstart/templates/registrationSent.ftl @@ -0,0 +1,29 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="email" type="java.lang.String" --] +[#-- @ftlvariable name="emailSent" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('registration-verification-sent-title')] +

+ ${theme.message('registration-verification-sent', email)} +

+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/registrationVerificationRequired.ftl b/kickstart/templates/registrationVerificationRequired.ftl new file mode 100644 index 0000000..5ab0545 --- /dev/null +++ b/kickstart/templates/registrationVerificationRequired.ftl @@ -0,0 +1,65 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="collectVerificationCode" type="boolean" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="verificationId" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [#-- Custom code goes here --] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('registration-verification-required-title')] + [#-- The user does not have a verified registration. Add optionall messaging here with instruction to the user. --] + + [#-- Let the user know why they ended up here --] +

+ ${theme.message("{description}registration-verification-required")} +

+ + [#-- If configured, collect the verification code on this form, this means the user sits here until they verify their registration. --] + [#if collectVerificationCode] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="verify"/] + [@helpers.hidden name="collectVerificationCode"/] + [@helpers.hidden name="verificationId"/] +
+ [@helpers.input type="text" name="oneTimeCode" id="otp" autocapitalize="none" autofocus=true autocomplete="one-time-code" autocorrect="off" placeholder="${theme.message('code')}" leftAddon="lock"/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+
+ [@helpers.button text=theme.message('submit')/] +
+
+ [#else] +

${theme.message("{description}registration-verification-required-non-interactive")}

+ [/#if] + + [#-- Resend a verification email --] +
+ [@helpers.oauthHiddenFields/] + [@helpers.hidden name="action" value="resend"/] + [@helpers.hidden name="collectVerificationCode"/] +
+ +
+
+ + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/registrationVerify.ftl b/kickstart/templates/registrationVerify.ftl new file mode 100644 index 0000000..8906650 --- /dev/null +++ b/kickstart/templates/registrationVerify.ftl @@ -0,0 +1,42 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="showCaptcha" type="boolean" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#-- @ftlvariable name="verificationId" type="java.lang.String" --] +[#import "../_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head] + [@helpers.captchaScripts showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] + [/@helpers.head] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message('registration-verification-form-title')] + [#-- FusionAuth automatically handles errors that occur during registration verification and outputs them in the HTML --] +
+ [@helpers.hidden name="captcha_token"/] + [@helpers.hidden name="client_id"/] + [@helpers.hidden name="tenantId"/] +

+ ${theme.message('registration-verification-form')} +

+
+ [@helpers.input type="text" name="email" id="email" autocapitalize="none" autofocus=true autocomplete="on" autocorrect="off" placeholder="${theme.message('email')}" leftAddon="user"/] + [@helpers.captchaBadge showCaptcha=showCaptcha captchaMethod=tenant.captchaConfiguration.captchaMethod siteKey=tenant.captchaConfiguration.siteKey/] +
+
+ [@helpers.button text=theme.message('submit')/] +
+
+ [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/samlv2Logout.ftl b/kickstart/templates/samlv2Logout.ftl new file mode 100644 index 0000000..a63a949 --- /dev/null +++ b/kickstart/templates/samlv2Logout.ftl @@ -0,0 +1,51 @@ +[#ftl/] +[#-- @ftlvariable name="allLogoutURLs" type="java.util.Set" --] +[#-- @ftlvariable name="registeredLogoutURLs" type="java.util.Set" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "../_helpers.ftl" as helpers/] + +[#-- You may adjust the duration that we wait before completing the logout. --] +[#assign logoutDurationInSeconds = 2 /] + +[@helpers.html] + [@helpers.head title=theme.message("logout-title")/] + [@helpers.body] + [@helpers.header] + [#-- Custom header code goes here --] + [/@helpers.header] + + [@helpers.main title=theme.message("logging-out")] +
+
+
+
+ [/@helpers.main] + + [#-- Use allLogoutURLs to call the logout URL of all applications in the tenant, or use registeredLogoutURLs to log out of just the applications the user is currently registered. + Note, that just because a user does not currently have a registration, does not neccessarily mean the user does not hold a session with an application. It is possible the user has been un-registered + recently, or an application may have created a session for a user regardless of their registration. In most cases it is safest to simply call all applications and ensure that the Single Logout + URL can handle logout requests for users that may or may not have a session with that application. + --] + [#list allLogoutURLs![] as logoutURL] + + [/#list] +
+ [@helpers.hidden name="binding"/] + [@helpers.hidden name="RelayState"/] + [@helpers.hidden name="SAMLRequest"/] + [@helpers.hidden name="Signature"/] + [@helpers.hidden name="SigAlg"/] + [@helpers.hidden name="tenantId"/] +
+ + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html] diff --git a/kickstart/templates/unauthorized.ftl b/kickstart/templates/unauthorized.ftl new file mode 100644 index 0000000..cd1ead7 --- /dev/null +++ b/kickstart/templates/unauthorized.ftl @@ -0,0 +1,40 @@ +[#ftl/] +[#-- @ftlvariable name="application" type="io.fusionauth.domain.Application" --] +[#-- @ftlvariable name="cause" type="java.lang.String" --] +[#-- @ftlvariable name="client_id" type="java.lang.String" --] +[#-- @ftlvariable name="currentUser" type="io.fusionauth.domain.User" --] +[#-- @ftlvariable name="incidentId" type="java.lang.String" --] +[#-- @ftlvariable name="tenant" type="io.fusionauth.domain.Tenant" --] +[#-- @ftlvariable name="tenantId" type="java.util.UUID" --] +[#import "_helpers.ftl" as helpers/] + +[@helpers.html] + [@helpers.head title=theme.message("unauthorized")/] + [@helpers.body] + + [@helpers.main title=theme.message("access-denied") colClass="col-xs col-sm-10 col-md-8 col-lg-7 col-xl-5"] + [#assign incidentId = (request.getAttribute("incidentId")!'')/] + [#assign incidentCause = (request.getAttribute("incidentCause")!'')/] + + [#if incidentCause?has_content && incidentCause == "BlockedIPAddressException"] + ${theme.message('unauthorized-message-blocked-ip', currentBaseURL)} + [#else] + ${theme.message("unauthorized-message")} + [/#if] +

+ ${theme.message("ip-address")}${theme.message("propertySeparator")} ${currentIPAddress} + [#assign currentLocation = fusionAuth.currentLocation()!{}/] + [#if currentLocation?has_content] +
${theme.message("location")}${theme.message("propertySeparator")} ${currentLocation.displayString} + [/#if] +

+ +
+ [#if incidentId?has_api]${theme.message("incident-id")}${theme.message("propertySeparator")} ${incidentId} · [/#if]${theme.message("security-by")} FusionAuth + [/@helpers.main] + + [@helpers.footer] + [#-- Custom footer code goes here --] + [/@helpers.footer] + [/@helpers.body] +[/@helpers.html]