@semapps/auth 1.1.3 → 1.2.0

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 (68) hide show
  1. package/dist/index.d.ts +8 -0
  2. package/dist/index.js +9 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/middlewares/localLogout.d.ts +2 -0
  5. package/dist/middlewares/localLogout.js +6 -0
  6. package/dist/middlewares/localLogout.js.map +1 -0
  7. package/dist/middlewares/redirectToFront.d.ts +2 -0
  8. package/dist/middlewares/redirectToFront.js +15 -0
  9. package/dist/middlewares/redirectToFront.js.map +1 -0
  10. package/dist/middlewares/saveRedirectUrl.d.ts +2 -0
  11. package/dist/middlewares/saveRedirectUrl.js +9 -0
  12. package/dist/middlewares/saveRedirectUrl.js.map +1 -0
  13. package/dist/middlewares/sendToken.d.ts +2 -0
  14. package/dist/middlewares/sendToken.js +6 -0
  15. package/dist/middlewares/sendToken.js.map +1 -0
  16. package/dist/mixins/auth.d.ts +98 -0
  17. package/dist/mixins/auth.js +235 -0
  18. package/dist/mixins/auth.js.map +1 -0
  19. package/dist/mixins/auth.sso.d.ts +76 -0
  20. package/dist/mixins/auth.sso.js +82 -0
  21. package/dist/mixins/auth.sso.js.map +1 -0
  22. package/dist/services/account.d.ts +122 -0
  23. package/dist/services/account.js +324 -0
  24. package/dist/services/account.js.map +1 -0
  25. package/dist/services/auth.cas.d.ts +100 -0
  26. package/dist/services/auth.cas.js +43 -0
  27. package/dist/services/auth.cas.js.map +1 -0
  28. package/dist/services/auth.local.d.ts +143 -0
  29. package/dist/services/auth.local.js +229 -0
  30. package/dist/services/auth.local.js.map +1 -0
  31. package/dist/services/auth.oidc.d.ts +102 -0
  32. package/dist/services/auth.oidc.js +63 -0
  33. package/dist/services/auth.oidc.js.map +1 -0
  34. package/dist/services/jwt.d.ts +50 -0
  35. package/dist/services/jwt.js +111 -0
  36. package/dist/services/jwt.js.map +1 -0
  37. package/dist/services/mail.d.ts +31 -0
  38. package/dist/services/mail.js +52 -0
  39. package/dist/services/mail.js.map +1 -0
  40. package/dist/services/migration.d.ts +18 -0
  41. package/dist/services/migration.js +33 -0
  42. package/dist/services/migration.js.map +1 -0
  43. package/dist/tsconfig.tsbuildinfo +1 -0
  44. package/index.ts +17 -0
  45. package/middlewares/localLogout.ts +6 -0
  46. package/middlewares/{redirectToFront.js → redirectToFront.ts} +2 -2
  47. package/middlewares/{saveRedirectUrl.js → saveRedirectUrl.ts} +2 -2
  48. package/middlewares/{sendToken.js → sendToken.ts} +2 -2
  49. package/mixins/auth.sso.ts +100 -0
  50. package/mixins/{auth.js → auth.ts} +91 -67
  51. package/package.json +16 -10
  52. package/services/account.ts +382 -0
  53. package/services/auth.cas.ts +56 -0
  54. package/services/auth.local.ts +276 -0
  55. package/services/{auth.oidc.js → auth.oidc.ts} +21 -9
  56. package/services/jwt.ts +127 -0
  57. package/services/mail.ts +67 -0
  58. package/services/migration.ts +43 -0
  59. package/tsconfig.json +10 -0
  60. package/index.js +0 -9
  61. package/middlewares/localLogout.js +0 -6
  62. package/mixins/auth.sso.js +0 -93
  63. package/services/account.js +0 -315
  64. package/services/auth.cas.js +0 -45
  65. package/services/auth.local.js +0 -238
  66. package/services/jwt.js +0 -101
  67. package/services/mail.js +0 -49
  68. package/services/migration.js +0 -29
