Setup user authentication for login-flow
This commit is contained in:
parent
8d6ff1ae94
commit
9390f5b920
122
app/assets/auth/forms.css
Normal file
122
app/assets/auth/forms.css
Normal file
@ -0,0 +1,122 @@
|
||||
:root {
|
||||
--input-padding-x: 1.5rem;
|
||||
--input-padding-y: 0.75rem;
|
||||
}
|
||||
|
||||
.login,
|
||||
.image {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.bg-image {
|
||||
background-image: url('https://source.unsplash.com/4812YdII6W0/2592x1728');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.login-heading {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.btn-login {
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.05rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
.form-label-group {
|
||||
position: relative;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.form-label-group>input,
|
||||
.form-label-group>label {
|
||||
padding: var(--input-padding-y) var(--input-padding-x);
|
||||
height: auto;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
.form-label-group>label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
/* Override default `<label>` margin */
|
||||
line-height: 1.5;
|
||||
color: #495057;
|
||||
cursor: text;
|
||||
/* Match the input under the label */
|
||||
border: 1px solid transparent;
|
||||
border-radius: .25rem;
|
||||
transition: all .1s ease-in-out;
|
||||
}
|
||||
|
||||
.form-label-group input::-webkit-input-placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.form-label-group input:-ms-input-placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.form-label-group input::-ms-input-placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.form-label-group input::-moz-placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.form-label-group input::placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.form-label-group input:not(:placeholder-shown) {
|
||||
padding-top: calc(var(--input-padding-y) + var(--input-padding-y) * (2 / 3));
|
||||
padding-bottom: calc(var(--input-padding-y) / 3);
|
||||
}
|
||||
|
||||
.form-label-group input:not(:placeholder-shown)~label {
|
||||
padding-top: calc(var(--input-padding-y) / 3);
|
||||
padding-bottom: calc(var(--input-padding-y) / 3);
|
||||
font-size: 12px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.form-error-message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-submit-button {
|
||||
margin-top: 50px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
/* Fallback for Edge
|
||||
-------------------------------------------------- */
|
||||
|
||||
@supports (-ms-ime-align: auto) {
|
||||
.form-label-group>label {
|
||||
display: none;
|
||||
}
|
||||
.form-label-group input::-ms-input-placeholder {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback for IE
|
||||
-------------------------------------------------- */
|
||||
|
||||
@media all and (-ms-high-contrast: none),
|
||||
(-ms-high-contrast: active) {
|
||||
.form-label-group>label {
|
||||
display: none;
|
||||
}
|
||||
.form-label-group input:-ms-input-placeholder {
|
||||
color: #777;
|
||||
}
|
||||
}
|
@ -12,16 +12,11 @@ class Home extends Controller {
|
||||
* Serve the main welcome page.
|
||||
*/
|
||||
welcome(req, res){
|
||||
|
||||
/*
|
||||
* Return the welcome view.
|
||||
* The page() method is added by Flitter and passes some
|
||||
* helpful contextual data to the view as well.
|
||||
*/
|
||||
return res.page('welcome', {
|
||||
user: req.user,
|
||||
T: req.T,
|
||||
})
|
||||
if ( req.user ) {
|
||||
return res.redirect('/app')
|
||||
} else {
|
||||
return res.redirect('/auth/login')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
12
app/controllers/auth/Forms.controller.js
Normal file
12
app/controllers/auth/Forms.controller.js
Normal file
@ -0,0 +1,12 @@
|
||||
const FormController = require('flitter-auth/controllers/Forms')
|
||||
|
||||
/*
|
||||
* Handles views and processing for auth registration/login/logout/etc.
|
||||
* Most handlers are inherited from the default flitter-auth/controllers/Forms
|
||||
* controller, however you can override them here as you need.
|
||||
*/
|
||||
class Forms extends FormController {
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = Forms
|
16
app/controllers/auth/KeyAction.controller.js
Normal file
16
app/controllers/auth/KeyAction.controller.js
Normal file
@ -0,0 +1,16 @@
|
||||
const Controller = require('flitter-auth/controllers/KeyAction')
|
||||
|
||||
/*
|
||||
* KeyAction Controller
|
||||
* -------------------------------------------------------------
|
||||
* Provides handler methods for flitter-auth's key actions.
|
||||
* Key actions allow your application to dynamically generate
|
||||
* one-time links that call methods on controllers and (optionally)
|
||||
* can even automatically sign in a user for the request, then log
|
||||
* them out. e.g. a password reset link could use a key action.
|
||||
*/
|
||||
class KeyAction extends Controller {
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = KeyAction
|
13
app/controllers/auth/Oauth2.controller.js
Normal file
13
app/controllers/auth/Oauth2.controller.js
Normal file
@ -0,0 +1,13 @@
|
||||
const Oauth2Controller = require('flitter-auth/controllers/Oauth2')
|
||||
|
||||
/*
|
||||
* Handles views, processing, and data retrieval for flitter-auth's
|
||||
* built-in OAuth2 server, if it is enabled. Most handlers are inherited
|
||||
* from flitter-auth/controllers/Oauth2, but you can override them here
|
||||
* as you need.
|
||||
*/
|
||||
class Oauth2 extends Oauth2Controller {
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = Oauth2
|
25
app/models/auth/KeyAction.model.js
Normal file
25
app/models/auth/KeyAction.model.js
Normal file
@ -0,0 +1,25 @@
|
||||
const Model = require('flitter-auth/model/KeyAction')
|
||||
|
||||
/*
|
||||
* KeyAction Model
|
||||
* -------------------------------------------------------------
|
||||
* Represents a single available key action. Key actions
|
||||
* are one-time use links that directly call a method on
|
||||
* a controller. These actions:
|
||||
*
|
||||
* - Can pass along context
|
||||
* - Have expiration dates
|
||||
* - Are single-use only
|
||||
* - Can automatically log in a user during the request lifecycle
|
||||
*
|
||||
* You can generate these actions using the request.security.keyaction()
|
||||
* method.
|
||||
*
|
||||
* See: module:flitter-auth/SecurityContext~SecurityContext#keyaction
|
||||
* See: module:flitter-auth/model/KeyAction~KeyAction
|
||||
*/
|
||||
class KeyAction extends Model {
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = KeyAction
|
18
app/models/auth/User.model.js
Normal file
18
app/models/auth/User.model.js
Normal file
@ -0,0 +1,18 @@
|
||||
const AuthUser = require('flitter-auth/model/User')
|
||||
|
||||
/*
|
||||
* Auth user model. This inherits fields and methods from the default
|
||||
* flitter-auth/model/User model, however you can override methods and
|
||||
* properties here as you need.
|
||||
*/
|
||||
class User extends AuthUser {
|
||||
static get schema() {
|
||||
return {...super.schema, ...{
|
||||
// other schema fields here
|
||||
}}
|
||||
}
|
||||
|
||||
// Other members and methods here
|
||||
}
|
||||
|
||||
module.exports = exports = User
|
@ -9,6 +9,7 @@
|
||||
* routes file.
|
||||
*/
|
||||
const Middleware = [
|
||||
"auth:Utility",
|
||||
|
||||
// Injects the RequestLocalizationHelper
|
||||
"i18n:Localize",
|
||||
|
15
app/routing/middleware/auth/GuestOnly.middleware.js
Normal file
15
app/routing/middleware/auth/GuestOnly.middleware.js
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* GuestOnly Middleware
|
||||
* -------------------------------------------------------------
|
||||
* Allows the request to proceed unless there's an authenticated user
|
||||
* in the session. If so, redirect to the auth flow destination if one
|
||||
* exists. If not, redirect to the default login route.
|
||||
*/
|
||||
const Middleware = require('flitter-auth/middleware/GuestOnly')
|
||||
class GuestOnly extends Middleware {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = GuestOnly
|
12
app/routing/middleware/auth/KeyAction.middleware.js
Normal file
12
app/routing/middleware/auth/KeyAction.middleware.js
Normal file
@ -0,0 +1,12 @@
|
||||
const Middleware = require('flitter-auth/middleware/KeyAction')
|
||||
|
||||
/*
|
||||
* KeyAction Middleware
|
||||
* -------------------------------------------------------------
|
||||
* Middleware for processing key actions.
|
||||
*/
|
||||
class KeyAction extends Middleware {
|
||||
|
||||
}
|
||||
|
||||
module.exports = exports = KeyAction
|
14
app/routing/middleware/auth/Oauth2TokenOnly.middleware.js
Normal file
14
app/routing/middleware/auth/Oauth2TokenOnly.middleware.js
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Oauth2TokenOnly Middleware
|
||||
* -------------------------------------------------------------
|
||||
* Allows the request to proceed if a valid OAuth2 bearer token was
|
||||
* provided. If not, return a JSON-encoded error message.
|
||||
*/
|
||||
const Middleware = require('flitter-auth/middleware/Oauth2TokenOnly')
|
||||
class Oauth2TokenOnly extends Middleware {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = Oauth2TokenOnly
|
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* ProviderRegistrationEnabled Middleware
|
||||
* -------------------------------------------------------------
|
||||
* Redirects the user to the login page if the registration page for
|
||||
* a particular auth provider is not enabled.
|
||||
*/
|
||||
const Middleware = require('flitter-auth/middleware/ProviderRegistrationEnabled')
|
||||
class ProviderRegistrationEnabled extends Middleware {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = ProviderRegistrationEnabled
|
15
app/routing/middleware/auth/ProviderRoute.middleware.js
Normal file
15
app/routing/middleware/auth/ProviderRoute.middleware.js
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Auth ProviderRoute Middleware
|
||||
* -------------------------------------------------------------
|
||||
* Many auth routes specify the name of a particular auth provider to
|
||||
* use. This middleware looks up the provider by that name and injects
|
||||
* it into the request.
|
||||
*/
|
||||
const Middleware = require('flitter-auth/middleware/ProviderRoute')
|
||||
class ProviderRoute extends Middleware {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = ProviderRoute
|
15
app/routing/middleware/auth/UserOnly.middleware.js
Normal file
15
app/routing/middleware/auth/UserOnly.middleware.js
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* UserOnly Middleware
|
||||
* -------------------------------------------------------------
|
||||
* Allows the request to proceed if there's an authenticated user
|
||||
* in the session. Otherwise, redirects the user to the login page
|
||||
* of the default provider.
|
||||
*/
|
||||
const Middleware = require('flitter-auth/middleware/UserOnly')
|
||||
class UserOnly extends Middleware {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = UserOnly
|
15
app/routing/middleware/auth/Utility.middleware.js
Normal file
15
app/routing/middleware/auth/Utility.middleware.js
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Auth Utility Middleware
|
||||
* -------------------------------------------------------------
|
||||
* This should be applied globally. Ensures basic things about the
|
||||
* request are true. For example, it provides the auth session data
|
||||
* and handles auth flow.
|
||||
*/
|
||||
const Middleware = require('flitter-auth/middleware/Utility')
|
||||
class Utility extends Middleware {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = Utility
|
113
app/routing/routers/auth/forms.routes.js
Normal file
113
app/routing/routers/auth/forms.routes.js
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Auth Form Routes
|
||||
* -------------------------------------------------------------
|
||||
* The routes here pertain to auth forms like register/login etc.
|
||||
* The general structure is as follows:
|
||||
*
|
||||
* /auth/{provider name}/{action}
|
||||
|
||||
* Individual providers may be interacted with individually, therefore:
|
||||
*
|
||||
* /auth/flitter/register
|
||||
*
|
||||
* You can omit the provider name to use the default provider:
|
||||
*
|
||||
* /auth/register
|
||||
*/
|
||||
const index = {
|
||||
|
||||
prefix: '/auth',
|
||||
|
||||
middleware: [
|
||||
|
||||
],
|
||||
|
||||
get: {
|
||||
'/:provider/register': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'middleware::auth:ProviderRegistrationEnabled',
|
||||
'controller::auth:Forms.registration_provider_get',
|
||||
],
|
||||
'/register': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'middleware::auth:ProviderRegistrationEnabled',
|
||||
'controller::auth:Forms.registration_provider_get',
|
||||
],
|
||||
|
||||
'/:provider/login': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'controller::auth:Forms.login_provider_get',
|
||||
],
|
||||
'/login': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'controller::auth:Forms.login_provider_get',
|
||||
],
|
||||
|
||||
'/:provider/logout': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:UserOnly',
|
||||
'controller::auth:Forms.logout_provider_clean_session',
|
||||
|
||||
// Note, this separation is between when the auth action has happened properly
|
||||
// and before the user is allowed to continue. You can use it to add your own
|
||||
// custom middleware for auth flow handling.
|
||||
|
||||
'controller::auth:Forms.logout_provider_present_success',
|
||||
],
|
||||
'/logout': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:UserOnly',
|
||||
'controller::auth:Forms.logout_provider_clean_session',
|
||||
'controller::auth:Forms.logout_provider_present_success',
|
||||
],
|
||||
},
|
||||
|
||||
post: {
|
||||
'/:provider/register': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'middleware::auth:ProviderRegistrationEnabled',
|
||||
'controller::auth:Forms.registration_provider_create_user',
|
||||
'controller::auth:Forms.registration_provider_present_user_created',
|
||||
],
|
||||
'/register': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'middleware::auth:ProviderRegistrationEnabled',
|
||||
'controller::auth:Forms.registration_provider_create_user',
|
||||
'controller::auth:Forms.registration_provider_present_user_created',
|
||||
],
|
||||
|
||||
'/:provider/login': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'controller::auth:Forms.login_provider_authenticate_user',
|
||||
'controller::auth:Forms.login_provider_present_success',
|
||||
],
|
||||
'/login': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:GuestOnly',
|
||||
'controller::auth:Forms.login_provider_authenticate_user',
|
||||
'controller::auth:Forms.login_provider_present_success',
|
||||
],
|
||||
|
||||
'/:provider/logout': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:UserOnly',
|
||||
'controller::auth:Forms.logout_provider_clean_session',
|
||||
'controller::auth:Forms.logout_provider_present_success',
|
||||
],
|
||||
'/logout': [
|
||||
'middleware::auth:ProviderRoute',
|
||||
'middleware::auth:UserOnly',
|
||||
'controller::auth:Forms.logout_provider_clean_session',
|
||||
'controller::auth:Forms.logout_provider_present_success',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = exports = index
|
16
app/routing/routers/auth/keyaction.routes.js
Normal file
16
app/routing/routers/auth/keyaction.routes.js
Normal file
@ -0,0 +1,16 @@
|
||||
module.exports = exports = {
|
||||
prefix: '/auth/action', // This is assumed by flitter-auth. Don't change it.
|
||||
middleware: [],
|
||||
get: {
|
||||
'/:key': [
|
||||
'middleware::auth:KeyAction',
|
||||
'controller::auth:KeyAction.handle',
|
||||
],
|
||||
},
|
||||
post: {
|
||||
'/:key': [
|
||||
'middleware::auth:KeyAction',
|
||||
'controller::auth:KeyAction.handle',
|
||||
],
|
||||
},
|
||||
}
|
46
app/routing/routers/auth/oauth2.routes.js
Normal file
46
app/routing/routers/auth/oauth2.routes.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* oauth2 Routes
|
||||
* -------------------------------------------------------------
|
||||
* Routes pertaining to the flitter-auth OAuth2 server implementation.
|
||||
*/
|
||||
const oauth2 = {
|
||||
|
||||
// Route prefix for all below routes
|
||||
prefix: '/auth/service/oauth2/',
|
||||
|
||||
middleware: [
|
||||
// Return 404 errors for these routes if the oauth2 server isn't enabled
|
||||
['util:Config', {key: 'auth.servers.oauth2.enable'}],
|
||||
],
|
||||
|
||||
get: {
|
||||
// Show the authorization page
|
||||
'/authorize': [
|
||||
'middleware::auth:UserOnly',
|
||||
'controller::auth:Oauth2.authorize_get',
|
||||
],
|
||||
|
||||
// Built-in data endpoints
|
||||
// Get the user info using a bearer token
|
||||
'/data/user': [
|
||||
['util:Config', {key: 'auth.servers.oauth2.build_in_endpoints.user.enable'}],
|
||||
'middleware::auth:Oauth2TokenOnly',
|
||||
'controller::auth:Oauth2.data_user_get',
|
||||
],
|
||||
},
|
||||
|
||||
post: {
|
||||
// Handle a successful authorization
|
||||
'/authorize': [
|
||||
'middleware::auth:UserOnly',
|
||||
'controller::auth:Oauth2.authorize_post',
|
||||
],
|
||||
|
||||
// Redeem an authorization code for an OAuth2 bearer token
|
||||
'/redeem': [
|
||||
'controller::auth:Oauth2.redeem_token',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = oauth2
|
16
app/views/auth/auth_page.pug
Normal file
16
app/views/auth/auth_page.pug
Normal file
@ -0,0 +1,16 @@
|
||||
html
|
||||
head
|
||||
title #{title} | #{_app.name}
|
||||
meta(name='viewport' content='width=device-width initial-scale=1')
|
||||
link(rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css')
|
||||
link(rel='stylesheet' href='/assets/auth/forms.css')
|
||||
body
|
||||
.container-fluid
|
||||
.row.no-gutter
|
||||
.col-md-12.col-lg-6.offset-lg-3
|
||||
.login.d-flex.align-items-center.py-5
|
||||
.container
|
||||
.row
|
||||
.col-md-9.col-lg-8.mx-auto
|
||||
block content
|
||||
script(src='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css')
|
9
app/views/auth/form.pug
Normal file
9
app/views/auth/form.pug
Normal file
@ -0,0 +1,9 @@
|
||||
extends ./auth_page
|
||||
|
||||
block content
|
||||
h3.login-heading.mb-4 #{heading_text}
|
||||
if errors
|
||||
each error in errors
|
||||
p.form-error-message #{error}
|
||||
form(method='post' enctype='multipart/form-data')
|
||||
block form
|
5
app/views/auth/form_page.pug
Normal file
5
app/views/auth/form_page.pug
Normal file
@ -0,0 +1,5 @@
|
||||
extends ./auth_page
|
||||
|
||||
block content
|
||||
h3.login-heading.mb-4 #{message}
|
||||
a.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(href=button_link) #{button_text}
|
17
app/views/auth/login.pug
Normal file
17
app/views/auth/login.pug
Normal file
@ -0,0 +1,17 @@
|
||||
extends ./form
|
||||
|
||||
block form
|
||||
.form-label-group
|
||||
input#inputUsername.form-control(type='text' name='username' value=(form_data ? form_data.username : '') required placeholder='Username' autofocus)
|
||||
label(for='inputUsername') Username
|
||||
.form-label-group
|
||||
input#inputPassword.form-control(type='password' name='password' required placeholder='Password')
|
||||
label(for='inputPassword') Password
|
||||
button.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(type='submit') Login
|
||||
|
||||
if registration_enabled
|
||||
.text-center
|
||||
span.small Need an account?
|
||||
a(href='./register') Register here.
|
||||
.text-center
|
||||
span.small(style="color: #999999;") Provider: #{provider_name}
|
12
app/views/auth/oauth2_authorize.pug
Normal file
12
app/views/auth/oauth2_authorize.pug
Normal file
@ -0,0 +1,12 @@
|
||||
extends ./auth_page
|
||||
|
||||
block content
|
||||
h3.login-heading.mb-4 Authorize #{client.name}?
|
||||
h5.login-heading.mb-4 #{client.name} wants to access basic user information about your #{_app.name} account.
|
||||
h5.login-heading.mb-4 After authorization, you may not be prompted again.
|
||||
form(method='post' enctype='multipart/form-data')
|
||||
input(type='hidden' name='redirect_uri' value=uri.toString())
|
||||
input(type='hidden' name='client_id' value=client.clientID)
|
||||
button.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(type='submit') Authorize #{client.name}
|
||||
.text-center
|
||||
span.small(style="color: #999999;") Will redirect to: #{uri.host}
|
16
app/views/auth/register.pug
Normal file
16
app/views/auth/register.pug
Normal file
@ -0,0 +1,16 @@
|
||||
extends ./form
|
||||
|
||||
block form
|
||||
.form-label-group
|
||||
input#inputUsername.form-control(type='text' name='username' value=(form_data ? form_data.username : '') required placeholder='Username' autofocus)
|
||||
label(for='inputUsername') Username
|
||||
.form-label-group
|
||||
input#inputPassword.form-control(type='password' name='password' required placeholder='Password')
|
||||
label(for='inputPassword') Password
|
||||
button.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(type='submit') Register
|
||||
.text-center
|
||||
span.small Already registered?
|
||||
a(href='./login') Log-in here.
|
||||
.text-center
|
||||
span.small(style="color: #999999;") Provider: #{provider_name}
|
||||
|
@ -1,46 +1,9 @@
|
||||
html
|
||||
head
|
||||
title #{T('welcome')} | #{_app.name}
|
||||
style(type="text/css").
|
||||
@import url('https://fonts.googleapis.com/css?family=Rajdhani');
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
background-color: #c7dbdf;
|
||||
}
|
||||
|
||||
.flitter-container {
|
||||
height: 60%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flitter-image {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.flitter-name {
|
||||
font-family: "Rajdhani";
|
||||
font-size: 50pt;
|
||||
margin-left: 35px;
|
||||
color: #00323d;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.flitter-text {
|
||||
font-family: "Rajdhani";
|
||||
font-size: 24pt;
|
||||
color: #00323d;
|
||||
}
|
||||
body
|
||||
.flitter-container
|
||||
img.flitter-image(src="/assets/flitter.png")
|
||||
a.flitter-name(href="https://flitter.garrettmills.dev/" target="_blank") #{T('powered_by_flitter')}
|
||||
if user
|
||||
.flitter-container
|
||||
p.flitter-text #{T('welcome')}, #{user.uid}! <a href="/auth/logout">#{T('log_out')}</a>
|
||||
else
|
||||
.flitter-container
|
||||
p.flitter-text #{T('new_to_flitter')} <a href="https://flitter.garrettmills.dev/" target="_blank">#{T('start_here')}</a>
|
||||
if user
|
||||
script.
|
||||
window.location.href = '/auth/login'
|
||||
else
|
||||
script.
|
||||
window.location.href = '/app'
|
177
config/auth.config.js
Normal file
177
config/auth.config.js
Normal file
@ -0,0 +1,177 @@
|
||||
const auth_config = {
|
||||
|
||||
default_provider: env('AUTH_DEFAULT_PROVIDER', 'flitter'),
|
||||
default_login_route: '/dash',
|
||||
|
||||
servers: {
|
||||
// OAuth2 authorization server
|
||||
oauth2: {
|
||||
enable: env('OAUTH2_SERVER_ENABLE', false),
|
||||
|
||||
// Grants that are available to clients. Supported types are authorization_code, password
|
||||
grants: ['authorization_code'],
|
||||
|
||||
// Built in data retrieval endpoints. These are protected by user-specific OAuth2 tokens
|
||||
built_in_endpoints: {
|
||||
|
||||
// Get the token user's data
|
||||
user: {
|
||||
enable: env('OAUTH2_SERVER_ENABLE', true),
|
||||
|
||||
// Fields to return to the endpoint
|
||||
// The keys are the keys in the request. The values are the keys in the user.
|
||||
fields: {
|
||||
username: 'uid',
|
||||
id: 'uuid',
|
||||
|
||||
// Data is a special key. It's key-value pairs are included,
|
||||
// unserialized, from the user's JSON data.
|
||||
data: {
|
||||
// Fields stored in serialized data can be included here:
|
||||
// special_field: 'some_json_data_field',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Auth provider configurations
|
||||
// You can have multiple of the same 'type' of auth source, but they
|
||||
// must have unique names. The name is the key of the source config.
|
||||
// Valid types are (by default): FlitterProvider, LdapProvider, Oauth2Provider
|
||||
sources: {
|
||||
// Default, database-backed auth provider
|
||||
flitter: {
|
||||
type: 'FlitterProvider',
|
||||
enable: env('AUTH_FLITTER_ENABLE', true),
|
||||
registration: env('AUTH_FLITTER_REGISTRATION', true),
|
||||
min_password_length: env('AUTH_MIN_PASSWORD_LENGTH', 8),
|
||||
},
|
||||
|
||||
// LDAP-backed auth provider
|
||||
example_ldap: {
|
||||
type: 'LdapProvider',
|
||||
enable: env('AUTH_LDAP_ENABLE', false),
|
||||
|
||||
host: env('AUTH_LDAP_HOST', 'localhost'),
|
||||
port: env('AUTH_LDAP_PORT', 389),
|
||||
secure: env('AUTH_LDAP_BIND_SECURE', false),
|
||||
bind_dn: env('AUTH_LDAP_BIND_DN', 'uid=auth_agent,ou=people,dc=domain,dc=local'),
|
||||
bind_secret: env('AUTH_LDAP_BIND_PW'),
|
||||
|
||||
user_search_base: env('AUTH_LDAP_SEARCH_BASE', 'ou=people,dc=domain,dc=local'),
|
||||
user_filter: env('AUTH_LDAP_USER_FILTER', '(uid=%u)'), // %u is the login provided username
|
||||
|
||||
min_password_length: env('AUTH_MIN_PASSWORD_LENGTH', 8),
|
||||
|
||||
// Maps flitter-auth roles to LDAP groups
|
||||
role_groups: {
|
||||
// Should correspond to existing auth roles
|
||||
// role_name: 'cn=somegroup,ou=groups,dc=domain,dc=local',
|
||||
},
|
||||
|
||||
// Maps user attributes to LDAP data attributes
|
||||
attributes: {
|
||||
uid: env('AUTH_LDAP_ATTR_UID', 'uid'),
|
||||
first_name: env('AUTH_LDAP_ATTR_FIRST_NAME', 'cn'),
|
||||
last_name: env('AUTH_LDAP_ATTR_LAST_NAME', 'sn'),
|
||||
email: env('AUTH_LDAP_ATTR_EMAIL', 'mail'),
|
||||
|
||||
// Special case - used to determine group memberships
|
||||
group_membership: env('AUTH_LDAP_ATTR_GROUPS', 'memberOf'),
|
||||
},
|
||||
|
||||
registration: env('AUTH_LDAP_REGISTRATION', false),
|
||||
|
||||
// Default attributes for new registered users
|
||||
// %u can be used to interpolate the registered user's uid
|
||||
registration_merge_attributes: {
|
||||
objectClass: ['posixAccount', 'shadowAccount', 'inetOrgPerson'],
|
||||
sn: '%u',
|
||||
cn: '%u',
|
||||
gecos: '%u',
|
||||
uidNumber: -1,
|
||||
gidNumber: -1,
|
||||
homeDirectory: '/dev/null',
|
||||
},
|
||||
},
|
||||
|
||||
example_oauth: {
|
||||
type: 'Oauth2Provider',
|
||||
enable: env('AUTH_OAUTH2_ENABLE', false),
|
||||
|
||||
source_name: env('AUTH_OAUTH2_SOURCE_NAME', 'GitHub'),
|
||||
source_client_id: env('AUTH_OAUTH2_CLIENT_ID'),
|
||||
source_client_secret: env('AUTH_OAUTH2_CLIENT_SECRET'),
|
||||
|
||||
// Login page destination where the user will be redirected to on login
|
||||
// %c will be interpolated with the client id
|
||||
// %r will be interpolated with the redirect callback url
|
||||
// NOTE: This url is the same as the login page - /auth/oauth2/login
|
||||
source_login_page: env('AUTH_OAUTH2_LOGIN_REDIRECT', 'https://github.com/login/oauth/authorize?client_id=%c'),
|
||||
|
||||
// Information about the OAuth2 Callback
|
||||
callback: {
|
||||
// URL query parameter name with the authorization_code token
|
||||
// e.g. ?code=XXXXXXXXXX
|
||||
token_key: 'code',
|
||||
},
|
||||
|
||||
// Information about the endpoint flitter-auth will use to redeem
|
||||
// the authorization_code token for a bearer token
|
||||
source_token: {
|
||||
endpoint: 'https://github.com/login/oauth/access_token',
|
||||
|
||||
// Field name where the authorization_code token will be specified in the request
|
||||
token_key: 'code',
|
||||
|
||||
// Field name for the client id
|
||||
client_id_key: 'client_id',
|
||||
|
||||
// Field name for the client secret
|
||||
client_secret_key: 'client_secret',
|
||||
|
||||
// Field name for the grant_type ('authorization_type')
|
||||
grant_type_key: 'grant_type',
|
||||
|
||||
// Field name where the bearer token will be specified in the response
|
||||
response_token_key: 'access_token',
|
||||
},
|
||||
|
||||
// Information about the endpoint flitter-auth will use to get
|
||||
// user information after it retrieves a bearer token
|
||||
user_data: {
|
||||
endpoint: 'https://api.github.com/user',
|
||||
method: 'get', // 'get' or 'post' only
|
||||
|
||||
// In the response data, what key is the user data in?
|
||||
// e.g. if 'data', then {'data': { ... }}
|
||||
// Set falsy to assume the data exists in the root: { ... }
|
||||
// data_root: 'data',
|
||||
|
||||
// Value that prefixes the token in the 'Authorization: ' header.
|
||||
// e.g. 'token ' would mean 'token a0fw93ja0w93ja093wj'
|
||||
// 'Bearer ' would be 'Bearer 0329j0239dj209j3209jd'
|
||||
token_prefix: 'token ',
|
||||
|
||||
// Mapping of user model attributes to OAuth2 return data from the endpoint
|
||||
// Note that uuid is not allowed, and uid is required
|
||||
attributes: {
|
||||
uid: 'login',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
roles: {
|
||||
|
||||
// Roles can be defined here as arrays of permissions:
|
||||
// 'role_name': [ 'permission1', 'permission2' ],
|
||||
// Then, users with that role will automatically inherit the permissions.
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
module.exports = auth_config
|
Loading…
Reference in New Issue
Block a user