-
Notifications
You must be signed in to change notification settings - Fork 267
Expand file tree
/
Copy pathsession.js
More file actions
106 lines (95 loc) · 3.09 KB
/
session.js
File metadata and controls
106 lines (95 loc) · 3.09 KB
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
var crypto = require('crypto')
var cookie = require('cookie')
var signature = require('cookie-signature')
module.exports = ({name, secret, cookie:options, store}) => {
name = name || 'grant'
options = options || {path: '/', httpOnly: true, secure: false, maxAge: null}
if (!secret) {
throw new Error('Grant: cookie secret is required')
}
var embed = !store
return (req) => {
var headerObj = req.headers instanceof Headers;
var headers = (headerObj ? Array.from(req.headers.keys()) : Object.keys(req.headers))
.filter((key) => /(?:set-)?cookie/i.test(key))
.reduce((all, key) => (all[key.toLowerCase()] = headerObj ? req.headers.get(key) : req.headers[key], all), {})
headers['set-cookie'] =
(headerObj ? headers.get('set-cookie') : headers['set-cookie']) ||
(req.multiValueHeaders && req.multiValueHeaders['Set-Cookie']) ||
[]
var cookies = {
input:
// vercel - parsed object
typeof req.cookies === 'object' && !(req.cookies instanceof Array) ? req.cookies :
cookie.parse(
headers.cookie ? headers.cookie :
// aws v2 event - array of key=value pairs
req.cookies ? req.cookies.join('; ') :
''
),
output: headers['set-cookie'].reduce((all, str) =>
(all[str.split(';')[0].split('=')[0]] = str, all), {})
}
var encode = (payload, opt = {}) => {
var data = embed
? Buffer.from(JSON.stringify(payload)).toString('base64')
: payload
var value = signature.sign(data, secret)
var output = cookie.serialize(name, value, {...options, ...opt})
cookies.output[name] = output
headers['set-cookie'] = Object.keys(cookies.output)
.map((name) => cookies.output[name])
}
var cookieStore = () => {
var session = (() => {
var payload = signature.unsign(cookies.input[name] || '', secret)
try {
return JSON.parse(Buffer.from(payload, 'base64').toString())
}
catch (err) {
return {grant: {}}
}
})()
var store = {
get: async (sid) => session,
set: async (sid, value) => session = value,
remove: async (sid) => session = {}
}
return {
get: async () => {
return store.get()
},
set: async (value) => {
encode(value)
return store.set(null, value)
},
remove: async () => {
encode('', {maxAge: 0})
await store.remove()
},
cookies,
headers,
}
}
var sessionStore = () => {
var sid = signature.unsign(cookies.input[name] || '', secret)
|| crypto.randomBytes(20).toString('hex')
return {
get: async () => {
return await store.get(sid) || {grant: {}}
},
set: async (value) => {
encode(sid)
return store.set(sid, value)
},
remove: async () => {
encode(sid, {maxAge: 0})
await store.remove(sid)
},
cookies,
headers,
}
}
return embed ? cookieStore() : sessionStore()
}
}