@@ -0,0 +1,276 @@
1
+ import path from 'path';
2
+ // @ts-expect-error TS(7016): Could not find a declaration file for module 'pass... Remove this comment to see the full error message
3
+ import { Strategy } from 'passport-local';
4
+ import { ServiceSchema } from 'moleculer';
5
+ import AuthMixin from '../mixins/auth.ts';
6
+ import sendToken from '../middlewares/sendToken.ts';
7
+ import AuthMailService from './mail.ts';
8
+
9
+ import { Errors } from 'moleculer';
10
+
11
+ const { MoleculerError } = Errors;
12
+
13
+ /** @type {import('moleculer').ServiceSchema} */
14
+ const AuthLocalService = {
15
+ name: 'auth' as const,
16
+ mixins: [AuthMixin],
17
+ settings: {
18
+ baseUrl: null,
19
+ jwtPath: null,
20
+ registrationAllowed: true,
21
+ reservedUsernames: [],
22
+ minPasswordLength: 1,
23
+ minUsernameLength: 1,
24
+ webIdSelection: [],
25
+ accountSelection: [],
26
+ formUrl: null,
27
+ mail: {
28
+ from: null,
29
+ transport: {
30
+ host: null,
31
+ port: null
32
+ },
33
+ defaults: {
34
+ locale: null,
35
+ frontUrl: null
36
+ }
37
+ }
38
+ },
39
+ dependencies: ['webid'],
40
+ async created() {
41
+ const { mail } = this.settings;
42
+
43
+ this.passportId = 'local';
44
+
45
+ if (mail !== false) {
46
+ // @ts-expect-error TS(2345): Argument of type '{ mixins: { name: "auth.mail"; m... Remove this comment to see the full error message
47
+ this.broker.createService({
48
+ mixins: [AuthMailService],
49
+ settings: {
50
+ ...mail
51
+ }
52
+ });
53
+ }
54
+ },
55
+ actions: {
56
+ signup: {
57
+ async handler(ctx) {
58
+ const { username, email, password, ...rest } = ctx.params;
59
+
60
+ // This is going to get in our way otherwise when waiting for completions.
61
+ // @ts-expect-error TS(2339): Property 'skipObjectsWatcher' does not exist on ty... Remove this comment to see the full error message
62
+ ctx.meta.skipObjectsWatcher = true;
63
+
64
+ let accountData = await ctx.call('auth.account.create', {
65
+ username,
66
+ email,
67
+ password,
68
+ ...this.pickAccountData(rest)
69
+ });
70
+
71
+ try {
72
+ const profileData = { nick: accountData.username, email: accountData.email, ...rest };
73
+ const webId = await ctx.call('webid.createWebId', this.pickWebIdData(profileData), {
74
+ meta: {
75
+ isSignup: true // Allow services to handle directly the webId creation if it is generated by the AuthService
76
+ }
77
+ });
78
+
79
+ // Link the webId with the account
80
+ accountData = await ctx.call('auth.account.attachWebId', { accountUri: accountData['@id'], webId });
81
+
82
+ ctx.emit('auth.registered', { webId, profileData, accountData });
83
+
84
+ const token = await ctx.call('auth.jwt.generateServerSignedToken', { payload: { webId } });
85
+
86
+ return { token, webId, newUser: true };
87
+ } catch (e) {
88
+ // Delete account if resource creation failed, or it may cause problems when retrying
89
+ await ctx.call('auth.account.remove', { id: accountData['@id'] });
90
+ throw e;
91
+ }
92
+ }
93
+ },
94
+
95
+ login: {
96
+ async handler(ctx) {
97
+ const { username, password } = ctx.params;
98
+
99
+ const accountData = await ctx.call('auth.account.verify', { username, password });
100
+
101
+ ctx.emit('auth.connected', { webId: accountData.webId, accountData }, { meta: { webId: null, dataset: null } });
102
+
103
+ const token = await ctx.call('auth.jwt.generateServerSignedToken', { payload: { webId: accountData.webId } });
104
+
105
+ return { token, webId: accountData.webId, newUser: false };
106
+ }
107
+ },
108
+
109
+ logout: {
110
+ async handler(ctx) {
111
+ // @ts-expect-error TS(2339): Property '$statusCode' does not exist on type '{}'... Remove this comment to see the full error message
112
+ ctx.meta.$statusCode = 302;
113
+ // @ts-expect-error TS(2339): Property '$location' does not exist on type '{}'.
114
+ ctx.meta.$location = ctx.params.redirectUrl || this.settings.formUrl;
115
+ // @ts-expect-error TS(2339): Property 'webId' does not exist on type '{}'.
116
+ ctx.emit('auth.disconnected', { webId: ctx.meta.webId });
117
+ }
118
+ },
119
+
120
+ redirectToForm: {
121
+ async handler(ctx) {
122
+ if (this.settings.formUrl) {
123
+ const formUrl = new URL(this.settings.formUrl);
124
+ if (ctx.params) {
125
+ for (const [key, value] of Object.entries(ctx.params)) {
126
+ formUrl.searchParams.set(key, value);
127
+ }
128
+ }
129
+ // @ts-expect-error TS(2339): Property '$statusCode' does not exist on type '{}'... Remove this comment to see the full error message
130
+ ctx.meta.$statusCode = 302;
131
+ // @ts-expect-error TS(2339): Property '$location' does not exist on type '{}'.
132
+ ctx.meta.$location = formUrl.toString();
133
+ } else {
134
+ throw new Error('No formUrl defined in auth.local settings');
135
+ }
136
+ }
137
+ },
138
+
139
+ resetPassword: {
140
+ async handler(ctx) {
141
+ const { email } = ctx.params;
142
+
143
+ const account = await ctx.call('auth.account.findByEmail', { email });
144
+
145
+ if (!account) {
146
+ throw new MoleculerError('email.not.exists', 400, 'BAD_REQUEST');
147
+ }
148
+
149
+ const token = await ctx.call('auth.account.generateResetPasswordToken', { webId: account.webId });
150
+
151
+ await ctx.call('auth.mail.sendResetPasswordEmail', {
152
+ account,
153
+ token
154
+ });
155
+ }
156
+ },
157
+
158
+ setNewPassword: {
159
+ async handler(ctx) {
160
+ const { email, token, password } = ctx.params;
161
+
162
+ const account = await ctx.call('auth.account.findByEmail', { email });
163
+
164
+ if (!account) {
165
+ throw new MoleculerError('email.not.exists', 400, 'BAD_REQUEST');
166
+ }
167
+
168
+ await ctx.call('auth.account.setNewPassword', { webId: account.webId, token, password });
169
+ }
170
+ }
171
+ },
172
+ methods: {
173
+ getStrategy() {
174
+ return new Strategy(
175
+ {
176
+ passReqToCallback: true // We want to have access to req below
177
+ },
178
+ (req: any, username: any, password: any, done: any) => {
179
+ req.$ctx
180
+ .call('auth.login', req.$params)
181
+ .then((returnedData: any) => {
182
+ done(null, returnedData);
183
+ })
184
+ .catch((e: any) => {
185
+ done(new MoleculerError(e.message, 401), false);
186
+ });
187
+ }
188
+ );
189
+ },
190
+ getApiRoutes(basePath) {
191
+ const loginRoute = {
192
+ path: path.join(basePath, '/auth/login'),
193
+ name: 'auth-login',
194
+ use: [this.passport.initialize()],
195
+ aliases: {
196
+ 'POST /': [this.passport.authenticate(this.passportId, { session: false }), sendToken]
197
+ }
198
+ };
199
+
200
+ const logoutRoute = {
201
+ path: path.join(basePath, '/auth/logout'),
202
+ name: 'auth-logout',
203
+ aliases: {
204
+ 'GET /': 'auth.logout'
205
+ }
206
+ };
207
+
208
+ const signupRoute = {
209
+ path: path.join(basePath, '/auth/signup'),
210
+ name: 'auth-signup',
211
+ aliases: {
212
+ 'POST /': 'auth.signup'
213
+ }
214
+ };
215
+
216
+ const formRoute = {
217
+ path: path.join(basePath, '/auth'),
218
+ name: 'auth',
219
+ aliases: {
220
+ 'GET /': 'auth.redirectToForm'
221
+ }
222
+ };
223
+
224
+ const resetPasswordRoute = {
225
+ path: path.join(basePath, '/auth/reset_password'),
226
+ name: 'auth-reset-password',
227
+ aliases: {
228
+ 'POST /': 'auth.resetPassword'
229
+ }
230
+ };
231
+ const setNewPasswordRoute = {
232
+ path: path.join(basePath, '/auth/new_password'),
233
+ name: 'auth-new-password',
234
+ aliases: {
235
+ 'POST /': 'auth.setNewPassword'
236
+ }
237
+ };
238
+
239
+ const accountSettingsRoute = {
240
+ path: path.join(basePath, '/auth/account'),
241
+ name: 'auth-account',
242
+ aliases: {
243
+ 'GET /': 'auth.account.findSettingsByWebId',
244
+ 'POST /': 'auth.account.updateAccountSettings'
245
+ },
246
+ authorization: true
247
+ };
248
+
249
+ const routes = [
250
+ loginRoute,
251
+ logoutRoute,
252
+ formRoute,
253
+ resetPasswordRoute,
254
+ setNewPasswordRoute,
255
+ accountSettingsRoute
256
+ ];
257
+
258
+ if (this.settings.registrationAllowed) {
259
+ return [...routes, signupRoute];
260
+ }
261
+
262
+ return routes;
263
+ }
264
+ }
265
+ } satisfies ServiceSchema;
266
+
267
+ export default AuthLocalService;
268
+
269
+ declare global {
270
+ export namespace Moleculer {
271
+ export interface AllServices {
272
+ // @ts-expect-error TS(2717): Subsequent property declarations must have the sam... Remove this comment to see the full error message
273
+ [AuthLocalService.name]: typeof AuthLocalService;
274
+ }
275
+ }
276
+ }
@@ -1,13 +1,16 @@
1
- const urlJoin = require('url-join');
2
- const { Issuer, Strategy, custom } = require('openid-client');
1
+ import urlJoin from 'url-join';
2
+ // @ts-expect-error TS(7016): Could not find a declaration file for module 'open... Remove this comment to see the full error message
3
+ import { Issuer, Strategy, custom } from 'openid-client';
4
+
5
+ import { ServiceSchema } from 'moleculer';
6
+ import AuthSSOMixin from '../mixins/auth.sso.ts';
3
7
 
