mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-02-17 14:30:34 +08:00
fix(api): JSON web token tests and fixes.
This commit is contained in:
parent
cd82729c5d
commit
30f7267c3e
89
packages/api/src/routes/auth/issueAccessToken.test.js
Normal file
89
packages/api/src/routes/auth/issueAccessToken.test.js
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright 2020-2021 Lowdefy, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import testContext from '../../test/testContext';
|
||||
import issueAccessToken from './issueAccessToken';
|
||||
|
||||
const secrets = {
|
||||
JWT_SECRET: 'JWT_SECRET',
|
||||
};
|
||||
|
||||
const RealDate = Date.now;
|
||||
|
||||
const mockNow = jest.fn();
|
||||
mockNow.mockImplementation(() => 1000);
|
||||
|
||||
beforeEach(() => {
|
||||
global.Date.now = mockNow;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
global.Date.now = RealDate;
|
||||
});
|
||||
|
||||
test('issueAccessToken', () => {
|
||||
const accessToken = issueAccessToken(testContext({ host: 'host', secrets }), {
|
||||
claims: { sub: 'sub', email: 'email' },
|
||||
});
|
||||
|
||||
const claims = jwt.verify(accessToken, 'JWT_SECRET', {
|
||||
algorithms: ['HS256'],
|
||||
audience: 'host',
|
||||
issuer: 'host',
|
||||
});
|
||||
expect(claims).toEqual({
|
||||
aud: 'host',
|
||||
email: 'email',
|
||||
exp: 14401, // 4 hours
|
||||
iat: 1,
|
||||
iss: 'host',
|
||||
sub: 'sub',
|
||||
lowdefy_access_token: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('issueAccessToken, configure token expiry', () => {
|
||||
const accessToken = issueAccessToken(
|
||||
testContext({
|
||||
config: {
|
||||
auth: {
|
||||
jwt: {
|
||||
expiresIn: '12h',
|
||||
},
|
||||
},
|
||||
},
|
||||
host: 'host',
|
||||
secrets,
|
||||
}),
|
||||
{ claims: { sub: 'sub', email: 'email' } }
|
||||
);
|
||||
const claims = jwt.verify(accessToken, 'JWT_SECRET', {
|
||||
algorithms: ['HS256'],
|
||||
audience: 'host',
|
||||
issuer: 'host',
|
||||
});
|
||||
expect(claims).toEqual({
|
||||
aud: 'host',
|
||||
email: 'email',
|
||||
exp: 43201, // 12 hours
|
||||
iat: 1,
|
||||
iss: 'host',
|
||||
sub: 'sub',
|
||||
lowdefy_access_token: true,
|
||||
});
|
||||
});
|
92
packages/api/src/routes/auth/issueOpenIdStateToken.test.js
Normal file
92
packages/api/src/routes/auth/issueOpenIdStateToken.test.js
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2020-2021 Lowdefy, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2020-2021 Lowdefy, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import testContext from '../../test/testContext';
|
||||
import issueOpenIdStateToken from './issueOpenIdStateToken';
|
||||
|
||||
const secrets = {
|
||||
JWT_SECRET: 'JWT_SECRET',
|
||||
};
|
||||
|
||||
const RealDate = Date.now;
|
||||
|
||||
const mockNow = jest.fn();
|
||||
mockNow.mockImplementation(() => 1000);
|
||||
|
||||
beforeEach(() => {
|
||||
global.Date.now = mockNow;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
global.Date.now = RealDate;
|
||||
});
|
||||
|
||||
test('issueOpenIdStateToken', async () => {
|
||||
const stateToken = issueOpenIdStateToken(testContext({ host: 'host', secrets }), {
|
||||
input: { i: true },
|
||||
pageId: 'pageId',
|
||||
urlQuery: { u: true },
|
||||
});
|
||||
const claims = jwt.verify(stateToken, 'JWT_SECRET', {
|
||||
algorithms: ['HS256'],
|
||||
audience: 'host',
|
||||
issuer: 'host',
|
||||
});
|
||||
expect(claims).toEqual({
|
||||
aud: 'host',
|
||||
exp: 301, // 5min
|
||||
iat: 1,
|
||||
input: { i: true },
|
||||
iss: 'host',
|
||||
lowdefy_openid_state_token: true,
|
||||
pageId: 'pageId',
|
||||
urlQuery: { u: true },
|
||||
});
|
||||
});
|
||||
|
||||
test('issueOpenIdStateToken, no location data', async () => {
|
||||
const stateToken = issueOpenIdStateToken(testContext({ host: 'host', secrets }), {});
|
||||
const claims = jwt.verify(stateToken, 'JWT_SECRET', {
|
||||
algorithms: ['HS256'],
|
||||
audience: 'host',
|
||||
issuer: 'host',
|
||||
});
|
||||
expect(claims).toEqual({
|
||||
aud: 'host',
|
||||
exp: 301, // 5min
|
||||
iat: 1,
|
||||
iss: 'host',
|
||||
lowdefy_openid_state_token: true,
|
||||
});
|
||||
});
|
97
packages/api/src/routes/auth/verifyAccessToken.test.js
Normal file
97
packages/api/src/routes/auth/verifyAccessToken.test.js
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright 2020-2021 Lowdefy, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import testContext from '../../test/testContext';
|
||||
import issueAccessToken from './issueAccessToken';
|
||||
import issueOpenIdStateToken from './issueOpenIdStateToken';
|
||||
import verifyAccessToken from './verifyAccessToken';
|
||||
|
||||
import { AuthenticationError, TokenExpiredError } from '../../context/errors';
|
||||
|
||||
const secrets = {
|
||||
JWT_SECRET: 'JWT_SECRET',
|
||||
};
|
||||
|
||||
const context = testContext({ host: 'host', secrets });
|
||||
|
||||
const RealDate = Date.now;
|
||||
|
||||
const mockNow = jest.fn();
|
||||
mockNow.mockImplementation(() => 1000);
|
||||
|
||||
beforeEach(() => {
|
||||
global.Date.now = mockNow;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
global.Date.now = RealDate;
|
||||
});
|
||||
|
||||
test('verifyAccessToken', () => {
|
||||
const token = issueAccessToken(context, {
|
||||
claims: { sub: 'sub', email: 'email' },
|
||||
});
|
||||
const claims = verifyAccessToken(context, { token });
|
||||
expect(claims).toEqual({
|
||||
aud: 'host',
|
||||
email: 'email',
|
||||
exp: 14401, // 4 hours
|
||||
iat: 1,
|
||||
iss: 'host',
|
||||
sub: 'sub',
|
||||
lowdefy_access_token: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('verifyAccessToken openIdState token invalid', () => {
|
||||
const token = issueOpenIdStateToken(context, {
|
||||
input: { i: true },
|
||||
pageId: 'pageId',
|
||||
urlQuery: { u: true },
|
||||
});
|
||||
expect(() => verifyAccessToken(context, { token })).toThrow(AuthenticationError);
|
||||
});
|
||||
|
||||
test('verifyAccessToken invalid token', () => {
|
||||
expect(() => verifyAccessToken(context, { token: 'not a token' })).toThrow(AuthenticationError);
|
||||
});
|
||||
|
||||
test('verifyAccessToken no sub invalid token', () => {
|
||||
const token = issueAccessToken(context, {
|
||||
claims: {
|
||||
email: 'email',
|
||||
},
|
||||
});
|
||||
expect(() => verifyAccessToken(context, { token })).toThrow(AuthenticationError);
|
||||
});
|
||||
|
||||
test('verifyAccessToken token expired', () => {
|
||||
const token = jwt.sign(
|
||||
{
|
||||
sub: 'sub',
|
||||
lowdefy_access_token: true,
|
||||
exp: -10000,
|
||||
},
|
||||
'JWT_SECRET',
|
||||
{
|
||||
audience: 'host',
|
||||
issuer: 'host',
|
||||
}
|
||||
);
|
||||
expect(() => verifyAccessToken(context, { token })).toThrow(TokenExpiredError);
|
||||
});
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { AuthenticationError, TokenExpiredError } from '../../context/errors';
|
||||
import { AuthenticationError } from '../../context/errors';
|
||||
|
||||
function verifyOpenIdStateToken({ host, secrets }, { token }) {
|
||||
try {
|
||||
@ -31,7 +31,7 @@ function verifyOpenIdStateToken({ host, secrets }, { token }) {
|
||||
return claims;
|
||||
} catch (err) {
|
||||
if (err.name === 'TokenExpiredError') {
|
||||
throw new TokenExpiredError('Token expired.');
|
||||
throw new AuthenticationError('Token expired.');
|
||||
} else {
|
||||
throw new AuthenticationError('Invalid token.');
|
||||
}
|
||||
|
90
packages/api/src/routes/auth/verifyOpenIdStateToken.test.js
Normal file
90
packages/api/src/routes/auth/verifyOpenIdStateToken.test.js
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 2020-2021 Lowdefy, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import testContext from '../../test/testContext';
|
||||
import issueAccessToken from './issueAccessToken';
|
||||
import issueOpenIdStateToken from './issueOpenIdStateToken';
|
||||
import verifyOpenIdStateToken from './verifyOpenIdStateToken';
|
||||
|
||||
import { AuthenticationError } from '../../context/errors';
|
||||
|
||||
const secrets = {
|
||||
JWT_SECRET: 'JWT_SECRET',
|
||||
};
|
||||
|
||||
const context = testContext({ host: 'host', secrets });
|
||||
|
||||
const RealDate = Date.now;
|
||||
|
||||
const mockNow = jest.fn();
|
||||
mockNow.mockImplementation(() => 1000);
|
||||
|
||||
beforeEach(() => {
|
||||
global.Date.now = mockNow;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
global.Date.now = RealDate;
|
||||
});
|
||||
|
||||
test('verifyOpenIdStateToken', () => {
|
||||
const token = issueOpenIdStateToken(context, {
|
||||
input: { i: true },
|
||||
pageId: 'pageId',
|
||||
urlQuery: { u: true },
|
||||
});
|
||||
const claims = verifyOpenIdStateToken(context, { token });
|
||||
expect(claims).toEqual({
|
||||
aud: 'host',
|
||||
exp: 301, // 5min
|
||||
iat: 1,
|
||||
input: { i: true },
|
||||
iss: 'host',
|
||||
lowdefy_openid_state_token: true,
|
||||
pageId: 'pageId',
|
||||
urlQuery: { u: true },
|
||||
});
|
||||
});
|
||||
|
||||
test('verifyOpenIdStateToken access token invalid', () => {
|
||||
const token = issueAccessToken(context, {
|
||||
claims: { sub: 'sub', email: 'email' },
|
||||
});
|
||||
expect(() => verifyOpenIdStateToken(context, { token })).toThrow(AuthenticationError);
|
||||
});
|
||||
|
||||
test('verifyOpenIdStateToken invalid token', () => {
|
||||
expect(() => verifyOpenIdStateToken(context, { token: 'not a token' })).toThrow(
|
||||
AuthenticationError
|
||||
);
|
||||
});
|
||||
|
||||
test('verifyOpenIdStateToken token expired', () => {
|
||||
const token = jwt.sign(
|
||||
{
|
||||
lowdefy_openid_state_token: true,
|
||||
exp: -10000,
|
||||
},
|
||||
'JWT_SECRET',
|
||||
{
|
||||
audience: 'host',
|
||||
issuer: 'host',
|
||||
}
|
||||
);
|
||||
expect(() => verifyOpenIdStateToken(context, { token })).toThrow(AuthenticationError);
|
||||
});
|
@ -28,8 +28,8 @@ async function run() {
|
||||
// configDirectory: path.resolve(process.cwd(), '../docs'),
|
||||
// configDirectory: path.resolve(process.cwd(), '../servers/serverDev'),
|
||||
configDirectory: process.cwd(),
|
||||
// outputDirectory: path.resolve(process.cwd(), '../servers/serverDev/.lowdefy/build'),
|
||||
outputDirectory: path.resolve(process.cwd(), './.lowdefy/build'),
|
||||
outputDirectory: path.resolve(process.cwd(), '../servers/serverDev/.lowdefy/build'),
|
||||
// outputDirectory: path.resolve(process.cwd(), './.lowdefy/build'),
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user