-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
147 lines (109 loc) · 3.18 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'use strict'
const Hapi = require('hapi')
const Boom = require('boom')
const qs = require('qs')
const fetch = require('node-fetch')
const jsonwebtoken = require('jsonwebtoken')
const low = require('lowdb')
const FileSync = require('lowdb/adapters/FileSync')
/**
* Environment Variables:
* In a real scenario get them using process.env
*/
const FACEBOOK_APP_ID = '695473890820467'
const FACEBOOK_APP_SECRET = 'a9a99c0af136540b83f7eb7c3c4bdc54'
const JWT_SECRET = 'ABRACADABRA'
/**
* Constants
*/
const FACEBOOK_ACCESS_TOKEN_URL = 'https://graph.accountkit.com/v1.0/access_token'
const FACEBOOK_ME_URL = 'https://graph.accountkit.com/v1.0/me'
/**
* Server Initialization
*/
const init = async () => {
const server = Hapi.server({ port: 3000 })
const db = getDatabase()
await server.register(require('hapi-auth-jwt2'))
server.auth.strategy('jwt', 'jwt', {
key: JWT_SECRET,
validate: validateJWT,
verifyOptions: { algorithms: ['HS256'] },
})
/**
* Routes
*/
server.route({ method: 'POST', path: '/auth', config: { auth: false }, handler: handleAuth })
server.route({ method: 'GET', path: '/me', config: { auth: 'jwt' }, handler: handleMe })
/**
* Route Handlers
*/
async function handleAuth(request) {
const users = db.get('users')
try {
const authInfo = await getFacebookToken(request.query.code)
let user = users.find({ id: authInfo.id }).value()
if (!user) {
const { phone } = await getFacebookMe(authInfo['access_token'])
user = { id: authInfo.id, phone }
users.push(user).write()
}
const jwt = jsonwebtoken.sign({ sub: user.id }, JWT_SECRET)
return { jwt }
} catch (err) {
return Boom.unauthorized()
}
}
function handleMe(request) {
const users = db.get('users')
const { credentials } = request.auth
const user = users.find({ id: credentials.sub }).value()
if (!user) {
return Boom.forbidden()
}
return user
}
await server.start()
console.log(`Server running at: ${server.info.uri}`)
}
process.on('unhandledRejection', err => {
console.log(err)
process.exit(1)
})
init()
/**
* Helpers
*/
function getDatabase() {
const adapter = new FileSync('db.json')
const db = low(adapter)
db.defaults({ users: [] }).write()
return db
}
function validateJWT(decodedToken) {
if (!decodedToken) {
return { isValid: false }
}
return { isValid: true, credentials: decodedToken }
}
async function getFacebookToken(code) {
var accessToken = ['AA', FACEBOOK_APP_ID, FACEBOOK_APP_SECRET].join('|')
var params = { grant_type: 'authorization_code', code, access_token: accessToken }
const url = `${FACEBOOK_ACCESS_TOKEN_URL}?${qs.stringify(params)}`
const headers = { 'Content-Type': 'application/json' }
const res = await fetch(url, { headers })
if (!res.ok) {
throw Error(res.statusText)
}
return res.json()
}
async function getFacebookMe(token) {
var params = { access_token: token }
const url = `${FACEBOOK_ME_URL}?${qs.stringify(params)}`
const headers = { 'Content-Type': 'application/json' }
const res = await fetch(url, { headers })
if (!res.ok) {
throw Error(res.statusText)
}
return res.json()
}