Merge pull request #2439 from automatisch/api-token-authentication
feat: Implement authentication for API tokens
This commit is contained in:
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@@ -13,8 +13,8 @@ jobs:
|
|||||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||||
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@@ -32,8 +32,8 @@ jobs:
|
|||||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||||
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@@ -54,8 +54,8 @@ jobs:
|
|||||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||||
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@@ -76,8 +76,8 @@ jobs:
|
|||||||
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
|
||||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
|
||||||
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import User from '../models/user.js';
|
import User from '../models/user.js';
|
||||||
import AccessToken from '../models/access-token.js';
|
import AccessToken from '../models/access-token.js';
|
||||||
|
import ApiToken from '../models/api-token.ee.js';
|
||||||
|
|
||||||
export const isAuthenticated = async (req) => {
|
export const isAuthenticated = async (req) => {
|
||||||
const token = req.headers['authorization'];
|
const token = req.headers['authorization'];
|
||||||
@@ -46,3 +47,29 @@ export const authenticateUser = async (request, response, next) => {
|
|||||||
return response.status(401).end();
|
return response.status(401).end();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isApiTokenAuthenticated = async (request) => {
|
||||||
|
const token = request.headers['x-api-token'];
|
||||||
|
|
||||||
|
if (token == null) return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const apiToken = await ApiToken.query().findOne({
|
||||||
|
token,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (apiToken == null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const authenticateApiToken = async (request, response, next) => {
|
||||||
|
if (await isApiTokenAuthenticated(request)) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
return response.status(401).end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { isAuthenticated } from './authentication.js';
|
import { isAuthenticated, isApiTokenAuthenticated } from './authentication.js';
|
||||||
import { createUser } from '../../test/factories/user.js';
|
import { createUser } from '../../test/factories/user.js';
|
||||||
|
import { createApiToken } from '../../test/factories/api-token.js';
|
||||||
import createAuthTokenByUserId from '../helpers/create-auth-token-by-user-id.js';
|
import createAuthTokenByUserId from '../helpers/create-auth-token-by-user-id.js';
|
||||||
|
|
||||||
describe('isAuthenticated', () => {
|
describe('isAuthenticated', () => {
|
||||||
@@ -31,3 +32,22 @@ describe('isAuthenticated', () => {
|
|||||||
expect(await isAuthenticated(req)).toBe(false);
|
expect(await isAuthenticated(req)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('isApiTokenAuthenticated', () => {
|
||||||
|
it('should return false if no token is provided', async () => {
|
||||||
|
const req = { headers: {} };
|
||||||
|
expect(await isApiTokenAuthenticated(req)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if token is invalid', async () => {
|
||||||
|
const req = { headers: { 'x-api-token': 'invalidToken' } };
|
||||||
|
expect(await isApiTokenAuthenticated(req)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if token is valid', async () => {
|
||||||
|
const apiToken = await createApiToken();
|
||||||
|
|
||||||
|
const req = { headers: { 'x-api-token': apiToken.token } };
|
||||||
|
expect(await isApiTokenAuthenticated(req)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user