forked from microauth/microauth-google
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
123 lines (96 loc) · 2.98 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
'use strict'
const provider = 'google';
const url = require('url')
const querystring = require('querystring')
const uuid = require('uuid')
const {google} = require('googleapis')
const redirect = require('micro-redirect')
const plus = google.plus({
version: 'v1'
})
const DEFAULT_SCOPES = [
'https://www.googleapis.com/auth/plus.me'
]
const getToken = (oauth2Client, code) => new Promise((resolve, reject) => {
oauth2Client.getToken(code, (err, tokens) => {
if (err) return reject(err)
oauth2Client.setCredentials(tokens)
resolve(tokens)
})
})
const getUser = oauth2Client => new Promise((resolve, reject) => {
plus.people.get({userId: 'me', auth: oauth2Client}, (err, response) => {
if (err) return reject(err)
resolve(response)
})
})
const microAuthGoogle = ({
clientId,
clientSecret,
callbackUrl,
path,
scopes = [],
accessType = 'offline'
}) => {
const states = [];
const oauth2Client = new google.auth.OAuth2(clientId, clientSecret, callbackUrl)
scopes = DEFAULT_SCOPES.concat(scopes)
return fn => async (req, res, ...args) => {
const {pathname, query} = url.parse(req.url)
if (pathname === path) {
try {
const state = uuid.v4()
states.push(state)
const urlHost = req.headers['host'];
const urlProtocol = urlHost.indexOf('localhost') !== -1 ? 'http' : 'https'
const callbackPath = url.parse(callbackUrl).pathname
const redirectUri = `${urlProtocol}://${urlHost}${callbackPath}`;
// update internal url paths
oauth2Client.redirectUri = redirectUri;
callbackUrl = redirectUri;
const redirectUrl = oauth2Client.generateAuthUrl({
// eslint-disable-next-line camelcase
redirect_uri: redirectUri,
access_type: accessType,
scope: scopes,
state
})
return redirect(res, 302, redirectUrl)
} catch (err) {
args.push({err, provider})
return fn(req, res, ...args)
}
}
const callbackPath = url.parse(callbackUrl).pathname
if (pathname === callbackPath) {
try {
const {state, code} = querystring.parse(query)
if (!states.includes(state)) {
const err = new Error('Invalid state')
args.push({err, provider})
return fn(req, res, ...args)
}
states.splice(states.indexOf(state), 1)
const tokens = await getToken(oauth2Client, code)
if (tokens.error) {
args.push({err: tokens.error, provider});
return fn(req, res, ...args);
}
const user = await getUser(oauth2Client)
const result = {
provider,
accessToken: tokens.access_token,
info: user,
tokens
}
args.push({result})
return fn(req, res, ...args)
} catch (err) {
args.push({err, provider})
return fn(req, res, ...args)
}
}
return fn(req, res, ...args)
}
}
module.exports = microAuthGoogle