@adminforth/two-factors-auth 1.0.12 → 1.0.15

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.
@@ -70,7 +70,6 @@
70
70
 
71
71
 
72
72
 
73
-
74
73
  const router = useRouter();
75
74
  const inProgress = ref(false);
76
75
 
@@ -143,10 +142,10 @@
143
142
  }
144
143
  })
145
144
  if (resp.allowedLogin){
146
- router.push('/');
147
- } else {
148
- showErrorTost('Invalid code');
149
- }
145
+ await user.finishLogin();
146
+ } else {
147
+ showErrorTost('Invalid code');
150
148
  }
149
+ }
151
150
  </script>
152
151
 
@@ -89,7 +89,6 @@ import { useUserStore } from '@/stores/user';
89
89
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
90
90
  import { callAdminForthApi, loadFile } from '@/utils';
91
91
  import { useRouter } from 'vue-router';
92
- import { initFlowbite } from 'flowbite'
93
92
  import { showErrorTost } from '@/composables/useFrontendApi';
94
93
 
95
94
 
@@ -180,9 +179,9 @@ async function sendCode () {
180
179
  }
181
180
  })
182
181
  if (resp.allowedLogin){
183
- router.push('/');
184
- } else {
185
- showErrorTost('Invalid code');
186
- }
182
+ await user.finishLogin()
183
+ } else {
184
+ showErrorTost('Invalid code');
187
185
  }
186
+ }
188
187
  </script>
@@ -70,7 +70,6 @@
70
70
 
71
71
 
72
72
 
73
-
74
73
  const router = useRouter();
75
74
  const inProgress = ref(false);
76
75
 
@@ -143,10 +142,10 @@
143
142
  }
144
143
  })
145
144
  if (resp.allowedLogin){
146
- router.push('/');
147
- } else {
148
- showErrorTost('Invalid code');
149
- }
145
+ await user.finishLogin();
146
+ } else {
147
+ showErrorTost('Invalid code');
150
148
  }
149
+ }
151
150
  </script>
152
151
 
@@ -89,7 +89,6 @@ import { useUserStore } from '@/stores/user';
89
89
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
90
90
  import { callAdminForthApi, loadFile } from '@/utils';
91
91
  import { useRouter } from 'vue-router';
92
- import { initFlowbite } from 'flowbite'
93
92
  import { showErrorTost } from '@/composables/useFrontendApi';
94
93
 
95
94
 
@@ -180,9 +179,9 @@ async function sendCode () {
180
179
  }
181
180
  })
182
181
  if (resp.allowedLogin){
183
- router.push('/');
184
- } else {
185
- showErrorTost('Invalid code');
186
- }
182
+ await user.finishLogin()
183
+ } else {
184
+ showErrorTost('Invalid code');
187
185
  }
186
+ }
188
187
  </script>
package/dist/index.js CHANGED
@@ -40,11 +40,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
40
40
  if (!this.authResource.columns.some((col) => col.name === this.options.twoFaSecretFieldName)) {
41
41
  throw new Error(`Column ${this.options.twoFaSecretFieldName} not found in ${this.authResource.label}`);
42
42
  }
