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.
Files changed (31) hide show
  1. package/bin/create/index.mjs +1 -1
  2. package/bin/create/validation.mjs +1 -1
  3. package/package.json +4 -3
  4. package/src/config/.env +19 -8
  5. package/src/config/defaults.mjs +28 -21
  6. package/src/config/index.mjs +10 -17
  7. package/src/engines/cron/syscheck.mjs +2 -2
  8. package/src/middleware/auth/basic.mjs +6 -4
  9. package/src/middleware/auth/guest.mjs +1 -0
  10. package/src/middleware/auth/passport/index.mjs +299 -0
  11. package/src/middleware/ssr/ssr_render.mjs +4 -2
  12. package/src/server.mjs +5 -10
  13. package/template/.agent/skills/miolo-auth/SKILL.md +273 -118
  14. package/template/.agent/skills/miolo-session-context/SKILL.md +4 -3
  15. package/template/.env +9 -2
  16. package/template/db/sql/01_users.sql +3 -0
  17. package/template/package.json +7 -7
  18. package/template/src/cli/pages/offline/Login.jsx +0 -3
  19. package/template/src/cli/pages/offline/LoginForm.jsx +89 -79
  20. package/template/src/cli/pages/todos/context/TodosProvider.jsx +2 -2
  21. package/template/src/server/db/io/users/auth.mjs +36 -4
  22. package/template/src/server/db/triggers/user.mjs +5 -4
  23. package/template/src/server/miolo/auth/passport.mjs +93 -0
  24. package/template/src/server/miolo/db.mjs +4 -15
  25. package/template/src/server/miolo/index.mjs +4 -2
  26. package/src/middleware/auth/credentials/index.mjs +0 -183
  27. package/template/.env.production +0 -111
  28. package/template/src/server/miolo/auth/credentials.mjs +0 -47
  29. /package/src/middleware/auth/{credentials → passport}/session/index.mjs +0 -0
  30. /package/src/middleware/auth/{credentials → passport}/session/store.mjs +0 -0
  31. /package/src/middleware/auth/{credentials → passport}/session/store_koa_redis.mjs +0 -0
@@ -26,7 +26,7 @@ export default async function create(appName, options = {}) {
26
26
  // Parse options
27
27
  const {
28
28
  port,
29
- auth: authMethod = 'credentials',
29
+ auth: authMethod = 'passport',
30
30
  dest = `./${appName}`
31
31
  } = options
32
32
 
@@ -19,7 +19,7 @@ export function validateAppName(name) {
19
19
  * Validates auth method
20
20
  */
21
21
  export function validateAuthMethod(authMethod) {
22
- const validAuthMethods = ['credentials', 'basic', 'guest']
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.154",
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.1.18",
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.1.18",
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=11111111-2222-3333-4444-555555555555
33
- MIOLO_SESSION_SECRET=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=./dist/cli
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=./dist/server
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
@@ -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
- //credentials: {
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
- // url_login : '/login',
362
- // url_logout: '/logout',
363
- // url_login_redirect: undefined
364
- // url_logout_redirect: '/'
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: [
@@ -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.error(`[cron][${cyan('SysCheck')}] RAM ${yellow(used)} MB used of ${green(total)} MB (${yellow(perc)} %)`)
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.error(`[cron][${cyan('SysCheck')}] DISK ${yellow(used)} GB used of ${green(total)} GB (${yellow(free)} GB free)`)
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 _get_credentials = (req) => {
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= _get_credentials(ctx.request)
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()
@@ -62,6 +62,7 @@ const init_guest_auth_middleware = ( app, options, session ) => {
62
62
  name: 'guest'
63
63
  },
64
64
  authenticated: true,
65
+ auth_method: 'guest',
65
66
  token
66
67
  }
67
68
 
@@ -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
- login_url: authConfig?.credentials?.url_login,
24
- logout_url: authConfig?.credentials?.url_logout,
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 { init_credentials_auth_middleware }from './middleware/auth/credentials/index.mjs'
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.auth_type == 'guest') {
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.auth_type == 'basic') {
74
+ if (config.auth.basic.enabled === true) {
76
75
  init_basic_auth_middleware(app, config.auth.basic)
77
76
  }
78
77
 
79
- if (config.auth_type == 'credentials') {
80
- init_credentials_auth_middleware(app, config.auth.credentials, config?.session, config?.cache)
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