0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor(core,experience): generate totp qrcode on server side (#4646)

This commit is contained in:
wangsijie 2023-10-13 14:19:03 +08:00 committed by GitHub
parent 42dbc0e62c
commit 03e654b459
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 23 additions and 20 deletions

View file

@ -35,12 +35,12 @@
"@logto/console": "workspace:*",
"@logto/core-kit": "workspace:^2.2.0",
"@logto/demo-app": "workspace:*",
"@logto/experience": "workspace:*",
"@logto/language-kit": "workspace:^1.0.0",
"@logto/phrases": "workspace:^1.5.0",
"@logto/phrases-experience": "workspace:^1.3.1",
"@logto/schemas": "workspace:^1.10.0",
"@logto/shared": "workspace:^3.0.0",
"@logto/experience": "workspace:*",
"@silverhand/essentials": "^2.8.4",
"@withtyped/client": "^0.7.22",
"chalk": "^5.0.0",
@ -72,6 +72,7 @@
"otplib": "^12.0.1",
"p-retry": "^6.0.0",
"pg-protocol": "^1.6.0",
"qrcode": "^1.5.3",
"redis": "^4.6.5",
"roarr": "^7.11.0",
"semver": "^7.3.8",
@ -98,6 +99,7 @@
"@types/koa__cors": "^4.0.0",
"@types/node": "^18.11.18",
"@types/oidc-provider": "^8.0.0",
"@types/qrcode": "^1.5.2",
"@types/semver": "^7.3.12",
"@types/sinon": "^10.0.13",
"@types/supertest": "^2.0.11",

View file

@ -194,6 +194,7 @@ describe('interaction routes', () => {
expect(storeInteractionResult).toBeCalled();
expect(response.statusCode).toEqual(200);
expect(response.body).toHaveProperty('secret');
expect(response.body).toHaveProperty('secretQrCode');
});
});
});

View file

@ -1,6 +1,7 @@
import { MfaFactor, requestVerificationCodePayloadGuard } from '@logto/schemas';
import type Router from 'koa-router';
import { type IRouterParamContext } from 'koa-router';
import qrcode from 'qrcode';
import { z } from 'zod';
import { type WithLogContext } from '#src/middleware/koa-audit-log.js';
@ -78,6 +79,7 @@ export default function additionalRoutes<T extends IRouterParamContext>(
status: [200],
response: z.object({
secret: z.string(),
secretQrCode: z.string(),
}),
}),
async (ctx, next) => {
@ -94,7 +96,10 @@ export default function additionalRoutes<T extends IRouterParamContext>(
true
);
ctx.body = { secret };
ctx.body = {
secret,
secretQrCode: await qrcode.toDataURL(`otpauth://totp/?secret=${secret}`),
};
return next();
}

View file

@ -45,7 +45,6 @@
"@testing-library/react": "^14.0.0",
"@types/color": "^3.0.3",
"@types/jest": "^29.4.0",
"@types/qrcode": "^1.5.2",
"@types/react": "^18.0.31",
"@types/react-dom": "^18.0.0",
"@types/react-helmet": "^6.1.6",
@ -118,8 +117,5 @@
"stylelint": {
"extends": "@silverhand/eslint-config-react/.stylelintrc"
},
"prettier": "@silverhand/eslint-config/.prettierrc",
"dependencies": {
"qrcode": "^1.5.3"
}
"prettier": "@silverhand/eslint-config/.prettierrc"
}

View file

@ -226,7 +226,9 @@ export const linkWithSocial = async (connectorId: string) => {
};
export const createTotpSecret = async () =>
api.post(`${interactionPrefix}/${verificationPath}/totp`).json<{ secret: string }>();
api
.post(`${interactionPrefix}/${verificationPath}/totp`)
.json<{ secret: string; secretQrCode: string }>();
export const bindMfa = async (payload: BindMfaPayload) => {
await api.put(`${interactionPrefix}/bind-mfa`, { json: payload });

View file

@ -1,5 +1,4 @@
import { MfaFactor } from '@logto/schemas';
import qrcode from 'qrcode';
import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
@ -28,13 +27,12 @@ const useStartTotpBinding = ({ replace }: Options = {}) => {
return;
}
const { secret } = result ?? {};
const { secret, secretQrCode } = result ?? {};
if (secret) {
if (secret && secretQrCode) {
const state: TotpBindingState = {
secret,
// Todo @wangsijie generate QR code on the server side
secretQrCode: await qrcode.toDataURL(`otpauth://totp/?secret=${secret}`),
secretQrCode,
availableFactors,
};
navigate({ pathname: `/${UserMfaFlow.MfaBinding}/${MfaFactor.TOTP}` }, { replace, state });

View file

@ -3262,6 +3262,9 @@ importers:
pg-protocol:
specifier: ^1.6.0
version: 1.6.0
qrcode:
specifier: ^1.5.3
version: 1.5.3
redis:
specifier: ^4.6.5
version: 4.6.5
@ -3335,6 +3338,9 @@ importers:
'@types/oidc-provider':
specifier: ^8.0.0
version: 8.0.0
'@types/qrcode':
specifier: ^1.5.2
version: 1.5.2
'@types/semver':
specifier: ^7.3.12
version: 7.3.12
@ -3478,10 +3484,6 @@ importers:
version: 3.22.3
packages/experience:
dependencies:
qrcode:
specifier: ^1.5.3
version: 1.5.3
devDependencies:
'@jest/types':
specifier: ^29.5.0
@ -3558,9 +3560,6 @@ importers:
'@types/jest':
specifier: ^29.4.0
version: 29.4.0
'@types/qrcode':
specifier: ^1.5.2
version: 1.5.2
'@types/react':
specifier: ^18.0.31
version: 18.0.31