miolo 3.0.0-beta.154 → 3.0.0-beta.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create/index.mjs +1 -1
- package/bin/create/validation.mjs +1 -1
- package/package.json +4 -3
- package/src/config/.env +19 -8
- package/src/config/defaults.mjs +28 -21
- package/src/config/index.mjs +10 -17
- package/src/engines/cron/syscheck.mjs +2 -2
- package/src/middleware/auth/basic.mjs +6 -4
- package/src/middleware/auth/guest.mjs +1 -0
- package/src/middleware/auth/passport/index.mjs +299 -0
- package/src/middleware/ssr/ssr_render.mjs +4 -2
- package/src/server.mjs +5 -10
- package/template/.agent/skills/miolo-auth/SKILL.md +273 -118
- package/template/.agent/skills/miolo-session-context/SKILL.md +4 -3
- package/template/.env +9 -2
- package/template/db/sql/01_users.sql +3 -0
- package/template/package.json +7 -7
- package/template/src/cli/pages/offline/Login.jsx +0 -3
- package/template/src/cli/pages/offline/LoginForm.jsx +89 -79
- package/template/src/cli/pages/todos/context/TodosProvider.jsx +2 -2
- package/template/src/server/db/io/users/auth.mjs +36 -4
- package/template/src/server/db/triggers/user.mjs +5 -4
- package/template/src/server/miolo/auth/passport.mjs +93 -0
- package/template/src/server/miolo/db.mjs +4 -15
- package/template/src/server/miolo/index.mjs +4 -2
- package/src/middleware/auth/credentials/index.mjs +0 -183
- package/template/.env.production +0 -111
- package/template/src/server/miolo/auth/credentials.mjs +0 -47
- /package/src/middleware/auth/{credentials → passport}/session/index.mjs +0 -0
- /package/src/middleware/auth/{credentials → passport}/session/store.mjs +0 -0
- /package/src/middleware/auth/{credentials → passport}/session/store_koa_redis.mjs +0 -0
package/bin/create/index.mjs
CHANGED
|
@@ -19,7 +19,7 @@ export function validateAppName(name) {
|
|
|
19
19
|
* Validates auth method
|
|
20
20
|
*/
|
|
21
21
|
export function validateAuthMethod(authMethod) {
|
|
22
|
-
const validAuthMethods = ['
|
|
22
|
+
const validAuthMethods = ['passport', 'basic', 'guest']
|
|
23
23
|
if (!validAuthMethods.includes(authMethod)) {
|
|
24
24
|
throw new Error(`Invalid auth method: ${authMethod}. Valid options: ${validAuthMethods.join(', ')}`)
|
|
25
25
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miolo",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.155",
|
|
4
4
|
"description": "all-in-one koa-based server",
|
|
5
5
|
"author": "Donato Lorenzo <donato@afialapis.com>",
|
|
6
6
|
"contributors": [
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@koa/cors": "^5.0.0",
|
|
49
49
|
"@koa/router": "^15.3.0",
|
|
50
50
|
"@maxmind/geoip2-node": "^6.3.4",
|
|
51
|
-
"@tailwindcss/vite": "^4.
|
|
51
|
+
"@tailwindcss/vite": "^4.2.0",
|
|
52
52
|
"@vitejs/plugin-react": "^5.1.4",
|
|
53
53
|
"cacheiro": "^0.5.0-beta.5",
|
|
54
54
|
"calustra": "^1.0.0-beta.7",
|
|
@@ -73,10 +73,11 @@
|
|
|
73
73
|
"nanoid": "^5.1.6",
|
|
74
74
|
"nodemailer": "^8.0.1",
|
|
75
75
|
"passport-local": "^1.0.0",
|
|
76
|
+
"passport-google-oauth20": "^2.0.0",
|
|
76
77
|
"socket.io": "^4.8.3",
|
|
77
78
|
"socket.io-client": "^4.8.3",
|
|
78
79
|
"statuses": "^2.0.2",
|
|
79
|
-
"tailwindcss": "^4.
|
|
80
|
+
"tailwindcss": "^4.2.0",
|
|
80
81
|
"tinguir": "^0.0.7",
|
|
81
82
|
"vite": "^7.3.1",
|
|
82
83
|
"winston": "^3.19.0",
|
package/src/config/.env
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#
|
|
2
2
|
# General
|
|
3
3
|
#
|
|
4
|
+
|
|
4
5
|
MIOLO_NAME=miolo
|
|
5
6
|
MIOLO_INTRE_LOCALE=es
|
|
6
7
|
|
|
7
8
|
#
|
|
8
9
|
# HTTP
|
|
9
10
|
#
|
|
11
|
+
|
|
10
12
|
MIOLO_PORT=8001
|
|
11
13
|
MIOLO_DEV_PORT=7001
|
|
12
14
|
MIOLO_HOSTNAME=localhost
|
|
@@ -25,12 +27,20 @@ MIOLO_GEOIP_ENABLED=false
|
|
|
25
27
|
MIOLO_GEOIP_DB=/var/lib/GeoIP/GeoLite2-City.mmdb
|
|
26
28
|
MIOLO_GEOIP_LOCAL_IPS=127.0.0.1
|
|
27
29
|
|
|
30
|
+
#
|
|
31
|
+
# If google auth
|
|
32
|
+
#
|
|
33
|
+
MIOLO_AUTH_GOOGLE_CLIENT_ID=123456
|
|
34
|
+
MIOLO_AUTH_GOOGLE_CLIENT_SECRET=123456
|
|
35
|
+
MIOLO_AUTH_GOOGLE_CALLBACK_URL=auth/google/callback
|
|
36
|
+
|
|
28
37
|
#
|
|
29
38
|
# Session
|
|
30
39
|
#
|
|
40
|
+
|
|
31
41
|
MIOLO_SESSION_KEY='miolo.sess'
|
|
32
|
-
MIOLO_SESSION_SALT=
|
|
33
|
-
MIOLO_SESSION_SECRET=
|
|
42
|
+
MIOLO_SESSION_SALT=00000000-0000-0000-0000-000000000000
|
|
43
|
+
MIOLO_SESSION_SECRET=00000000-0000-0000-0000-000000000000
|
|
34
44
|
MIOLO_SESSION_MAX_AGE=864000000
|
|
35
45
|
MIOLO_SESSION_SECURE=true
|
|
36
46
|
MIOLO_SESSION_RENEW=false
|
|
@@ -39,6 +49,7 @@ MIOLO_SESSION_SAME_SITE=lax # lax | strict
|
|
|
39
49
|
#
|
|
40
50
|
# Database
|
|
41
51
|
#
|
|
52
|
+
|
|
42
53
|
MIOLO_DB_DIALECT=postgres
|
|
43
54
|
MIOLO_DB_HOST=localhost
|
|
44
55
|
MIOLO_DB_DOCKER_HOST=postgres
|
|
@@ -53,18 +64,15 @@ MIOLO_DB_POOL_MIN=0 # Minimum number of connection in pool
|
|
|
53
64
|
# for more details read https://github.com/coopernurse/node-pool/issues/178#issuecomment-327110870,
|
|
54
65
|
MIOLO_DB_POOL_IDLE_TIMEOUT_MS=10000
|
|
55
66
|
|
|
56
|
-
|
|
57
67
|
#
|
|
58
68
|
# Logging
|
|
59
69
|
#
|
|
60
|
-
MIOLO_LOG_LEVEL=verbose
|
|
61
70
|
|
|
71
|
+
MIOLO_LOG_LEVEL=verbose
|
|
62
72
|
MIOLO_LOG_CONSOLE_ENABLED=true
|
|
63
73
|
#MIOLO_LOG_CONSOLE_LEVEL=verbose
|
|
64
|
-
|
|
65
74
|
MIOLO_LOG_FILE_ENABLED=false
|
|
66
75
|
#MIOLO_LOG_FILE_LEVEL=verbose
|
|
67
|
-
|
|
68
76
|
MIOLO_LOG_FILE_PATH=/var/log/afialapis/%MIOLO%.log
|
|
69
77
|
MIOLO_LOG_MAIL_ENABLED=false
|
|
70
78
|
MIOLO_LOG_MAIL_LEVEL=error
|
|
@@ -74,6 +82,7 @@ MIOLO_LOG_MAIL_TO=noreply@mail.com
|
|
|
74
82
|
#
|
|
75
83
|
# Mailer
|
|
76
84
|
#
|
|
85
|
+
|
|
77
86
|
MIOLO_MAILER_SILENT=true
|
|
78
87
|
MIOLO_MAILER_HOST=mail.com
|
|
79
88
|
MIOLO_MAILER_PORT=25
|
|
@@ -88,6 +97,7 @@ MIOLO_MAILER_SMTP_PASS=****
|
|
|
88
97
|
#
|
|
89
98
|
# Cache
|
|
90
99
|
#
|
|
100
|
+
|
|
91
101
|
MIOLO_REDIS_HOSTNAME=localhost
|
|
92
102
|
MIOLO_REDIS_HOSTNAME_DOCKER=redis
|
|
93
103
|
MIOLO_REDIS_PORT=6379
|
|
@@ -107,13 +117,14 @@ MIOLO_DOTENVX_DEBUG=false
|
|
|
107
117
|
#
|
|
108
118
|
# Build
|
|
109
119
|
#
|
|
120
|
+
|
|
110
121
|
MIOLO_BUILD_HTML_FILE=./src/cli/index.html
|
|
111
122
|
MIOLO_BUILD_CLIENT_ENTRY=./src/cli/entry-cli.jsx
|
|
112
|
-
MIOLO_BUILD_CLIENT_DEST=./
|
|
123
|
+
MIOLO_BUILD_CLIENT_DEST=./build/cli
|
|
113
124
|
MIOLO_BUILD_CLIENT_SUFFIX=iife.bundle.min
|
|
114
125
|
MIOLO_BUILD_SERVER_SSR_ENTRY=./src/server/ssr/entry-server.jsx
|
|
115
126
|
MIOLO_BUILD_SERVER_ENTRY=./src/server/server.mjs
|
|
116
|
-
MIOLO_BUILD_SERVER_DEST=./
|
|
127
|
+
MIOLO_BUILD_SERVER_DEST=./build/server
|
|
117
128
|
MIOLO_DEV_CONFIG_ENTRY=./src/server/config.mjs
|
|
118
129
|
MIOLO_DEV_WATCH_ENABLED=true
|
|
119
130
|
MIOLO_DEV_WATCH_DIRS=./src/server
|
package/src/config/defaults.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
|
-
const SESSION_MAX_AGE = 86400 * 10 * 1000
|
|
3
2
|
|
|
3
|
+
const SESSION_MAX_AGE = 86400 * 10 * 1000
|
|
4
|
+
const root = (dir) => path.resolve(process.cwd(), dir)
|
|
4
5
|
|
|
5
6
|
//
|
|
6
7
|
// Notice `miolo` has support for `.env` files
|
|
@@ -22,8 +23,12 @@ export default function make_config_defaults() {
|
|
|
22
23
|
catcher_url: '/sys/jserror',
|
|
23
24
|
|
|
24
25
|
static: {
|
|
25
|
-
favicon: '',
|
|
26
|
-
folders: {
|
|
26
|
+
favicon: root('src/static/img/favicon.ico'),
|
|
27
|
+
folders: {
|
|
28
|
+
'/build': root('build'),
|
|
29
|
+
'/static': root('src/static'),
|
|
30
|
+
'/': root('src/static/public')
|
|
31
|
+
}
|
|
27
32
|
},
|
|
28
33
|
|
|
29
34
|
// cors can be:
|
|
@@ -108,6 +113,7 @@ export default function make_config_defaults() {
|
|
|
108
113
|
secure: process.env?.MIOLO_SESSION_SECURE === 'true',
|
|
109
114
|
|
|
110
115
|
/** (string) session cookie sameSite options (default null, don't set it) */
|
|
116
|
+
/** NOTE: Google Auth requires 'lax' */
|
|
111
117
|
sameSite: process.env.MIOLO_SESSION_SAME_SITE || 'lax', // 'strict',
|
|
112
118
|
}
|
|
113
119
|
},
|
|
@@ -351,31 +357,32 @@ export default function make_config_defaults() {
|
|
|
351
357
|
// realm: '',
|
|
352
358
|
// paths: [],
|
|
353
359
|
//},
|
|
354
|
-
//
|
|
360
|
+
//guest: {
|
|
361
|
+
// make_guest_token: undefined // (session) => ''
|
|
362
|
+
//},
|
|
363
|
+
//passport: {
|
|
355
364
|
// get_user_id: (user, done, ctx) => done(null, user.id), // default
|
|
356
365
|
// find_user_by_id: (id, done, ctx) => done(null, {id: 1}), // ok=> done(null, user) err=> done(error, null)
|
|
357
366
|
// local_auth_user: (username, password, done, ctx) => done(null, {id: 1})
|
|
358
367
|
// auth => done(null, user)
|
|
359
368
|
// noauth=> done(null, false, {message: ''})
|
|
360
369
|
// err => done(error, null)
|
|
361
|
-
//
|
|
362
|
-
//
|
|
363
|
-
//
|
|
364
|
-
//
|
|
370
|
+
// local_url_login : '/login',
|
|
371
|
+
// local_url_logout: '/logout',
|
|
372
|
+
// local_url_login_redirect: undefined
|
|
373
|
+
// local_url_logout_redirect: '/'
|
|
374
|
+
// google_auth_user: (accessToken, refreshToken, profile, done, ctx) => done(null, {id: 1})
|
|
375
|
+
// auth => done(null, user)
|
|
376
|
+
// noauth=> done(null, false, {message: ''})
|
|
377
|
+
// err => done(error, null)
|
|
378
|
+
// google_client_id: 'your-google-client-id',
|
|
379
|
+
// google_client_secret: 'your-google-client-secret',
|
|
380
|
+
// google_url_login : '/auth/google',
|
|
381
|
+
// google_url_callback : '/auth/google/callback',
|
|
382
|
+
// google_url_logout: '/logout',
|
|
383
|
+
// google_url_login_redirect: undefined
|
|
384
|
+
// google_url_logout_redirect: '/'
|
|
365
385
|
//}
|
|
366
|
-
//guest: {
|
|
367
|
-
// make_guest_token: undefined // (session) => ''
|
|
368
|
-
//},
|
|
369
|
-
//custom: callback,
|
|
370
|
-
// here callback receives (app)
|
|
371
|
-
// and returns:
|
|
372
|
-
// - a middleware function
|
|
373
|
-
// or
|
|
374
|
-
// - an array like [{
|
|
375
|
-
// method: 'GET' // POST,...
|
|
376
|
-
// url: '/aa/bb',
|
|
377
|
-
// callback: a middleware function
|
|
378
|
-
// }, ...]
|
|
379
386
|
},
|
|
380
387
|
|
|
381
388
|
middlewares: [
|
package/src/config/index.mjs
CHANGED
|
@@ -3,22 +3,6 @@ import { init_env_config } from './env.mjs'
|
|
|
3
3
|
import make_config_defaults from './defaults.mjs'
|
|
4
4
|
import {isPlainObject} from 'is-plain-object'
|
|
5
5
|
|
|
6
|
-
function _get_auth_type(config) {
|
|
7
|
-
if (config?.auth?.basic) {
|
|
8
|
-
return 'basic'
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (config?.auth?.credentials) {
|
|
12
|
-
return 'credentials'
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
if (config?.auth?.custom) {
|
|
16
|
-
return 'custom'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return 'guest'
|
|
20
|
-
}
|
|
21
|
-
|
|
22
6
|
|
|
23
7
|
export function init_config(makeConfig) {
|
|
24
8
|
// Init environment vars
|
|
@@ -32,8 +16,17 @@ export function init_config(makeConfig) {
|
|
|
32
16
|
const all_config= merge(base_config, custom_config, {isMergeableObject: isPlainObject})
|
|
33
17
|
|
|
34
18
|
// Some addendum
|
|
35
|
-
all_config.auth_type = _get_auth_type(all_config)
|
|
36
19
|
all_config.use_catcher = all_config?.http?.catcher_url ? true : false
|
|
37
20
|
|
|
21
|
+
for (const auth_type of ['guest', 'basic', 'passport']) {
|
|
22
|
+
if (all_config.auth?.[auth_type] == undefined) {
|
|
23
|
+
all_config.auth[auth_type] = {
|
|
24
|
+
enabled: false
|
|
25
|
+
}
|
|
26
|
+
} else if (all_config.auth[auth_type]?.enabled == undefined) {
|
|
27
|
+
all_config.auth[auth_type].enabled = true
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
38
31
|
return all_config
|
|
39
32
|
}
|
|
@@ -23,7 +23,7 @@ function _sys_check_and_log(logger) {
|
|
|
23
23
|
const perc= Math.round( (used*100)/total, 2)
|
|
24
24
|
|
|
25
25
|
if (perc>80) {
|
|
26
|
-
logger.
|
|
26
|
+
logger.warn(`[cron][${cyan('SysCheck')}] RAM ${yellow(used)} MB used of ${green(total)} MB (${yellow(perc)} %)`)
|
|
27
27
|
} else {
|
|
28
28
|
logger.info(`[cron][${cyan('SysCheck')}] RAM ${yellow(used)} MB used of ${green(total)} MB (${yellow(perc)} %)`)
|
|
29
29
|
}
|
|
@@ -36,7 +36,7 @@ function _sys_check_and_log(logger) {
|
|
|
36
36
|
const free = Math.round(_toGB(result.free), 2)
|
|
37
37
|
|
|
38
38
|
if (free<1) {
|
|
39
|
-
logger.
|
|
39
|
+
logger.warn(`[cron][${cyan('SysCheck')}] DISK ${yellow(used)} GB used of ${green(total)} GB (${yellow(free)} GB free)`)
|
|
40
40
|
} else {
|
|
41
41
|
logger.info(`[cron][${cyan('SysCheck')}] DISK ${yellow(used)} GB used of ${green(total)} GB (${yellow(free)} GB free)`)
|
|
42
42
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import koa_mount from 'koa-mount'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const _get_basic_credentials = (req) => {
|
|
4
4
|
let sauth= req?.headers?.authorization
|
|
5
5
|
|
|
6
6
|
if (! sauth) {
|
|
@@ -31,7 +31,7 @@ const init_basic_auth_middleware = ( app, options ) => {
|
|
|
31
31
|
async function basic_auth_middleware(ctx, next) {
|
|
32
32
|
let au_user
|
|
33
33
|
try {
|
|
34
|
-
au_user=
|
|
34
|
+
au_user= _get_basic_credentials(ctx.request)
|
|
35
35
|
} catch(_) {}
|
|
36
36
|
|
|
37
37
|
const unauth_err = () => {
|
|
@@ -48,7 +48,8 @@ const init_basic_auth_middleware = ( app, options ) => {
|
|
|
48
48
|
|
|
49
49
|
ctx.session= {
|
|
50
50
|
user: undefined,
|
|
51
|
-
authenticated: false
|
|
51
|
+
authenticated: false,
|
|
52
|
+
auth_method: undefined
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
ctx.body= {
|
|
@@ -74,7 +75,8 @@ const init_basic_auth_middleware = ( app, options ) => {
|
|
|
74
75
|
|
|
75
76
|
ctx.session= {
|
|
76
77
|
user,
|
|
77
|
-
authenticated: true
|
|
78
|
+
authenticated: true,
|
|
79
|
+
auth_method: 'basic'
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
await next()
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars*/
|
|
2
|
+
import passport from 'koa-passport'
|
|
3
|
+
import LocalStrategy from 'passport-local'
|
|
4
|
+
import { Strategy as GoogleStrategy } from 'passport-google-oauth20'
|
|
5
|
+
import Router from '@koa/router'
|
|
6
|
+
import { init_session_middleware } from './session/index.mjs'
|
|
7
|
+
|
|
8
|
+
// local: {
|
|
9
|
+
// get_user_id: (user, done) => done(null, user.id), // default
|
|
10
|
+
// find_user_by_id: (id, done) => done(null, {id: 1}), // ok=> done(null, user) err=> done(error, null)
|
|
11
|
+
// local_auth_user: (username, password, done) => done(null, {id: 1})
|
|
12
|
+
// // auth=> done(null, user) noauth=> done(null, false, {message: ''}) err=> done(error, null)
|
|
13
|
+
// local_url_login : '/login',
|
|
14
|
+
// local_url_logout: '/logout',
|
|
15
|
+
// local_url_login_redirect: undefined
|
|
16
|
+
// local_url_logout_redirect: '/'
|
|
17
|
+
// google_auth_user: (accessToken, refreshToken, profile, done, ctx) => done(null, {id: 1})
|
|
18
|
+
// // auth=> done(null, user) noauth=> done(null, false, {message: ''}) err=> done(error, null)
|
|
19
|
+
// google_client_id: 'your-google-client-id',
|
|
20
|
+
// google_client_secret: 'your-google-client-secret',
|
|
21
|
+
// google_url_login : '/auth/google',
|
|
22
|
+
// google_url_callback : '/auth/google/callback',
|
|
23
|
+
// google_url_logout: '/logout',
|
|
24
|
+
// google_url_login_redirect: undefined
|
|
25
|
+
// google_url_logout_redirect: '/'
|
|
26
|
+
// }
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const def_get_user_id = (user, done, ctx) => done(null, user.id)
|
|
30
|
+
|
|
31
|
+
const def_find_user_by_id = (id, done, ctx) => {
|
|
32
|
+
const err = Error('You need to define auth.passport.find_user_by_id')
|
|
33
|
+
done(err, null)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const def_local_auth_user = (username, password, done, ctx) => {
|
|
37
|
+
const err = Error('You need to define auth.passport.local_auth_user')
|
|
38
|
+
done(err, null)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const def_google_auth_user = (accessToken, refreshToken, profile, done, ctx) => {
|
|
42
|
+
const err = Error('You need to define auth.passport.google_auth_user')
|
|
43
|
+
done(err, null)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
const init_passport_auth_middleware = ( app, options, sessionConfig, cacheConfig) => {
|
|
48
|
+
const {get_user_id, find_user_by_id, local_auth_user,
|
|
49
|
+
local_url_login, local_url_logout, local_url_login_redirect, local_url_logout_redirect, google_auth_user,
|
|
50
|
+
google_client_id, google_client_secret,
|
|
51
|
+
google_url_login, google_url_callback, google_url_logout, google_url_login_redirect, google_url_logout_redirect} = options
|
|
52
|
+
|
|
53
|
+
//const local_options = {}
|
|
54
|
+
|
|
55
|
+
// fallback funcs
|
|
56
|
+
const get_user_id_f = get_user_id || def_get_user_id
|
|
57
|
+
const find_user_by_id_f = find_user_by_id || def_find_user_by_id
|
|
58
|
+
const local_auth_user_f = local_auth_user || def_local_auth_user
|
|
59
|
+
const local_url_login_f = local_url_login || '/login'
|
|
60
|
+
const local_url_logout_f = local_url_logout || '/logout'
|
|
61
|
+
const google_auth_user_f = google_auth_user || def_google_auth_user
|
|
62
|
+
|
|
63
|
+
const google_url_login_f = google_url_login || '/auth/google'
|
|
64
|
+
const google_url_callback_f = google_url_callback || '/auth/google/callback'
|
|
65
|
+
const google_url_logout_f = google_url_logout || '/logout'
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
// init passport
|
|
69
|
+
const serialize_user = (ctx) => (user, done) => {
|
|
70
|
+
process.nextTick(function() {
|
|
71
|
+
try {
|
|
72
|
+
ctx.miolo.logger.debug(`[auth][passport] serializing user...`)
|
|
73
|
+
ctx.sessionId = ctx.session?.externalKey ? ctx.getSessionStoreKey(ctx.session?.externalKey) : undefined
|
|
74
|
+
return get_user_id_f(user, done, ctx)
|
|
75
|
+
} catch(error) {
|
|
76
|
+
ctx.miolo.logger.error(`[auth][passport] Error serializing user: ${error}`)
|
|
77
|
+
return done(error, null)
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const deserialize_user = (ctx) => (id, done) => {
|
|
83
|
+
process.nextTick(function() {
|
|
84
|
+
try {
|
|
85
|
+
ctx.miolo.logger.debug(`[auth][passport] deserializing user...`)
|
|
86
|
+
ctx.sessionId = ctx.session?.externalKey ? ctx.getSessionStoreKey(ctx.session?.externalKey) : undefined
|
|
87
|
+
return find_user_by_id_f(id, done, ctx)
|
|
88
|
+
} catch(error) {
|
|
89
|
+
ctx.miolo.logger.error(`[auth][passport] Error deserializing user: ${error}`)
|
|
90
|
+
return done(error, null)
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const local_strategy= (ctx) => new LocalStrategy.Strategy (
|
|
96
|
+
(username, password, done) => {
|
|
97
|
+
ctx.sessionId = ctx.session?.externalKey ? ctx.getSessionStoreKey(ctx.session?.externalKey) : undefined
|
|
98
|
+
return local_auth_user_f(username, password, done, ctx)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
let google_strategy
|
|
102
|
+
|
|
103
|
+
if (google_client_id) {
|
|
104
|
+
google_strategy = (ctx) => new GoogleStrategy(
|
|
105
|
+
{
|
|
106
|
+
clientID: google_client_id,
|
|
107
|
+
clientSecret: google_client_secret,
|
|
108
|
+
callbackURL: google_url_callback_f,
|
|
109
|
+
passReqToCallback: true
|
|
110
|
+
},
|
|
111
|
+
(_req, accessToken, refreshToken, profile, done) => {
|
|
112
|
+
ctx.sessionId = ctx.session?.externalKey ? ctx.getSessionStoreKey(ctx.session?.externalKey) : undefined
|
|
113
|
+
return google_auth_user_f(accessToken, refreshToken, profile, done, ctx)
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
app.use((ctx, next) => {
|
|
119
|
+
passport.serializeUser(serialize_user(ctx))
|
|
120
|
+
passport.deserializeUser(deserialize_user(ctx))
|
|
121
|
+
passport.use(local_strategy(ctx))
|
|
122
|
+
if (google_client_id) {
|
|
123
|
+
passport.use('google', google_strategy(ctx))
|
|
124
|
+
}
|
|
125
|
+
return next()
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
init_session_middleware(app, sessionConfig, cacheConfig)
|
|
130
|
+
|
|
131
|
+
app.use(passport.initialize())
|
|
132
|
+
app.use(passport.session())
|
|
133
|
+
|
|
134
|
+
async function _ensure_ctx_user (ctx, next) {
|
|
135
|
+
try{
|
|
136
|
+
if (ctx.session.authenticated) {
|
|
137
|
+
ctx.session.user = ctx.state.user
|
|
138
|
+
}
|
|
139
|
+
} catch(_) {}
|
|
140
|
+
await next()
|
|
141
|
+
}
|
|
142
|
+
app.use(_ensure_ctx_user)
|
|
143
|
+
|
|
144
|
+
// handle auth routes
|
|
145
|
+
const handleLocalLogIn = (ctx, next) => {
|
|
146
|
+
ctx.miolo.logger.debug(`[auth][local] handleLocalLogIn() - authenticating...`)
|
|
147
|
+
return passport.authenticate('local', async function(err, user, info, _status) {
|
|
148
|
+
|
|
149
|
+
if ((user === false) || (user == undefined) || (err != undefined)) {
|
|
150
|
+
ctx.miolo.logger.debug(`[auth][local] handleLocalLogIn() - user not authenticated`)
|
|
151
|
+
ctx.session.user = undefined
|
|
152
|
+
ctx.session.authenticated = false
|
|
153
|
+
ctx.session.auth_method = undefined
|
|
154
|
+
ctx.sessionId = undefined
|
|
155
|
+
|
|
156
|
+
// This will show error logs on the catcher middleware
|
|
157
|
+
// ctx.throw(401)
|
|
158
|
+
|
|
159
|
+
ctx.status= 401
|
|
160
|
+
|
|
161
|
+
ctx.body = {
|
|
162
|
+
ok: false,
|
|
163
|
+
data: {
|
|
164
|
+
user: undefined,
|
|
165
|
+
authenticated: false,
|
|
166
|
+
info: info,
|
|
167
|
+
},
|
|
168
|
+
error: err?.message || err?.stack || err
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
ctx.miolo.logger.debug(`[auth][local] handleLocalLogIn() - user authenticated`)
|
|
172
|
+
await ctx.login(user)
|
|
173
|
+
ctx.session.user = user // ctx.state.user
|
|
174
|
+
ctx.session.authenticated = true
|
|
175
|
+
ctx.session.auth_method = 'local'
|
|
176
|
+
|
|
177
|
+
ctx.body = {
|
|
178
|
+
ok: true,
|
|
179
|
+
data: {
|
|
180
|
+
user : user,
|
|
181
|
+
authenticated: true
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (local_url_login_redirect!=undefined) {
|
|
186
|
+
ctx.redirect(local_url_login_redirect)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
})(ctx)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
// handle auth routes
|
|
194
|
+
const handleGoogleLogin = passport.authenticate('google', {
|
|
195
|
+
scope: ['profile', 'email']
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
const handleGoogleCallback = (ctx, next) => {
|
|
199
|
+
ctx.miolo.logger.debug(`[auth][google] handleGoogleCallback() - authenticating...`)
|
|
200
|
+
return passport.authenticate('google', async function(err, user, info, _status) {
|
|
201
|
+
if (err || (user === false)) {
|
|
202
|
+
ctx.miolo.logger.debug(`[auth][google] handleGoogleCallback() - user not authenticated`)
|
|
203
|
+
ctx.session.user = undefined
|
|
204
|
+
ctx.session.authenticated = false
|
|
205
|
+
ctx.session.auth_method = undefined
|
|
206
|
+
ctx.sessionId = undefined
|
|
207
|
+
|
|
208
|
+
// This will show error logs on the catcher middleware
|
|
209
|
+
// ctx.throw(401)
|
|
210
|
+
|
|
211
|
+
ctx.status= 401
|
|
212
|
+
|
|
213
|
+
ctx.body = {
|
|
214
|
+
ok: err==undefined,
|
|
215
|
+
data: {
|
|
216
|
+
user: undefined,
|
|
217
|
+
authenticated: false,
|
|
218
|
+
info: info,
|
|
219
|
+
},
|
|
220
|
+
error: err
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
ctx.redirect(google_url_logout_redirect || '/')
|
|
224
|
+
|
|
225
|
+
} else {
|
|
226
|
+
ctx.miolo.logger.debug(`[auth][google] handleGoogleCallback() - user authenticated`)
|
|
227
|
+
await ctx.login(user)
|
|
228
|
+
ctx.session.user = user // ctx.state.user
|
|
229
|
+
ctx.session.authenticated = true
|
|
230
|
+
ctx.session.auth_method = 'google'
|
|
231
|
+
|
|
232
|
+
// ctx.body = {
|
|
233
|
+
// ok: true,
|
|
234
|
+
// data: {
|
|
235
|
+
// user : user,
|
|
236
|
+
// authenticated: true
|
|
237
|
+
// }
|
|
238
|
+
// }
|
|
239
|
+
|
|
240
|
+
ctx.redirect(google_url_login_redirect || '/')
|
|
241
|
+
}
|
|
242
|
+
})(ctx, next)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
const handleLogOut = async (ctx, next) => {
|
|
247
|
+
if (ctx.session.authenticated) {
|
|
248
|
+
ctx.miolo.logger.debug(`[auth][passport] handleLogOut() - logging out...`)
|
|
249
|
+
|
|
250
|
+
ctx.session.user = undefined
|
|
251
|
+
ctx.session.authenticated = false
|
|
252
|
+
ctx.session.auth_method = undefined
|
|
253
|
+
ctx.sessionId = undefined
|
|
254
|
+
|
|
255
|
+
ctx.body = {
|
|
256
|
+
ok: true,
|
|
257
|
+
data: {
|
|
258
|
+
user: undefined,
|
|
259
|
+
authenticated: false
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (local_url_logout_redirect!=undefined) {
|
|
264
|
+
ctx.redirect(local_url_logout_redirect)
|
|
265
|
+
} else {
|
|
266
|
+
await ctx.logout()
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
ctx.miolo.logger.debug(`[auth][passport] handleLogOut() - logging out (unauthed)...`)
|
|
270
|
+
|
|
271
|
+
// This will show error logs on the catcher middleware
|
|
272
|
+
// ctx.throw(401)
|
|
273
|
+
|
|
274
|
+
ctx.status= 401
|
|
275
|
+
ctx.body = {
|
|
276
|
+
ok: true,
|
|
277
|
+
data: {
|
|
278
|
+
user: undefined,
|
|
279
|
+
authenticated: false
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Init the router
|
|
286
|
+
const login_router = new Router()
|
|
287
|
+
login_router.post(local_url_login_f, handleLocalLogIn)
|
|
288
|
+
login_router.get (local_url_logout_f, handleLogOut)
|
|
289
|
+
login_router.post(local_url_logout_f, handleLogOut)
|
|
290
|
+
login_router.get(google_url_login_f, handleGoogleLogin)
|
|
291
|
+
login_router.get(google_url_callback_f, handleGoogleCallback)
|
|
292
|
+
login_router.get(google_url_logout_f, handleLogOut)
|
|
293
|
+
login_router.post(google_url_logout_f, handleLogOut)
|
|
294
|
+
|
|
295
|
+
app.use(login_router.routes())
|
|
296
|
+
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export {init_passport_auth_middleware}
|
|
@@ -20,13 +20,15 @@ export async function init_ssr_render_middleware(app, config, devRender= undefin
|
|
|
20
20
|
hostname: httpConfig?.hostname,
|
|
21
21
|
port: httpConfig?.port,
|
|
22
22
|
catcher_url: httpConfig?.catcher_url,
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
auth_method: ctx.session?.auth_method,
|
|
24
|
+
login_url: ctx.session?.auth_method === 'google' ? authConfig?.passport?.google_url_login : authConfig?.passport?.local_url_login,
|
|
25
|
+
logout_url: ctx.session?.auth_method === 'google' ? authConfig?.passport?.google_url_logout : authConfig?.passport?.local_url_logout,
|
|
25
26
|
//socket: {
|
|
26
27
|
// enabled: socketConfig?.enabled===true,
|
|
27
28
|
// config: socketConfig?.config?.cli || {}
|
|
28
29
|
//}
|
|
29
30
|
}
|
|
31
|
+
ctx.miolo.logger.debug(`[render-ssr] rendering an ${ctx?.session?.authenticated === true ? 'authenticated' : 'unauthenticated'} context...`)
|
|
30
32
|
|
|
31
33
|
const ssr_data = await ssr_loader(ctx)
|
|
32
34
|
const context = ssr_build_context(ctx, config, ssr_data)
|
package/src/server.mjs
CHANGED
|
@@ -14,8 +14,7 @@ import { init_route_catch_js_error } from './middleware/routes/catch_js_er
|
|
|
14
14
|
|
|
15
15
|
import { init_guest_auth_middleware } from './middleware/auth/guest.mjs'
|
|
16
16
|
import { init_basic_auth_middleware } from './middleware/auth/basic.mjs'
|
|
17
|
-
import {
|
|
18
|
-
import { init_custom_auth_middleware } from './middleware/auth/custom.mjs'
|
|
17
|
+
import { init_passport_auth_middleware } from './middleware/auth/passport/index.mjs'
|
|
19
18
|
|
|
20
19
|
import { init_extra_middlewares } from './middleware/extra.mjs'
|
|
21
20
|
import { init_router } from './middleware/routes/router/index.mjs'
|
|
@@ -68,20 +67,16 @@ async function miolo(makeConfig, devInit= undefined, devRender= undefined) {
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
// auth middleware
|
|
71
|
-
if (config.
|
|
70
|
+
if (config.auth.guest.enabled === true) {
|
|
72
71
|
init_guest_auth_middleware(app, config.auth.guest, config?.session)
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
if (config.
|
|
74
|
+
if (config.auth.basic.enabled === true) {
|
|
76
75
|
init_basic_auth_middleware(app, config.auth.basic)
|
|
77
76
|
}
|
|
78
77
|
|
|
79
|
-
if (config.
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (config.auth_type == 'custom') {
|
|
84
|
-
init_custom_auth_middleware(app, config.auth.custom)
|
|
78
|
+
if (config.auth.passport.enabled === true) {
|
|
79
|
+
init_passport_auth_middleware(app, config.auth.passport, config?.session, config?.cache)
|
|
85
80
|
}
|
|
86
81
|
|
|
87
82
|
// extra middlewares
|