Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit 748eb0d

Browse files
author
fireice.topcoder
committed
add authorization with cookie
1 parent 45daf54 commit 748eb0d

File tree

4 files changed

+138
-12
lines changed

4 files changed

+138
-12
lines changed

deploy/development.bat

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,6 @@ set WATERMARK_FILE_PATH=test/test_files/design_image_file_generator/studio_logo_
9090

9191
set WKHTMLTOIMAGE_COMMAND_PATH=/home/ubuntu/tmp/wkhtmltox-0.12.1/static-build/posix-local/wkhtmltox-0.12.1/bin/wkhtmltoimage
9292
set WKHTMLTOIMAGE_IMAGE_WIDTH=1024
93-
set HIGHLIGHT_STYLE_LINK=http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/%OVERRIDE_STYLE_NAME%.min.css
93+
set HIGHLIGHT_STYLE_LINK=http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/%OVERRIDE_STYLE_NAME%.min.css
94+
95+
set JWT_TOKEN_COOKIE_KEY="tcjwt_vm"

deploy/development.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,5 @@ export WATERMARK_FILE_PATH=test/test_files/design_image_file_generator/studio_lo
9696
export WKHTMLTOIMAGE_COMMAND_PATH=/home/ubuntu/tmp/wkhtmltox-0.12.1/static-build/posix-local/wkhtmltox-0.12.1/bin/wkhtmltoimage
9797
export WKHTMLTOIMAGE_IMAGE_WIDTH=1024
9898
export HIGHLIGHT_STYLE_LINK=http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.3/styles/%OVERRIDE_STYLE_NAME%.min.css
99+
100+
export JWT_TOKEN_COOKIE_KEY="tcjwt_vm"