4
8
  custom.setHttpOptionsDefaults({
5
9
  timeout: 10000
6
10
  });
7
- const AuthSSOMixin = require('../mixins/auth.sso');
8
11
 
9
12
  const AuthOIDCService = {
10
- name: 'auth',
13
+ name: 'auth' as const,
11
14
  mixins: [AuthSSOMixin],
12
15
  settings: {
13
16
  baseUrl: null,
@@ -51,13 +54,13 @@ const AuthOIDCService = {
51
54
  params,
52
55
  passReqToCallback: true
53
56
  },
54
- (req, tokenset, userinfo, done) => {
57
+ (req: any, tokenset: any, userinfo: any, done: any) => {
55
58
  req.$ctx
56
59
  .call('auth.loginOrSignup', { ssoData: userinfo })
57
- .then(loginData => {
60
+ .then((loginData: any) => {
58
61
  done(null, loginData);
59
62
  })
60
- .catch(e => {
63
+ .catch((e: any) => {
61
64
  console.error(e);
62
65
  done(null, false);
63
66
  });
@@ -65,6 +68,15 @@ const AuthOIDCService = {
65
68
  );
66
69
  }
67
70
  }
68
- };
71
+ } satisfies ServiceSchema;
72
+
73
+ export default AuthOIDCService;
69
74
 
70
- module.exports = AuthOIDCService;
75
+ declare global {
76
+ export namespace Moleculer {
77
+ export interface AllServices {
78
+ // @ts-expect-error TS(2717): Subsequent property declarations must have the sam... Remove this comment to see the full error message
79
+ [AuthOIDCService.name]: typeof AuthOIDCService;
80
+ }
81
+ }
82
+ }
@@ -0,0 +1,127 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ // @ts-expect-error TS(7016): Could not find a declaration file for module 'json... Remove this comment to see the full error message
4
+ import jwt from 'jsonwebtoken';
5
+ import crypto from 'crypto';
6
+ import { ServiceSchema } from 'moleculer';
7
+
8
+ /**
9
+ * Service that creates and validates JSON web tokens(JWT).
10
+ * Tokens are signed against this server's keys.
11
+ * This is useful for generating/validating authentication tokens.
12
+ *
13
+ * TODO: Tokens do not expire.
14
+ */
15
+ const AuthJwtSchema = {
16
+ name: 'auth.jwt' as const,
17
+ settings: {
18
+ jwtPath: null
19
+ },
20
+ async created() {
21
+ const privateKeyPath = path.resolve(this.settings.jwtPath, 'jwtRS256.key');
22
+ const publicKeyPath = path.resolve(this.settings.jwtPath, 'jwtRS256.key.pub');
23
+
24
+ if (!fs.existsSync(privateKeyPath) && !fs.existsSync(publicKeyPath)) {
25
+ this.logger.info('JWT keypair not found, generating...');
26
+ if (!fs.existsSync(this.settings.jwtPath)) {
27
+ fs.mkdirSync(this.settings.jwtPath);
28
+ }
29
+ await this.actions.generateKeyPair({ privateKeyPath, publicKeyPath });
30
+ }
31
+
32
+ this.privateKey = fs.readFileSync(privateKeyPath);
33
+ this.publicKey = fs.readFileSync(publicKeyPath);
34
+ },
35
+ actions: {
36
+ generateKeyPair: {
37
+ handler(ctx) {
38
+ const { privateKeyPath, publicKeyPath } = ctx.params;
39
+
40
+ return new Promise((resolve, reject) => {
41
+ crypto.generateKeyPair(
42
+ 'rsa',
43
+ {
44
+ modulusLength: 4096,
45
+ publicKeyEncoding: {
46
+ type: 'spki',
47
+ format: 'pem'
48
+ },
49
+ privateKeyEncoding: {
50
+ type: 'pkcs8',
51
+ format: 'pem'
52
+ }
53
+ },
54
+ (err, publicKey, privateKey) => {
55
+ if (err) {
56
+ reject(err);
57
+ } else {
58
+ fs.writeFile(privateKeyPath, privateKey, err => {
59
+ if (err) {
60
+ reject(err);
61
+ } else {
62
+ fs.writeFile(publicKeyPath, publicKey, err => {
63
+ if (err) {
64
+ reject(err);
65
+ } else {
66
+ resolve({ privateKey, publicKey });
67
+ }
68
+ });
69
+ }
70
+ });
71
+ }
72
+ }
73
+ );
74
+ });
75
+ }
76
+ },
77
+
78
+ generateServerSignedToken: {
79
+ async handler(ctx) {
80
+ const { payload } = ctx.params;
81
+ return jwt.sign(payload, this.privateKey, { algorithm: 'RS256' });
82
+ }
83
+ },
84
+
85
+ verifyServerSignedToken: {
86
+ /** Verifies that the token was signed by this server. */
87
+ async handler(ctx) {
88
+ const { token } = ctx.params;
89
+ try {
90
+ return jwt.verify(token, this.publicKey, { algorithms: ['RS256'] });
91
+ } catch (err) {
92
+ return false;
93
+ }
94
+ }
95
+ },
96
+
97
+ generateUnsignedToken: {
98
+ async handler(ctx) {
99
+ const { payload } = ctx.params;
100
+ const token = jwt.sign(payload, null, { algorithm: 'none' });
101
+ return token;
102
+ }
103
+ },
104
+
105
+ decodeToken: {
106
+ // Warning, this does NOT verify if signature is valid
107
+ async handler(ctx) {
108
+ const { token } = ctx.params;
109
+ try {
110
+ return jwt.decode(token);
111
+ } catch (err) {
112
+ return false;
113
+ }
114
+ }
115
+ }
116
+ }
117
+ } satisfies ServiceSchema;
118
+
119
+ export default AuthJwtSchema;
120
+
121
+ declare global {
122
+ export namespace Moleculer {
123
+ export interface AllServices {
124
+ [AuthJwtSchema.name]: typeof AuthJwtSchema;
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,67 @@
1
+ import path from 'path';
2
+ import urlJoin from 'url-join';
3
+ // @ts-expect-error TS(7016): Could not find a declaration file for module 'mole... Remove this comment to see the full error message
4
+ import MailService from 'moleculer-mail';
5
+ import { ServiceSchema } from 'moleculer';
6
+ import { fileURLToPath } from 'url';
7
+
8
+ // @ts-expect-error TS(1470): The 'import.meta' meta-property is not allowed in ... Remove this comment to see the full error message
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+
11
+ const AuthMailSchema = {
12
+ name: 'auth.mail' as const,
13
+ mixins: [MailService],
14
+ settings: {
15
+ defaults: {
16
+ locale: 'en',
17
+ frontUrl: null
18
+ },
19
+ templateFolder: path.join(__dirname, '../templates'),
20
+ from: null,
21
+ transport: null
22
+ },
23
+ actions: {
24
+ sendResetPasswordEmail: {
25
+ async handler(ctx) {
26
+ const { account, token } = ctx.params;
27
+
28
+ await this.actions.send(
29
+ {
30
+ to: account.email,
31
+ template: 'reset-password',
32
+ locale: this.getTemplateLocale(account.preferredLocale || this.settings.defaults.locale),
33
+ data: {
34
+ account,
35
+ resetUrl: `${urlJoin(this.settings.defaults.frontUrl, 'login')}?new_password=true&token=${token}`
36
+ }
37
+ },
38
+ {
39
+ parentCtx: ctx
40
+ }
41
+ );
42
+ }
43
+ }
44
+ },
45
+ methods: {
46
+ getTemplateLocale(userLocale) {
47
+ switch (userLocale) {
48
+ case 'fr':
49
+ return 'fr-FR';
50
+ case 'en':
51
+ return 'en-EN';
52
+ default:
53
+ return 'en-EN';
54
+ }
55
+ }
56
+ }
57
+ } satisfies ServiceSchema;
58
+
59
+ export default AuthMailSchema;
60
+
61
+ declare global {
62
+ export namespace Moleculer {
63
+ export interface AllServices {
64
+ [AuthMailSchema.name]: typeof AuthMailSchema;
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,43 @@
1
+ import { MIME_TYPES } from '@semapps/mime-types';
2
+ import { getSlugFromUri } from '@semapps/ldp';
3
+ import { ServiceSchema } from 'moleculer';
4
+
5
+ const AuthMigrationSchema = {
6
+ name: 'auth.migration' as const,
7
+ actions: {
8
+ migrateUsersToAccounts: {
9
+ async handler(ctx) {
10
+ const { usersContainer, emailPredicate, usernamePredicate } = ctx.params;
11
+
12
+ const results = await ctx.call('ldp.container.get', { containerUri: usersContainer, accept: MIME_TYPES.JSON });
13
+
14
+ for (const user of results['ldp:contains']) {
15
+ if (user[emailPredicate]) {
16
+ try {
17
+ await ctx.call('auth.account.create', {
18
+ email: user[emailPredicate],
19
+ username: usernamePredicate ? user[usernamePredicate] : getSlugFromUri(user.id),
20
+ webId: user.id
21
+ });
22
+ } catch (e) {
23
+ // @ts-expect-error TS(18046): 'e' is of type 'unknown'.
24
+ console.log(`Unable to create account for user ${user.id}. Error message: ${e.message}`);
25
+ }
26
+ } else {
27
+ console.log(`No email found for user ${user.id}`);
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ } satisfies ServiceSchema;
34
+
35
+ export default AuthMigrationSchema;
36
+
37
+ declare global {
38
+ export namespace Moleculer {
39
+ export interface AllServices {
40
+ [AuthMigrationSchema.name]: typeof AuthMigrationSchema;
41
+ }
42
+ }
43
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": false,
5
+ "rewriteRelativeImportExtensions": true,
6
+ "outDir": "dist",
7
+ "rootDir": "./"
8
+ },
9
+ "include": ["*"]
10
+ }
package/index.js DELETED
@@ -1,9 +0,0 @@
1
- module.exports = {
2
- AuthCASService: require('./services/auth.cas'),
3
- AuthLocalService: require('./services/auth.local'),
4
- AuthOIDCService: require('./services/auth.oidc'),
5
- AuthAccountService: require('./services/account'),
6
- AuthJWTService: require('./services/jwt'),
7
- AuthMigrationService: require('./services/migration'),
8
- AuthMailService: require('./services/mail')
9
- };
@@ -1,6 +0,0 @@
1
- const localLogout = (req, res, next) => {
2
- req.logout(); // Passport logout
3
- next();
4
- };
5
-
6
- module.exports = localLogout;
@@ -1,93 +0,0 @@
1
- const path = require('path');
2
- const session = require('express-session');
3
- const AuthMixin = require('./auth');
4
- const saveRedirectUrl = require('../middlewares/saveRedirectUrl');
5
- const redirectToFront = require('../middlewares/redirectToFront');
6
- const localLogout = require('../middlewares/localLogout');
7
-
8
- const AuthSSOMixin = {
9
- mixins: [AuthMixin],
10
- settings: {
11
- baseUrl: null,
12
- jwtPath: null,
13
- registrationAllowed: true,
14
- reservedUsernames: [],
15
- webIdSelection: [],
16
- // SSO-specific settings
17
- sessionSecret: 's€m@pps',
18
- selectSsoData: null
19
- },
20
- actions: {
21
- async loginOrSignup(ctx) {
22
- const { ssoData } = ctx.params;
23
-
24
- const profileData = this.settings.selectSsoData ? await this.settings.selectSsoData(ssoData) : ssoData;
25
-
26
- // TODO use UUID to identify unique accounts with SSO
27
- const existingAccounts = await ctx.call('auth.account.find', { query: { email: profileData.email } });
28
-
29
- let accountData;
30
- let webId;
31
- let newUser;
32
- if (existingAccounts.length > 0) {
33
- accountData = existingAccounts[0];
34
- webId = accountData.webId;
35
- newUser = false;
36
-
37
- // TODO update account with recent profileData information
38
-
39
- ctx.emit('auth.connected', { webId, accountData, ssoData }, { meta: { webId: null, dataset: null } });
40
- } else {
41
- if (!this.settings.registrationAllowed) {
42
- throw new Error('registration.not-allowed');
43
- }
44
-
45
- accountData = await ctx.call('auth.account.create', {
46
- uuid: profileData.uuid,
47
- email: profileData.email,
48
- username: profileData.username
49
- });
50
- webId = await ctx.call('webid.createWebId', this.pickWebIdData({ nick: accountData.username, ...profileData }));
51
- newUser = true;
52
-
53
- // Link the webId with the account
54
- await ctx.call('auth.account.attachWebId', { accountUri: accountData['@id'], webId });
55
-
56
- ctx.emit(
57
- 'auth.registered',
58
- { webId, profileData, accountData, ssoData },
59
- { meta: { webId: null, dataset: null } }
60
- );
61
- }
62
-
63
- const token = await ctx.call('auth.jwt.generateServerSignedToken', { payload: { webId } });
64
-
65
- return { token, newUser };
66
- }
67
- },
68
- methods: {
69
- getApiRoutes(basePath) {
70
- const sessionMiddleware = session({ secret: this.settings.sessionSecret, maxAge: null });
71
- return [
72
- {
73
- path: path.join(basePath, '/auth'),
74
- name: 'auth',
75
- use: [sessionMiddleware, this.passport.initialize(), this.passport.session()],
76
- aliases: {
77
- 'GET /': [saveRedirectUrl, this.passport.authenticate(this.passportId, { session: false }), redirectToFront]
78
- }
79
- },
80
- {
81
- path: path.join(basePath, '/auth/logout'),
82
- name: 'auth-logout',
83
- use: [sessionMiddleware, this.passport.initialize(), this.passport.session()],
84
- aliases: {
85
- 'GET /': [saveRedirectUrl, localLogout, redirectToFront]
86
- }
87
- }
88
- ];
89
- }
90
- }
91
- };
92
-
93
- module.exports = AuthSSOMixin;