-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
141 lines (118 loc) · 3.18 KB
/
index.js
File metadata and controls
141 lines (118 loc) · 3.18 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
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
/**
* Axel Boberg © 2019
*/
const ServerError = require('./lib/error/ServerError')
const uri = require('./lib/uri')
const defaults = require('./lib/defaults')
const request = require('request')
const DEFAULT_OPTS = {
'host': 'https://accounts.volontar.app',
'authorizationEndpoint': '/oauth/authorize',
'tokenEndpoint': '/oauth/token'
}
/**
* Make a request to the token-endpoint
* @param { Object } body
* @returns { Promise<Object> }
*/
function tokenRequest (body, opts) {
/*
Setup default body, which
should always authenticate
the client as per spec
*/
const _body = defaults(body, {
client_id: opts.clientId,
client_secret: opts.clientSecret
})
/*
Setup default request-options
*/
const _opts = {
uri: opts.host + opts.tokenEndpoint,
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
body: uri.serialize(_body)
}
return new Promise((resolve, reject) => {
request(_opts, (err, res) => {
if (err) {
return reject(err)
}
const body = JSON.parse(res.body)
/*
If a server-side error occured,
throw it as a ServerError for
easier handling
*/
if (res.statusCode !== 200) {
return reject(
new ServerError(body)
)
}
return resolve(body)
})
})
}
/**
* An OAuth2 client for authentication
* against the Volontar-API
* @param { Object } opts
*/
function Client (opts = {}) {
const _opts = defaults(opts, DEFAULT_OPTS)
if (!_opts.clientId) throw new ReferenceError(`Missing required parameter 'clientId'`)
if (!_opts.redirectUri) throw new ReferenceError(`Missing required parameter 'redirectUri'`)
if (!_opts.clientSecret) throw new ReferenceError(`Missing required parameter 'clientSecret'`)
// Expose options
this.opts = _opts
/**
* Generate a url for authorization
* @param { String } scope A space-separated string of the requested scopes
* @param { Object? } opts
* @returns { String }
*/
this.authorize = function (scope, opts) {
if (!scope) throw new TypeError('Scope cannot be undefined')
const authzOpts = defaults(opts || {}, {
state: 'none',
responseType: 'code'
})
const baseUrl = `${_opts.host}${_opts.authorizationEndpoint}`
const params = {
client_id: _opts.clientId,
redirect_uri: _opts.redirectUri,
response_type: authzOpts.responseType,
scope: scope,
state: authzOpts.state
}
return uri.appendQueryParameters(baseUrl, params)
}
/**
* Get an access-token
* @param { String } authorizationCode A valid authorization-code
* @returns { Promise<Object> }
*/
this.token = function (authorizationCode) {
const body = {
code: authorizationCode,
grant_type: 'authorization_code'
}
return tokenRequest(body, _opts)
}
/**
* Refresh an access-token
* @param { String } refreshToken A valid refresh-token
* @returns { Promise<Object> }
*/
this.refresh = function (refreshToken) {
const body = {
refresh_token: refreshToken,
grant_type: 'refresh_token'
}
return tokenRequest(body, _opts)
}
}
module.exports = Client