initializers/middleware.js

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,27 @@ exports.middleware = function (api, next) {
8181
isCachedReturned,
8282
cacheKey,
8383
socialUserId,
84-
socialProvider;
85-
if (!_.isDefined(authHeader)) {
84+
socialProvider,
85+
cookieToken = api.utils.parseCookies(connection.rawConnection.req)[process.env.JWT_TOKEN_COOKIE_KEY];
86+
87+
if (_.isUndefined(authHeader) && _.isUndefined(cookieToken)) {
8688
connection.caller = {accessLevel: "anon"};
8789
next(connection, true);
8890
return;
8991
}
92+
9093
async.waterfall([
9194
function (cb) {
92-
var reg = /^bearer ([\s\S]+)$/i;
93-
if (!reg.test(authHeader)) {
94-
cb(new IllegalArgumentError("Malformed Auth header"));
95-
return;
95+
if (_.isUndefined(authHeader)) {
96+
cb(null, cookieToken);
97+
} else {
98+
var reg = /^bearer ([\s\S]+)$/i;
99+
if (!reg.test(authHeader)) {
100+
cb(new IllegalArgumentError("Malformed Auth header"));
101+
return;
102+
}
103+
cb(null, reg.exec(authHeader)[1]);
96104
}
97-
cb(null, reg.exec(authHeader)[1]);
98105
}, function (token, cb) {
99106
jwt.verify(token,
100107
api.config.tcConfig.oauthClientSecret,
@@ -107,6 +114,11 @@ exports.middleware = function (api, next) {
107114
return;
108115
}
109116
var split = decoded.sub.split("|");
117+
if (split.length == 1) {
118+
// token.sub should contain "|"
119+
cb(new IllegalArgumentError('Malformed Auth header. token.sub is in bad format!'));
120+
return;
121+
}
110122
try {
111123
socialUserId = (split[split.length-1] || "").trim();
112124
socialProvider = (split[0] || "").trim();
@@ -212,7 +224,8 @@ exports.middleware = function (api, next) {
212224
//error messages returned by jwt.verify(...) method
213225
if (err.message.indexOf('Invalid token') !== -1 ||
214226
String(err.message).startsWith("jwt audience invalid.") ||
215-
err.message === "invalid signature") {
227+
err.message === "invalid signature" ||
228+
err.message === "jwt malformed") {
216229
errorMessage = "Malformed Auth header";
217230
baseError = api.helper.apiCodes.badRequest;
218231
} else if (err.message === "jwt expired") {

test/test.oauth.js

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ describe('Test Oauth', function () {
4545
adminSubAD = "ad|400001",
4646
notFoundSub = "google-oauth|458965118758";
4747
var jwtToken = "";
48+
var jwtTokenCookieKey = process.env.JWT_TOKEN_COOKIE_KEY;
4849

4950

5051
/**
@@ -83,15 +84,19 @@ describe('Test Oauth', function () {
8384
* Create request and return it
8485
* @param {Number} statusCode the expected status code
8586
* @param {String} authHeader the Authorization header. Optional
87+
* @param {String} authCookie the Authorization cookie. Optional
8688
* @return {Object} request
8789
*/
88-
function createRequest(statusCode, authHeader) {
90+
function createRequest(statusCode, authHeader, authCookie) {
8991
var req = request(API_ENDPOINT)
9092
.get('/test/oauth')
9193
.set('Accept', 'application/json');
9294
if (authHeader) {
9395
req = req.set('Authorization', authHeader);
9496
}
97+
if (authCookie) {
98+
req = req.set('cookie', authCookie);
99+
}
95100
return req.expect('Content-Type', /json/).expect(statusCode);
96101
}
97102

@@ -114,6 +119,26 @@ describe('Test Oauth', function () {
114119
});
115120
}
116121

122+
/**
123+
* Get response and assert response from /test/oauth
124+
* @param {Object} expectedResponse the expected response
125+
* @param {String} authHeader the Authorization header. Optional
126+
* @param {String} authCookie the Authorization cookie. Optional
127+
* @param {Function<err>} done the callback
128+
*/
129+
function assertResponseWithCookie(expectedResponse, authHeader, authCookie, done) {
130+
createRequest(200, authHeader, authCookie)
131+
.end(function (err, res) {
132+
assert.ifError(err);
133+
assert.ok(res.body);
134+
var response = res.body;
135+
delete response.serverInformation;
136+
delete response.requesterInformation;
137+
assert.deepEqual(response, expectedResponse);
138+
done(err);
139+
});
140+
}
141+
117142
/**
118143
* Get response and assert response from /test/oauth
119144
* @param {Number} statusCode the expected status code
@@ -137,6 +162,30 @@ describe('Test Oauth', function () {
137162
});
138163
}
139164

165+
/**
166+
* Get response and assert response from /test/oauth
167+
* @param {Number} statusCode the expected status code
168+
* @param {String} authHeader the Authorization header. Optional
169+
* @param {String} authCookie the Authorization cookie. Optional
170+
* @param {String} errorMessage the expected error message header. Optional
171+
* @param {Function<err>} done the callback
172+
*/
173+
function assertErrorResponseWithCookie(statusCode, authHeader, authCookie, errorMessage, done) {
174+
createRequest(statusCode, authHeader, authCookie)
175+
.end(function (err, res) {
176+
if (err) {
177+
done(err);
178+
return;
179+
}
180+
if (errorMessage) {
181+
assert.ok(res.body);
182+
assert.ok(res.body.error);
183+
assert.equal(res.body.error.details, errorMessage);
184+
}
185+
done();
186+
});
187+
}
188+
140189

141190
/**
142191
* Generate an auth header
@@ -147,6 +196,15 @@ describe('Test Oauth', function () {
147196
return "Bearer " + jwt.sign(data || {}, SECRET, {expiresInMinutes: 1000, audience: CLIENT_ID});
148197
}
149198

199+
/**
200+
* Generate an auth cookie
201+
* @param {Object} data the data to generate
202+
* @return {String} the generated string
203+
*/
204+
function generateAuthCookie(data) {
205+
return jwtTokenCookieKey + "=" + jwt.sign(data || {}, SECRET, {expiresInMinutes: 1000, audience: CLIENT_ID});
206+
}
207+
150208
/**
151209
* /test/oauth/ with no header
152210
*/
@@ -245,11 +303,37 @@ describe('Test Oauth', function () {
245303
/**
246304
* /test/oauth/ with header
247305
*/
248-
it('should be authorized as admin (ac)', function (done) {
306+
it('should be authorized as admin (ad)', function (done) {
249307
var oauth = generateAuthHeader({ sub: adminSubAD});
250308
assertResponse({accessLevel: "admin", userId: 400001, handle: "admin_user"}, oauth, done);
251309
});
252310

311+
/**
312+
* /test/oauth/ with header and cookie
313+
*/
314+
it('should be authorized as admin (ad) with both header and cookie', function (done) {
315+
var authHeader = generateAuthHeader({ sub: adminSubAD});
316+
var authCookie = generateAuthCookie({ sub: adminSubAD});
317+
assertResponseWithCookie({accessLevel: "admin", userId: 400001, handle: "admin_user"}, authHeader, authCookie, done);
318+
});
319+
320+
/**
321+
* /test/oauth/ with header and cookie
322+
*/
323+
it('should be authorized as admin (ad) with header but invalid cookie', function (done) {
324+
var authHeader = generateAuthHeader({ sub: adminSubAD});
325+
var authCookie = jwtTokenCookieKey + "=asd";
326+
assertResponseWithCookie({accessLevel: "admin", userId: 400001, handle: "admin_user"}, authHeader, authCookie, done);
327+
});
328+
329+
/**
330+
* /test/oauth/ without header but with cookie
331+
*/
332+
it('should be authorized as admin (ad) without header but with cookie', function (done) {
333+
var authCookie = generateAuthCookie({ sub: adminSubAD});
334+
assertResponseWithCookie({accessLevel: "admin", userId: 400001, handle: "admin_user"}, null, authCookie, done);
335+
});
336+
253337
/**
254338
* /test/oauth/ with expired header
255339
*/
@@ -282,6 +366,23 @@ describe('Test Oauth', function () {
282366
assertErrorResponse(400, oauth + "asd", "Malformed Auth header", done);
283367
});
284368

369+
/**
370+
* /test/oauth/ with invalid header but valid cookie
371+
*/
372+
it('should return error if header is invalid but cookie is valid', function (done) {
373+
var authHeader = generateAuthHeader({ sub: userSubGoogle});
374+
var authCookie = generateAuthCookie({ sub: userSubGoogle});
375+
assertErrorResponseWithCookie(400, authHeader + "asd", authCookie, "Malformed Auth header", done);
376+
});
377+
378+
/**
379+
* /test/oauth/ with no header but invalid cookie
380+
*/
381+
it('should return error if no header provided but cookie is invalid', function (done) {
382+
var authCookie = generateAuthCookie({ sub: userSubGoogle});
383+
assertErrorResponseWithCookie(400, null, authCookie + "asd", "Malformed Auth header", done);
384+
});
385+
285386
/**
286387
* /test/oauth/ with invalid header
287388
*/
@@ -293,8 +394,16 @@ describe('Test Oauth', function () {
293394
/**
294395
* /test/oauth/ with invalid header
295396
*/
296-
it('should return error if header is invalid (no provider in sub)', function (done) {
397+
it('should return error if header is invalid (bad format)', function (done) {
297398
var oauth = generateAuthHeader({ sub: "123" });
399+
assertErrorResponse(400, oauth, "Malformed Auth header. token.sub is in bad format!", done);
400+
});
401+
402+
/**
403+
* /test/oauth/ with invalid header
404+
*/
405+
it('should return error if header is invalid (no provider in sub)', function (done) {
406+
var oauth = generateAuthHeader({ sub: "|123" });
298407
assertErrorResponse(400, oauth, "Malformed Auth header. No provider in token.sub!", done);
299408
});
300409

0 commit comments

Comments
 (0)