Skip to content

Commit

Permalink
chore: check error message text in tests
Browse files Browse the repository at this point in the history
check error message text as well as codes in tests
  • Loading branch information
emonddr committed May 2, 2019
1 parent 5a5299c commit 6427f68
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@ describe('Basic Authentication', () => {
it('returns error for missing Authorization header', async () => {
const client = whenIMakeRequestTo(server);

//not passing in 'Authorization' header
await client.get('/whoAmI').expect(401);
await client.get('/whoAmI').expect({
error: {
message: 'Authorization header not found.',
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it(`returns error for missing 'Basic ' portion of Authorization header value`, async () => {
Expand All @@ -69,7 +74,13 @@ describe('Basic Authentication', () => {
{alternativePrefix: 'NotB@sic '},
),
)
.expect(401);
.expect({
error: {
message: `Authorization header is not of type 'Basic'.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it(`returns error for too many parts in Authorization header value`, async () => {
Expand All @@ -83,12 +94,17 @@ describe('Basic Authentication', () => {
users.list['[email protected]'].password,
) + ' someOtherValue',
)
.expect(401);
.expect({
error: {
message: `Authorization header value has too many parts. It must follow the pattern: 'Basic xxyyzz' where xxyyzz is a base64 string.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it(`returns error for missing ':' in decrypted Authorization header credentials value`, async () => {
const client = whenIMakeRequestTo(server);
// substituting ':' with '|'
await client
.get('/whoAmI')
.set(
Expand All @@ -99,7 +115,13 @@ describe('Basic Authentication', () => {
{alternativeSeparator: '|'},
),
)
.expect(401);
.expect({
error: {
message: `Authorization header 'Basic' value does not contain two parts separated by ':'.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it(`returns error for too many parts in decrypted Authorization header credentials value`, async () => {
Expand All @@ -114,7 +136,13 @@ describe('Basic Authentication', () => {
{extraSegment: 'extraPart'},
),
)
.expect(401);
.expect({
error: {
message: `Authorization header 'Basic' value does not contain two parts separated by ':'.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('allows anonymous requests to methods with no decorator', async () => {
Expand All @@ -131,6 +159,56 @@ describe('Basic Authentication', () => {
.expect(200, {running: true});
});

it('returns error for unknown authentication strategy', async () => {
class InfoController {
@get('/status')
@authenticate('doesnotexist')
status() {
return {running: true};
}
}

app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect({
error: {
message: `The strategy 'doesnotexist' is not available.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('returns error when undefined user profile returned from authentication strategy', async () => {
class BadBasicStrategy implements AuthenticationStrategy {
name: string = 'badbasic';
async authenticate(request: Request): Promise<UserProfile | undefined> {
return undefined;
}
}
registerAuthenticationStrategy(server, BadBasicStrategy);

class InfoController {
@get('/status')
@authenticate('badbasic')
status() {
return {running: true};
}
}

app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect({
error: {
message: `User profile not returned from strategy's authenticate function`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

async function givenAServer() {
app = getApp();
server = await app.getServer(RestServer);
Expand Down Expand Up @@ -170,44 +248,6 @@ describe('Basic Authentication', () => {
app.controller(MyController);
}

it('returns error for unknown authentication strategy', async () => {
class InfoController {
@get('/status')
@authenticate('doesnotexist')
status() {
return {running: true};
}
}

app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect(401);
});

it('returns error when undefined user profile returned from authentication strategy', async () => {
class BadBasicStrategy implements AuthenticationStrategy {
name: string = 'badbasic';
async authenticate(request: Request): Promise<UserProfile | undefined> {
return undefined;
}
}
registerAuthenticationStrategy(server, BadBasicStrategy);

class InfoController {
@get('/status')
@authenticate('badbasic')
status() {
return {running: true};
}
}

app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect(401);
});

function givenAuthenticatedSequence() {
// bind user defined sequence
server.sequence(MyAuthenticationSequence);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import {
registerAuthenticationStrategy,
UserProfile,
} from '../..';
import {getApp, getUserRepository} from '../fixtures/helper';
import {
createBearerAuthorizationHeaderValue,
getApp,
getUserRepository,
} from '../fixtures/helper';
import {JWTAuthenticationStrategyBindings, USER_REPO} from '../fixtures/keys';
import {MyAuthenticationSequence} from '../fixtures/sequences/authentication.sequence';
import {JWTService} from '../fixtures/services/jwt-service';
Expand Down Expand Up @@ -81,7 +85,7 @@ describe('JWT Authentication', () => {

const email = (await whenIMakeRequestTo(server)
.get('/whoAmI')
.set('Authorization', 'Bearer ' + token)
.set('Authorization', createBearerAuthorizationHeaderValue(token))
.expect(200)).text;

expect(email).to.equal(testUsers.list['[email protected]'].email);
Expand Down Expand Up @@ -134,10 +138,15 @@ describe('JWT Authentication', () => {
expect(token).to.be.not.null();
expect(token).to.be.String();

//not passing in 'Authorization' header
await whenIMakeRequestTo(server)
.get('/whoAmI')
.expect(401);
.expect({
error: {
message: 'Authorization header not found.',
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it(`returns error for invalid 'Bearer ' portion of Authorization header value`, async () => {
Expand Down Expand Up @@ -187,11 +196,19 @@ describe('JWT Authentication', () => {
expect(token).to.be.not.null();
expect(token).to.be.String();

// not specifying an `Authorization` header value
await whenIMakeRequestTo(server)
.get('/whoAmI')
.set('Authorization', 'NotB3ar3r ' + token)
.expect(401);
.set(
'Authorization',
createBearerAuthorizationHeaderValue(token, 'NotB3ar3r '),
)
.expect({
error: {
message: `Authorization header is not of type 'Bearer'.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it(`returns error for too many parts in Authorization header value`, async () => {
Expand Down Expand Up @@ -241,11 +258,19 @@ describe('JWT Authentication', () => {
expect(token).to.be.not.null();
expect(token).to.be.String();

// not specifying an `Authorization` header value
await whenIMakeRequestTo(server)
.get('/whoAmI')
.set('Authorization', 'Bearer ' + token + ' someOtherValue')
.expect(401);
.set(
'Authorization',
createBearerAuthorizationHeaderValue(token) + ' someOtherValue',
)
.expect({
error: {
message: `Authorization header value has too many parts. It must follow the pattern: 'Bearer xx.yy.zz' where xx.yy.zz is a valid JWT token.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('returns error due to expired token', async () => {
Expand All @@ -270,8 +295,14 @@ describe('JWT Authentication', () => {

await whenIMakeRequestTo(server)
.get('/whoAmI')
.set('Authorization', 'Bearer ' + expiredToken)
.expect(401);
.set('Authorization', createBearerAuthorizationHeaderValue(expiredToken))
.expect({
error: {
message: `Error verifying token : jwt expired`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('returns error due to invalid token #1', async () => {
Expand All @@ -295,8 +326,14 @@ describe('JWT Authentication', () => {

await whenIMakeRequestTo(server)
.get('/whoAmI')
.set('Authorization', 'Bearer ' + invalidToken)
.expect(401);
.set('Authorization', createBearerAuthorizationHeaderValue(invalidToken))
.expect({
error: {
message: 'Error verifying token : invalid token',
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('returns error due to invalid token #2', async () => {
Expand All @@ -320,8 +357,14 @@ describe('JWT Authentication', () => {

await whenIMakeRequestTo(server)
.get('/whoAmI')
.set('Authorization', 'Bearer ' + invalidToken)
.expect(401);
.set('Authorization', createBearerAuthorizationHeaderValue(invalidToken))
.expect({
error: {
message: 'Error verifying token : jwt malformed',
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('creates a json web token and throws error for missing email', async () => {
Expand Down Expand Up @@ -351,7 +394,13 @@ describe('JWT Authentication', () => {

await whenIMakeRequestTo(server)
.get('/createtoken')
.expect(401);
.expect({
error: {
message: `Error generating token : userProfile 'email' is null`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('creates a json web token and throws error for missing name', async () => {
Expand Down Expand Up @@ -381,7 +430,13 @@ describe('JWT Authentication', () => {

await whenIMakeRequestTo(server)
.get('/createtoken')
.expect(401);
.expect({
error: {
message: `Error generating token : userProfile 'name' is null`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('allows anonymous requests to methods with no decorator', async () => {
Expand Down Expand Up @@ -410,7 +465,13 @@ describe('JWT Authentication', () => {
app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect(401);
.expect({
error: {
message: `The strategy 'doesnotexist' is not available.`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

it('returns error when undefined user profile returned from authentication strategy', async () => {
Expand All @@ -433,7 +494,13 @@ describe('JWT Authentication', () => {
app.controller(InfoController);
await whenIMakeRequestTo(server)
.get('/status')
.expect(401);
.expect({
error: {
message: `User profile not returned from strategy's authenticate function`,
name: 'UnauthorizedError',
statusCode: 401,
},
});
});

async function givenAServer() {
Expand Down
9 changes: 9 additions & 0 deletions packages/authentication/src/__tests__/fixtures/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,12 @@ export function createBasicAuthorizationHeaderValue(
)
);
}

export function createBearerAuthorizationHeaderValue(
token: string,
alternativePrefix?: string,
): string {
// default type is 'Bearer ', unless another is specified
const prefix = alternativePrefix ? alternativePrefix : 'Bearer ';
return prefix + token;
}
Loading

0 comments on commit 6427f68

Please sign in to comment.