-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
123 lines (85 loc) · 3.06 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const express = require('express')
const crypto = require("node:crypto");
const {
generateRegistrationOptions,
verifyRegistrationResponse,
generateAuthenticationOptions,
verifyAuthenticationResponse
} = require('@simplewebauthn/server')
if (!globalThis.crypto) {
globalThis.crypto = crypto;
}
const PORT = 3000
const app = express();
app.use(express.static('./public'))
app.use(express.json())
// States
const userStore = {}
const challengeStore = {}
app.post('/register', (req, res) => {
const { username, password } = req.body
const id = `user_${Date.now()}`
const user = {
id,
username,
password
}
userStore[id] = user
console.log(`Register successfull`, userStore[id])
return res.json({ id })
})
app.post('/register-challenge', async (req, res) => {
const { userId } = req.body
if (!userStore[userId]) return res.status(404).json({ error: 'user not found!' })
const user = userStore[userId]
const challengePayload = await generateRegistrationOptions({
rpID: 'localhost',
rpName: 'My Localhost Machine',
attestationType: 'none',
userName: user.username,
timeout: 30_000,
})
challengeStore[userId] = challengePayload.challenge
return res.json({ options: challengePayload })
})
app.post('/register-verify', async (req, res) => {
const { userId, cred } = req.body
if (!userStore[userId]) return res.status(404).json({ error: 'user not found!' })
const user = userStore[userId]
const challenge = challengeStore[userId]
const verificationResult = await verifyRegistrationResponse({
expectedChallenge: challenge,
expectedOrigin: 'http://localhost:3000',
expectedRPID: 'localhost',
response: cred,
})
if (!verificationResult.verified) return res.json({ error: 'could not verify' });
userStore[userId].passkey = verificationResult.registrationInfo
return res.json({ verified: true })
})
app.post('/login-challenge', async (req, res) => {
const { userId } = req.body
if (!userStore[userId]) return res.status(404).json({ error: 'user not found!' })
const opts = await generateAuthenticationOptions({
rpID: 'localhost',
})
challengeStore[userId] = opts.challenge
return res.json({ options: opts })
})
app.post('/login-verify', async (req, res) => {
const { userId, cred } = req.body
if (!userStore[userId]) return res.status(404).json({ error: 'user not found!' })
const user = userStore[userId]
const challenge = challengeStore[userId]
const result = await verifyAuthenticationResponse({
expectedChallenge: challenge,
expectedOrigin: 'http://localhost:3000',
expectedRPID: 'localhost',
response: cred,
authenticator: user.passkey
})
if (!result.verified) return res.json({ error: 'something went wrong' })
// Login the user: Session, Cookies, JWT
return res.json({ success: true, userId })
})
app.listen(PORT, () => console.log(`Server started on PORT:${PORT}`))