-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
141 lines (119 loc) · 4.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
'use strict';
const debug = require('debug')('koa:oauth2-server'),
OAuthServer = require('oauth2-server'),
Request = OAuthServer.Request,
Response = OAuthServer.Response;
const ePath = 'oauth2-server/lib/errors/',
OAuthError = require(ePath + 'oauth-error'),
InvalidScopeError = require(ePath + 'invalid-scope-error'),
InvalidArgumentError = require(ePath + 'invalid-argument-error'),
UnauthorizedRequestError = require(ePath + 'unauthorized-request-error');
class KoaOAuthServer {
constructor(options) {
this.options = options || {};
if(!options.model) {
throw new InvalidArgumentError('Missing parameter: `model`');
}
// If no `saveTokenMetadata` method is set via the model, we create
// a simple passthrough mechanism instead
this.saveTokenMetadata = options.model.saveTokenMetadata
? options.model.saveTokenMetadata
: (token, data) => { return Promise.resolve(token); };
// If no `checkScope` method is set via the model, we provide a default
this.checkScope = options.model.checkScope
? options.model.checkScope
: (scope, token) => { return token.scope.indexOf(scope) !== -1; }
this.server = new OAuthServer(options);
}
// Returns token authentication middleware
authenticate() {
debug('Creating authentication endpoint middleware');
return async (ctx, next) => {
debug('Running authenticate endpoint middleware');
const request = new Request(ctx.request),
response = new Response(ctx.response);
await this.server
.authenticate(request, response)
.then(async (token) => {
ctx.state.oauth = { token: token };
await next();
})
.catch((err) => { handleError(err, ctx); });
};
}
// Returns authorization endpoint middleware
// Used by the client to obtain authorization from the resource owner
authorize(options) {
debug('Creating authorization endpoint middleware');
return async (ctx, next) => {
debug('Running authorize endpoint middleware');
const request = new Request(ctx.request),
response = new Response(ctx.response);
await this.server
.authorize(request, response, options)
.then(async (code) => {
ctx.state.oauth = { code: code };
handleResponse(ctx, response);
await next();
})
.catch((err) => { handleError(err, ctx); });
};
}
// Returns token endpoint middleware
// Used by the client to exchange authorization grant for access token
token() {
debug('Creating token endpoint middleware');
return async (ctx, next) => {
debug('Running token endpoint middleware');
const request = new Request(ctx.request),
response = new Response(ctx.response);
await this.server
.token(request, response)
.then((token) => {
return this.saveTokenMetadata(token, ctx.request);
})
.then(async (token) => {
ctx.state.oauth = { token: token };
handleResponse(ctx, response);
await next();
})
.catch((err) => { handleError(err, ctx); });
};
}
// Returns scope check middleware
// Used to limit access to a route or router to carriers of a certain scope.
scope(required) {
debug(`Creating scope check middleware (${required})`);
return (ctx, next) => {
const result = this.checkScope(required, ctx.state.oauth.token);
if(result !== true) {
const err = result === false
? `Required scope: \`${required}\``
: result;
handleError(new InvalidScopeError(err), ctx);
return;
}
return next();
};
}
}
function handleResponse(ctx, response) {
debug(`Preparing success response (${response.status})`);
ctx.set(response.headers);
ctx.status = response.status;
ctx.body = response.body;
}
// Add custom headers to the context, then propagate error upwards
function handleError(err, ctx) {
debug(`Preparing error response (${err.code || 500})`);
const response = new Response(ctx.response);
ctx.set(response.headers);
ctx.status = err.code || 500;
throw err;
}
// Expose error classes
KoaOAuthServer.OAuthError = OAuthError;
KoaOAuthServer.InvalidScopeError = InvalidScopeError;
KoaOAuthServer.InvalidArgumentError = InvalidArgumentError;
KoaOAuthServer.UnauthorizedRequestError = UnauthorizedRequestError;
module.exports = KoaOAuthServer;