43
- const beforeLoginConfirmation = this.adminforth.config.auth;
44
- if (!beforeLoginConfirmation.beforeLoginConfirmation) {
45
- beforeLoginConfirmation.beforeLoginConfirmation = [];
46
- }
47
- beforeLoginConfirmation.beforeLoginConfirmation.push((_a) => __awaiter(this, [_a], void 0, function* ({ adminUser }) {
43
+ this.adminforth.config.auth.beforeLoginConfirmation.push((_a) => __awaiter(this, [_a], void 0, function* ({ adminUser, response }) {
48
44
  if (adminUser.isRoot) {
49
45
  return { body: { loginAllowed: true }, ok: true };
50
46
  }
@@ -60,31 +56,22 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
60
56
  newSecret = tempSecret.secret;
61
57
  }
62
58
  else {
59
+ const value = this.adminforth.auth.issueJWT({ userName, issuer: brandName, pk: userPk }, 'tempTotp');
60
+ response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; max-age=3600; `);
63
61
  return {
64
62
  body: {
65
63
  loginAllowed: false,
66
64
  redirectTo: '/confirm2fa',
67
- setCookie: [{
68
- name: 'totpTemporaryJWT',
69
- value: this.adminforth.auth.issueJWT({ userName, issuer: brandName, pk: userPk }, 'tempTotp'),
70
- expiry: '1h',
71
- httpOnly: true
72
- },]
73
65
  },
74
66
  ok: true
75
67
  };
76
68
  }
77
69
  const totpTemporaryJWT = this.adminforth.auth.issueJWT({ userName, newSecret, issuer: brandName, pk: userPk }, 'tempTotp');
70
+ response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${totpTemporaryJWT}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + '1h').toUTCString()} `);
78
71
  return {
79
72
  body: {
80
73
  loginAllowed: false,
81
74
  redirectTo: secret ? '/confirm2fa' : '/setup2fa',
82
- setCookie: [{
83
- name: 'totpTemporaryJWT',
84
- value: totpTemporaryJWT,
85
- expiry: '1h',
86
- httpOnly: true
87
- },]
88
75
  },
89
76
  ok: true
90
77
  };
@@ -96,8 +83,9 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
96
83
  path: `/plugin/twofa/initSetup`,
97
84
  noAuth: true,
98
85
  handler: (server) => __awaiter(this, void 0, void 0, function* () {
86
+ var _a;
99
87
  const toReturn = { totpJWT: null, status: 'ok', };
100
- const totpTemporaryJWT = server.cookies['adminforth_totpTemporaryJWT'];
88
+ const totpTemporaryJWT = (_a = server.cookies.find((cookie) => cookie.key === 'adminforth_totpTemporaryJWT')) === null || _a === void 0 ? void 0 : _a.value;
101
89
  if (totpTemporaryJWT) {
102
90
  toReturn.totpJWT = totpTemporaryJWT;
103
91
  }
@@ -108,8 +96,9 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
108
96
  method: 'POST',
109
97
  path: `/plugin/twofa/confirmSetup`,
110
98
  noAuth: true,
111
- handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, cookies }) {
112
- const totpTemporaryJWT = cookies['adminforth_totpTemporaryJWT'];
99
+ handler: (_b) => __awaiter(this, [_b], void 0, function* ({ body, adminUser, response, cookies }) {
100
+ var _c;
101
+ const totpTemporaryJWT = (_c = cookies.find((cookie) => cookie.key === 'adminforth_totpTemporaryJWT')) === null || _c === void 0 ? void 0 : _c.value;
113
102
  const decoded = yield this.adminforth.auth.verify(totpTemporaryJWT, 'tempTotp');
114
103
  if (!decoded) {
115
104
  return { status: 'error', message: 'Invalid token' };
@@ -120,8 +109,8 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
120
109
  this.connectors = this.adminforth.connectors;
121
110
  const connector = this.connectors[this.authResource.dataSource];
122
111
  yield connector.updateRecord({ resource: this.authResource, recordId: decoded.pk, newValues: { [this.options.twoFaSecretFieldName]: decoded.newSecret } });
123
- this.adminForthAuth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
124
- this.adminForthAuth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
112
+ this.adminforth.auth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
113
+ this.adminforth.auth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
125
114
  return { status: 'ok', allowedLogin: true };
126
115
  }
127
116
  else {
@@ -135,8 +124,8 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
135
124
  const user = yield connector.getRecordByPrimaryKey(this.authResource, decoded.pk);
136
125
  const verified = twofactor.verifyToken(user[this.options.twoFaSecretFieldName], body.code);
137
126
  if (verified) {
138
- this.adminForthAuth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
139
- this.adminForthAuth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
127
+ this.adminforth.auth.removeCustomCookie({ response, name: 'totpTemporaryJWT' });
128
+ this.adminforth.auth.setAuthCookie({ response, username: decoded.userName, pk: decoded.pk });
140
129
  return { status: 'ok', allowedLogin: true };
141
130
  }
142
131
  else {
package/index.ts CHANGED
@@ -1,10 +1,8 @@
1
- import { AdminForthResource } from "adminforth/types/AdminForthConfig.js";
2
- import type { IAdminForth, IHttpServer, IAdminForthAuth } from "adminforth/types/AdminForthConfig.js";
3
- import { AdminForthPlugin } from "adminforth";
1
+ import { AdminForthPlugin } from "adminforth";
2
+ import type { AdminForthResource, AdminUser, IAdminForth, IHttpServer, IAdminForthAuth, BeforeLoginConfirmationFunction, IAdminForthHttpResponse } from "adminforth";
4
3
  import twofactor from 'node-2fa';
5
4
  import { PluginOptions } from "./types.js"
6
5
 
7
-
8
6
  export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
9
7
  options: PluginOptions;
10
8
  adminforth: IAdminForth;
@@ -44,54 +42,46 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
44
42
  if(!this.authResource.columns.some((col)=>col.name === this.options.twoFaSecretFieldName)){
45
43
  throw new Error(`Column ${this.options.twoFaSecretFieldName} not found in ${this.authResource.label}`)
46
44
  }
47
- const beforeLoginConfirmation = this.adminforth.config.auth as any
48
- if (!beforeLoginConfirmation.beforeLoginConfirmation){
49
- beforeLoginConfirmation.beforeLoginConfirmation = []
50
- }
51
- beforeLoginConfirmation.beforeLoginConfirmation.push(async({adminUser})=>{
52
- if(adminUser.isRoot){
53
- return { body: {loginAllowed: true}, ok: true}
54
- }
55
- const secret = adminUser.dbUser[this.options.twoFaSecretFieldName]
56
- const userName = adminUser.dbUser[adminforth.config.auth.usernameField]
57
- const brandName = adminforth.config.customization.brandName
58
- const authResource = adminforth.config.resources.find((res)=>res.resourceId === adminforth.config.auth.resourceId )
59
- const authPk = authResource.columns.find((col)=>col.primaryKey).name
60
- const userPk = adminUser.dbUser[authPk]
61
- let newSecret = null
62
- if (!secret){
63
- const tempSecret = twofactor.generateSecret({name: brandName,account: userName})
64
- newSecret = tempSecret.secret
65
- } else {
66
- return {
45
+ (this.adminforth.config.auth.beforeLoginConfirmation as BeforeLoginConfirmationFunction[]).push(
46
+ async({ adminUser, response }: { adminUser: AdminUser, response: IAdminForthHttpResponse} )=> {
47
+ if(adminUser.isRoot){
48
+ return { body: {loginAllowed: true}, ok: true}
49
+ }
50
+ const secret = adminUser.dbUser[this.options.twoFaSecretFieldName]
51
+ const userName = adminUser.dbUser[adminforth.config.auth.usernameField]
52
+ const brandName = adminforth.config.customization.brandName
53
+ const authResource = adminforth.config.resources.find((res)=>res.resourceId === adminforth.config.auth.resourceId )
54
+ const authPk = authResource.columns.find((col)=>col.primaryKey).name
55
+ const userPk = adminUser.dbUser[authPk]
56
+ let newSecret = null
57
+ if (!secret){
58
+ const tempSecret = twofactor.generateSecret({name: brandName,account: userName})
59
+ newSecret = tempSecret.secret
60
+ } else {
61
+ const value = this.adminforth.auth.issueJWT({userName, issuer:brandName, pk:userPk },'tempTotp');
62
+ response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; max-age=3600; `);
63
+
64
+ return {
65
+ body:{
66
+ loginAllowed: false,
67
+ redirectTo: '/confirm2fa',
68
+
69
+ },
70
+ ok: true
71
+
72
+ }
73
+ }
74
+ const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:brandName, pk:userPk },'tempTotp', )
75
+ response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${totpTemporaryJWT}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + '1h').toUTCString() } `);
76
+
77
+ return {
67
78
  body:{
68
79
  loginAllowed: false,
69
- redirectTo: '/confirm2fa',
70
- setCookie: [{
71
- name: 'totpTemporaryJWT',
72
- value: this.adminforth.auth.issueJWT({userName, issuer:brandName, pk:userPk },'tempTotp', ),
73
- expiry: '1h',
74
- httpOnly: true
75
- },]
80
+ redirectTo: secret ? '/confirm2fa' : '/setup2fa',
76
81
  },
77
82
  ok: true
78
-
79
83
  }
80
- }
81
- const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:brandName, pk:userPk },'tempTotp', )
82
- return {
83
- body:{
84
- loginAllowed: false,
85
- redirectTo: secret ? '/confirm2fa' : '/setup2fa',
86
- setCookie: [{
87
- name: 'totpTemporaryJWT',
88
- value: totpTemporaryJWT,
89
- expiry: '1h',
90
- httpOnly: true
91
- },]},
92
- ok: true
93
- }
94
- })
84
+ })
95
85
  }
96
86
 
97
87
  setupEndpoints(server: IHttpServer): void {
@@ -101,7 +91,8 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
101
91
  noAuth: true,
102
92
  handler: async (server) => {
103
93
  const toReturn = {totpJWT:null,status:'ok',}
104
- const totpTemporaryJWT = server.cookies['adminforth_totpTemporaryJWT']
94
+
95
+ const totpTemporaryJWT = server.cookies.find((cookie)=>cookie.key === 'adminforth_totpTemporaryJWT')?.value;
105
96
  if (totpTemporaryJWT){
106
97
  toReturn.totpJWT = totpTemporaryJWT
107
98
  }
@@ -113,7 +104,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
113
104
  path: `/plugin/twofa/confirmSetup`,
114
105
  noAuth: true,
115
106
  handler: async ({ body, adminUser, response, cookies }) => {
116
- const totpTemporaryJWT = cookies['adminforth_totpTemporaryJWT']
107
+ const totpTemporaryJWT = cookies.find((cookie)=>cookie.key === 'adminforth_totpTemporaryJWT')?.value;
117
108
  const decoded = await this.adminforth.auth.verify(totpTemporaryJWT, 'tempTotp');
118
109
  if ( !decoded ) {
119
110
  return {status:'error',message:'Invalid token'}
@@ -124,9 +115,9 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
124
115
  this.connectors = this.adminforth.connectors
125
116
  const connector = this.connectors[this.authResource.dataSource];
126
117
  await connector.updateRecord({resource:this.authResource, recordId:decoded.pk, newValues:{[this.options.twoFaSecretFieldName]: decoded.newSecret}})
127
- this.adminForthAuth.removeCustomCookie({response, name:'totpTemporaryJWT'})
128
- this.adminForthAuth.setAuthCookie({response, username:decoded.userName, pk:decoded.pk})
129
- return { status: 'ok',allowedLogin: true }
118
+ this.adminforth.auth.removeCustomCookie({response, name:'totpTemporaryJWT'})
119
+ this.adminforth.auth.setAuthCookie({response, username:decoded.userName, pk:decoded.pk})
120
+ return { status: 'ok', allowedLogin: true }
130
121
  } else {
131
122
  return {error: 'Wrong or expired OTP code'}
132
123
  }
@@ -137,9 +128,9 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
137
128
  const user = await connector.getRecordByPrimaryKey(this.authResource, decoded.pk)
138
129
  const verified = twofactor.verifyToken(user[this.options.twoFaSecretFieldName], body.code);
139
130
  if (verified) {
140
- this.adminForthAuth.removeCustomCookie({response, name:'totpTemporaryJWT'})
141
- this.adminForthAuth.setAuthCookie({response, username:decoded.userName, pk:decoded.pk})
142
- return { status: 'ok',allowedLogin: true }
131
+ this.adminforth.auth.removeCustomCookie({response, name:'totpTemporaryJWT'})
132
+ this.adminforth.auth.setAuthCookie({response, username:decoded.userName, pk:decoded.pk})
133
+ return { status: 'ok', allowedLogin: true }
143
134
  } else {
144
135
  return {error: 'Wrong or expired OTP code'}
145
136
  }
package/package.json CHANGED
@@ -1,17 +1,16 @@
1
1
  {
2
2
  "name": "@adminforth/two-factors-auth",
3
- "version": "1.0.12",
3
+ "version": "1.0.15",
4
4
  "description": "AdminForth plugin for two factors authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
- "rollout": "tsc && cp -r custom dist/custom && npm version patch && npm publish --access public"
9
+ "rollout": "tsc && cp -rf custom dist/ && npm version patch && npm publish --access public"
10
10
  },
11
11
  "author": "devforth",
12
12
  "license": "ISC",
13
13
  "dependencies": {
14
- "adminforth": "^1.1.95",
15
14
  "node-2fa": "^2.0.3"
16
15
  }
17
16
  }