summaryrefslogtreecommitdiff
path: root/src/server/api
diff options
context:
space:
mode:
authorSatsuki Yanagi <17376330+u1-liquid@users.noreply.github.com>2019-07-05 07:48:12 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2019-07-05 07:48:12 +0900
commit114523e69e30a90bc7bc043254cfc89e3a523c46 (patch)
tree69272cff9f201423ef7057efb3e7782b38cfded7 /src/server/api
parentUpdate Emojis immediately (#5106) (diff)
downloadsharkey-114523e69e30a90bc7bc043254cfc89e3a523c46.tar.gz
sharkey-114523e69e30a90bc7bc043254cfc89e3a523c46.tar.bz2
sharkey-114523e69e30a90bc7bc043254cfc89e3a523c46.zip
Fix WebAuthn login (#5103)
Diffstat (limited to 'src/server/api')
-rw-r--r--src/server/api/endpoints/i/2fa/getkeys.ts67
-rw-r--r--src/server/api/private/signin.ts42
2 files changed, 40 insertions, 69 deletions
diff --git a/src/server/api/endpoints/i/2fa/getkeys.ts b/src/server/api/endpoints/i/2fa/getkeys.ts
deleted file mode 100644
index bb1585d795..0000000000
--- a/src/server/api/endpoints/i/2fa/getkeys.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import $ from 'cafy';
-import * as bcrypt from 'bcryptjs';
-import * as crypto from 'crypto';
-import define from '../../../define';
-import { UserProfiles, UserSecurityKeys, AttestationChallenges } from '../../../../../models';
-import { ensure } from '../../../../../prelude/ensure';
-import { promisify } from 'util';
-import { hash } from '../../../2fa';
-import { genId } from '../../../../../misc/gen-id';
-
-export const meta = {
- requireCredential: true,
-
- secure: true,
-
- params: {
- password: {
- validator: $.str
- }
- }
-};
-
-const randomBytes = promisify(crypto.randomBytes);
-
-export default define(meta, async (ps, user) => {
- const profile = await UserProfiles.findOne(user.id).then(ensure);
-
- // Compare password
- const same = await bcrypt.compare(ps.password, profile.password!);
-
- if (!same) {
- throw new Error('incorrect password');
- }
-
- const keys = await UserSecurityKeys.find({
- userId: user.id
- });
-
- if (keys.length === 0) {
- throw new Error('no keys found');
- }
-
- // 32 byte challenge
- const entropy = await randomBytes(32);
- const challenge = entropy.toString('base64')
- .replace(/=/g, '')
- .replace(/\+/g, '-')
- .replace(/\//g, '_');
-
- const challengeId = genId();
-
- await AttestationChallenges.save({
- userId: user.id,
- id: challengeId,
- challenge: hash(Buffer.from(challenge, 'utf-8')).toString('hex'),
- createdAt: new Date(),
- registrationChallenge: false
- });
-
- return {
- challenge,
- challengeId,
- securityKeys: keys.map(key => ({
- id: key.id
- }))
- };
-});
diff --git a/src/server/api/private/signin.ts b/src/server/api/private/signin.ts
index cd9fe5bb9d..bc9346d088 100644
--- a/src/server/api/private/signin.ts
+++ b/src/server/api/private/signin.ts
@@ -9,6 +9,7 @@ import { ILocalUser } from '../../../models/entities/user';
import { genId } from '../../../misc/gen-id';
import { ensure } from '../../../prelude/ensure';
import { verifyLogin, hash } from '../2fa';
+import { randomBytes } from 'crypto';
export default async (ctx: Koa.BaseContext) => {
ctx.set('Access-Control-Allow-Origin', config.url);
@@ -99,7 +100,7 @@ export default async (ctx: Koa.BaseContext) => {
});
return;
}
- } else {
+ } else if (body.credentialId) {
const clientDataJSON = Buffer.from(body.clientDataJSON, 'hex');
const clientData = JSON.parse(clientDataJSON.toString('utf-8'));
const challenge = await AttestationChallenges.findOne({
@@ -131,7 +132,7 @@ export default async (ctx: Koa.BaseContext) => {
const securityKey = await UserSecurityKeys.findOne({
id: Buffer.from(
body.credentialId
- .replace(/\-/g, '+')
+ .replace(/-/g, '+')
.replace(/_/g, '/'),
'base64'
).toString('hex')
@@ -161,7 +162,44 @@ export default async (ctx: Koa.BaseContext) => {
});
return;
}
+ } else {
+ const keys = await UserSecurityKeys.find({
+ userId: user.id
+ });
+
+ if (keys.length === 0) {
+ await fail(403, {
+ error: 'no keys found'
+ });
+ }
+
+ // 32 byte challenge
+ const challenge = randomBytes(32).toString('base64')
+ .replace(/=/g, '')
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_');
+
+ const challengeId = genId();
+
+ await AttestationChallenges.save({
+ userId: user.id,
+ id: challengeId,
+ challenge: hash(Buffer.from(challenge, 'utf-8')).toString('hex'),
+ createdAt: new Date(),
+ registrationChallenge: false
+ });
+
+ ctx.body = {
+ challenge,
+ challengeId,
+ securityKeys: keys.map(key => ({
+ id: key.id
+ }))
+ };
+ ctx.status = 200;
+ return;
}
await fail();
+ return;
};