-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
98 lines (85 loc) · 2.19 KB
/
index.ts
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
import { type Cookie, getCookies, setCookie } from './deps.ts'
import { createKey, sign, verify } from './utils.ts'
/**
* Sign a value with Secret
*
* ### usage:
* ```ts
* const cookie = await cookieSign('hello', 'super_secret')
* // hello.gsSaKanhysk-CuNkIJhUWsHItAOcFZbrNNTa95qCfAE.
* ```
*/
const cookieSign = async (value: string, secret: string) => {
const key = await createKey(secret)
const data = await sign(key, value)
return `${value}.${data}`
}
/**
* Verify an input with Secret
*
* ### usage:
* ```ts
* cookieVerify('hello.gsSaKanhysk-CuNkIJhUWsHItAOcFZbrNNTa95qCfAE.', 'super_secret')
* // true
* ```
*/
const cookieVerify = async (input: string, secret: string) => {
const key = await createKey(secret)
// get the signature and raw data
try {
const inputArr = input.split('.')
const data = inputArr.slice(0, -1).join('.')
const signature = inputArr.at(-1)
if (!signature) throw Error('Invalid input: Bad data')
return await verify(key, signature, data)
} catch (_err) {
throw Error('Invalid input')
}
}
type CookieOptions = Omit<Cookie, 'name' | 'value'>
/**
* Create a signed cookie. **returns** the cookie string and headers
*
* ### usage:
* ```ts
* const { cookie } = await createSignedCookie('id', '1', 'super_secret', { httpOnly: true })
* // id=1....
* ```
*/
const createSignedCookie = async (
cookie_name: string,
cookie_value: string,
secret: string,
opts: CookieOptions = { path: '/' }
) => {
const value = await cookieSign(cookie_value, secret)
const cookie: Cookie = {
name: cookie_name,
value,
...opts,
}
const headers = new Headers()
setCookie(headers, cookie)
return { headers, cookie: headers.get('set-cookie') || '' }
}
/**
* Verify a signed cookie.
*
* ### usage:
* ```ts
* await verifySignedCookie(headers, 'id', 'super_secret')
* // false or cookie value
* ```
*/
const verifySignedCookie = async (
headers: Headers,
cookie_name: string,
secret: string
) => {
const cookie = getCookies(headers)[cookie_name]
if (cookie && (await cookieVerify(cookie, secret))) {
return cookie
}
return false
}
export { cookieSign, cookieVerify, createSignedCookie, verifySignedCookie }