mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(next-api): basic authentication setup (#49378)
* feat(next-api): add fastify-auth0-verify plugin * feat(next-api): add fastify-jwt-authz plugin * feat(next-api): accept privacy endpoint with scopes support * fix(next-api): ignore eslint and ts errors They will be fixed in a future PR when the package with errors has been updated Co-authored-by: Niraj Nandish <nirajnandish@icloud.com> Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
committed by
Mrugesh Mohapatra
parent
1c9004046b
commit
7199f033fb
+14
-1
@@ -1,10 +1,13 @@
|
||||
import { config } from 'dotenv';
|
||||
config({ path: '../.env' });
|
||||
import fastifyAuth0 from 'fastify-auth0-verify';
|
||||
import Fastify from 'fastify';
|
||||
import middie from '@fastify/middie';
|
||||
|
||||
import jwtAuthz from './plugins/fastify-jwt-authz';
|
||||
import { testRoutes } from './routes/test';
|
||||
import { dbConnector } from './db';
|
||||
import { testMiddleware } from './middleware';
|
||||
import { auth0Verify, testMiddleware } from './middleware';
|
||||
|
||||
const fastify = Fastify({
|
||||
logger: { level: process.env.NODE_ENV === 'development' ? 'debug' : 'fatal' }
|
||||
@@ -18,8 +21,18 @@ const start = async () => {
|
||||
// NOTE: Awaited to ensure `.use` is registered on `fastify`
|
||||
await fastify.register(middie);
|
||||
|
||||
// Auth0 plugin
|
||||
void fastify.register(fastifyAuth0, {
|
||||
domain: process.env.AUTH0_DOMAIN,
|
||||
audience: process.env.AUTH0_AUDIENCE
|
||||
});
|
||||
void fastify.register(jwtAuthz);
|
||||
|
||||
void fastify.use('/test', testMiddleware);
|
||||
|
||||
// Hooks
|
||||
void fastify.addHook('preValidation', auth0Verify);
|
||||
|
||||
void fastify.register(dbConnector);
|
||||
void fastify.register(testRoutes);
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
import type { NextFunction, NextHandleFunction } from '@fastify/middie';
|
||||
|
||||
export async function auth0Verify() {
|
||||
// Verify user authorization code with Auth0
|
||||
export async function auth0Verify(
|
||||
this: FastifyInstance,
|
||||
request: FastifyRequest,
|
||||
reply: FastifyReply
|
||||
) {
|
||||
await this.authenticate(request, reply);
|
||||
}
|
||||
|
||||
type MiddieRequest = Parameters<NextHandleFunction>[0];
|
||||
|
||||
+3
-2
@@ -7,7 +7,8 @@
|
||||
"@fastify/middie": "8.1",
|
||||
"@fastify/mongodb": "6.1.0",
|
||||
"fastify": "4.9.2",
|
||||
"fastify-plugin": "4.3.0"
|
||||
"fastify-auth0-verify": "^1.0.0",
|
||||
"fastify-plugin": "^4.3.0"
|
||||
},
|
||||
"description": "The freeCodeCamp.org open-source codebase and curriculum",
|
||||
"engines": {
|
||||
@@ -35,7 +36,7 @@
|
||||
"build": "tsc",
|
||||
"develop": "nodemon index.ts",
|
||||
"start": "NODE_ENV=production node index.js",
|
||||
"test": "NODE_OPTIONS='--test-only' ts-node **/*.test.ts"
|
||||
"test": "node --test -r ts-node/register **/*.test.ts"
|
||||
},
|
||||
"version": "0.0.1"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Ethan Arrowood
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import assert from 'node:assert';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { describe, it } from 'node:test';
|
||||
import Fastify from 'fastify';
|
||||
import jwtAuthz from './fastify-jwt-authz';
|
||||
|
||||
interface ErrorResponse {
|
||||
statusCode: number;
|
||||
error: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
describe('fastify-jwt-authz', { only: true }, () => {
|
||||
it('should decorate request instance with jwtAuthz method', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get('/test', function (request) {
|
||||
assert(request.jwtAuthz);
|
||||
return { foo: 'bar' };
|
||||
});
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test'
|
||||
});
|
||||
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
});
|
||||
|
||||
it('should throw an error "Scopes cannot be empty" with an empty scopes parameter', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get(
|
||||
'/test2',
|
||||
{
|
||||
preHandler: function (request, _reply, done) {
|
||||
void request.jwtAuthz([], done);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
return { foo: 'bar' };
|
||||
}
|
||||
);
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test2'
|
||||
});
|
||||
const resData: ErrorResponse = res.json();
|
||||
|
||||
assert.strictEqual(res.statusCode, 500);
|
||||
assert.strictEqual(resData.message, 'Scopes cannot be empty');
|
||||
});
|
||||
|
||||
it('should throw an error "request.user does not exist" non existing request.user', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get(
|
||||
'/test3',
|
||||
{
|
||||
preHandler: function (request, _reply, done) {
|
||||
void request.jwtAuthz(['baz'], done);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
return { foo: 'bar' };
|
||||
}
|
||||
);
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test3'
|
||||
});
|
||||
const resData: ErrorResponse = res.json();
|
||||
|
||||
assert.strictEqual(res.statusCode, 500);
|
||||
assert.strictEqual(resData.message, 'request.user does not exist');
|
||||
});
|
||||
|
||||
it('should throw an error "request.user.scope must be a string"', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get(
|
||||
'/test4',
|
||||
{
|
||||
preHandler: function (request, _reply, done) {
|
||||
request.user = {
|
||||
name: 'sample',
|
||||
scope: 123
|
||||
};
|
||||
void request.jwtAuthz(['baz'], done);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
return { foo: 'bar' };
|
||||
}
|
||||
);
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test4'
|
||||
});
|
||||
const resData: ErrorResponse = res.json();
|
||||
|
||||
assert.strictEqual(res.statusCode, 500);
|
||||
assert.strictEqual(resData.message, 'request.user.scope must be a string');
|
||||
});
|
||||
|
||||
it('should throw an error "Insufficient scope"', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get(
|
||||
'/test5',
|
||||
{
|
||||
preHandler: function (request, _reply, done) {
|
||||
request.user = {
|
||||
name: 'sample',
|
||||
scope: 'baz'
|
||||
};
|
||||
void request.jwtAuthz(['foo'], done);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
return { foo: 'bar' };
|
||||
}
|
||||
);
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test5'
|
||||
});
|
||||
const resData: ErrorResponse = res.json();
|
||||
|
||||
assert.strictEqual(res.statusCode, 500);
|
||||
assert.strictEqual(resData.message, 'Insufficient scope');
|
||||
});
|
||||
|
||||
it('should verify user scope', async () => {
|
||||
const fastify = Fastify();
|
||||
await fastify.register(jwtAuthz);
|
||||
|
||||
fastify.get(
|
||||
'/test6',
|
||||
{
|
||||
preHandler: function (request, _reply, done) {
|
||||
request.user = {
|
||||
name: 'sample',
|
||||
scope: 'user manager'
|
||||
};
|
||||
void request.jwtAuthz(['user'], done);
|
||||
}
|
||||
},
|
||||
function () {
|
||||
return { foo: 'bar' };
|
||||
}
|
||||
);
|
||||
|
||||
fastify.listen({ port: 0 }, function () {
|
||||
fastify.server.unref();
|
||||
});
|
||||
|
||||
const res = await fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/test6'
|
||||
});
|
||||
|
||||
const resData: { foo: string } = res.json();
|
||||
|
||||
assert.strictEqual(res.statusCode, 200);
|
||||
assert.strictEqual(resData.foo, 'bar');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Ethan Arrowood
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import { FastifyPluginCallback, FastifyRequest } from 'fastify';
|
||||
import fp from 'fastify-plugin';
|
||||
|
||||
interface UserObject {
|
||||
scope: string;
|
||||
}
|
||||
|
||||
export interface JwtAuthz {
|
||||
(scopes: string[], callback: (err?: Error) => void): Promise<void>;
|
||||
}
|
||||
|
||||
const fastifyJwtAuthz: FastifyPluginCallback = (fastify, _opts, done) => {
|
||||
fastify.decorateRequest('jwtAuthz', checkScopes);
|
||||
|
||||
done();
|
||||
|
||||
function checkScopes(
|
||||
this: FastifyRequest,
|
||||
scopes: string[],
|
||||
callback: (err?: Error) => void
|
||||
) {
|
||||
if (callback === undefined) {
|
||||
return new Promise((resolve, reject) => {
|
||||
void this.jwtAuthz(scopes, function (err) {
|
||||
return err ? reject(err) : resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (scopes.length === 0) {
|
||||
return callback(new Error('Scopes cannot be empty'));
|
||||
}
|
||||
const user = this.user as UserObject;
|
||||
if (!user) {
|
||||
return callback(new Error('request.user does not exist'));
|
||||
}
|
||||
if (typeof user.scope !== 'string') {
|
||||
return callback(new Error('request.user.scope must be a string'));
|
||||
}
|
||||
|
||||
const userScopes = user.scope.split(' ');
|
||||
const allowed = scopes.some(scope => {
|
||||
return userScopes.indexOf(scope) !== -1;
|
||||
});
|
||||
|
||||
return callback(allowed ? undefined : new Error('Insufficient scope'));
|
||||
}
|
||||
};
|
||||
|
||||
declare module 'fastify' {
|
||||
interface FastifyRequest {
|
||||
jwtAuthz: JwtAuthz;
|
||||
}
|
||||
}
|
||||
|
||||
export default fp(fastifyJwtAuthz);
|
||||
+44
-1
@@ -1,4 +1,4 @@
|
||||
import { FastifyPluginCallback } from 'fastify';
|
||||
import { FastifyPluginCallback, FastifyRequest } from 'fastify';
|
||||
|
||||
export const testRoutes: FastifyPluginCallback = (fastify, _options, done) => {
|
||||
const collection = fastify.mongo.db?.collection('user');
|
||||
@@ -10,5 +10,48 @@ export const testRoutes: FastifyPluginCallback = (fastify, _options, done) => {
|
||||
const user = await collection?.findOne({ email: 'bar@bar.com' });
|
||||
return { user };
|
||||
});
|
||||
|
||||
fastify.put(
|
||||
'/update-privacy-terms',
|
||||
{
|
||||
preHandler: [
|
||||
function (
|
||||
req: FastifyRequest<{ Body: { quincyEmails: boolean } }>,
|
||||
_res,
|
||||
done
|
||||
) {
|
||||
void req.jwtAuthz(['write:user'], done);
|
||||
}
|
||||
],
|
||||
schema: {
|
||||
body: {
|
||||
required: ['quincyEmails'],
|
||||
properties: {
|
||||
quincyEmails: { type: 'boolean' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
(req, res) => {
|
||||
const {
|
||||
body: { quincyEmails }
|
||||
} = req;
|
||||
|
||||
const update = {
|
||||
acceptedPrivacyTerms: true,
|
||||
sendQuincyEmail: !!quincyEmails
|
||||
};
|
||||
|
||||
return collection
|
||||
?.updateOne({ email: 'bar@bar.com' }, { $set: update })
|
||||
.then(() => {
|
||||
void res.code(200).send({ msg: 'Successfully updated' });
|
||||
})
|
||||
.catch(err => {
|
||||
fastify.log.error(err);
|
||||
void res.code(500).send({ msg: 'Something went wrong' });
|
||||
});
|
||||
}
|
||||
);
|
||||
done();
|
||||
};
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true
|
||||
"resolveJsonModule": true,
|
||||
"typeRoots": ["../node_modules/@types", "../node_modules/@fastify"]
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+142
-3
@@ -117,7 +117,8 @@
|
||||
"@fastify/middie": "8.1",
|
||||
"@fastify/mongodb": "6.1.0",
|
||||
"fastify": "4.9.2",
|
||||
"fastify-plugin": "4.3.0"
|
||||
"fastify-auth0-verify": "^1.0.0",
|
||||
"fastify-plugin": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
@@ -4559,6 +4560,23 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@fastify/cookie": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-8.3.0.tgz",
|
||||
"integrity": "sha512-P9hY9GO11L20TnZ33XN3i0bt+3x0zaT7S0ohAzWO950E9PB2xnNhLYzPFJIGFi5AVN0yr5+/iZhWxeYvR6KCzg==",
|
||||
"dependencies": {
|
||||
"cookie": "^0.5.0",
|
||||
"fastify-plugin": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/cookie/node_modules/cookie": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/deepmerge": {
|
||||
"version": "1.3.0",
|
||||
"license": "MIT"
|
||||
@@ -4574,10 +4592,21 @@
|
||||
"fast-json-stringify": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/jwt": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/jwt/-/jwt-6.6.0.tgz",
|
||||
"integrity": "sha512-D5lYtj8M2Geh/njiNmC9DDw+1jVq9muc36xBrl8rp4n46f4a3vFNzJrCI4dcWIZqUmuki8hwM/zRSvU+Y5wy1g==",
|
||||
"dependencies": {
|
||||
"@fastify/error": "^3.0.0",
|
||||
"@lukeed/ms": "^2.0.0",
|
||||
"fast-jwt": "^2.0.0",
|
||||
"fastify-plugin": "^4.0.0",
|
||||
"steed": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/middie": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/middie/-/middie-8.1.0.tgz",
|
||||
"integrity": "sha512-VvUCLfKx2j6KSnh8puT8QW7d5YNzi2fD/4HcFvRQ3a7sHlCo+qtfX2fqzFvNqnMVbNft7GX1JL5if/riUiXsyg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fastify-plugin": "^4.0.0",
|
||||
"path-to-regexp": "^6.1.0",
|
||||
@@ -5946,6 +5975,14 @@
|
||||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lukeed/ms": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.1.tgz",
|
||||
"integrity": "sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@mdx-js/mdx": {
|
||||
"version": "1.6.22",
|
||||
"dev": true,
|
||||
@@ -20612,6 +20649,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/clone": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
|
||||
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/clone-deep": {
|
||||
"version": "4.0.1",
|
||||
"license": "MIT",
|
||||
@@ -25870,6 +25915,19 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-jwt": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-jwt/-/fast-jwt-2.2.0.tgz",
|
||||
"integrity": "sha512-0KSVmXROvYRCHzmmNzFMEDkd1mfbKopW1TfM2fELv5hZb/blUhfc7bxY7dJiagvR116Vhg6itk9LPUGFRQjRSg==",
|
||||
"dependencies": {
|
||||
"asn1.js": "^5.4.1",
|
||||
"ecdsa-sig-formatter": "^1.0.11",
|
||||
"mnemonist": "^0.39.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14 <20"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"license": "MIT"
|
||||
@@ -25928,6 +25986,17 @@
|
||||
"version": "1.0.12",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fastfall": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz",
|
||||
"integrity": "sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==",
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fastify": {
|
||||
"version": "4.9.2",
|
||||
"license": "MIT",
|
||||
@@ -25948,6 +26017,22 @@
|
||||
"tiny-lru": "^9.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fastify-auth0-verify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fastify-auth0-verify/-/fastify-auth0-verify-1.0.0.tgz",
|
||||
"integrity": "sha512-/nrfkq6qGgRoe72wwa7wE85aWajIbB/z2CYRXUDzQCd5OgvgsO/RRBGK33ZovuQ52DmjOJvNtqHQAPbcsPMK/Q==",
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^8.0.0",
|
||||
"@fastify/jwt": "^6.1.0",
|
||||
"fastify-plugin": "^4.0.0",
|
||||
"http-errors": "^2.0.0",
|
||||
"node-cache": "^5.0.1",
|
||||
"node-fetch": "^2.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fastify-plugin": {
|
||||
"version": "4.3.0",
|
||||
"license": "MIT"
|
||||
@@ -25979,6 +26064,15 @@
|
||||
"version": "4.0.0",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/fastparallel": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz",
|
||||
"integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==",
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.4",
|
||||
"xtend": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.13.0",
|
||||
"license": "ISC",
|
||||
@@ -25986,6 +26080,15 @@
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fastseries": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz",
|
||||
"integrity": "sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==",
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.0",
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fault": {
|
||||
"version": "1.0.4",
|
||||
"license": "MIT",
|
||||
@@ -38107,6 +38210,14 @@
|
||||
"version": "0.5.3",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mnemonist": {
|
||||
"version": "0.39.5",
|
||||
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.5.tgz",
|
||||
"integrity": "sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==",
|
||||
"dependencies": {
|
||||
"obliterator": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha": {
|
||||
"version": "10.2.0",
|
||||
"dev": true,
|
||||
@@ -38881,6 +38992,17 @@
|
||||
"version": "4.2.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-cache": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
|
||||
"integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
|
||||
"dependencies": {
|
||||
"clone": "2.x"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-dir": {
|
||||
"version": "0.1.17",
|
||||
"dev": true,
|
||||
@@ -39828,6 +39950,11 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/obliterator": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz",
|
||||
"integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ=="
|
||||
},
|
||||
"node_modules/obuf": {
|
||||
"version": "1.1.2",
|
||||
"license": "MIT"
|
||||
@@ -48621,6 +48748,18 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/steed": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/steed/-/steed-1.1.3.tgz",
|
||||
"integrity": "sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==",
|
||||
"dependencies": {
|
||||
"fastfall": "^1.5.0",
|
||||
"fastparallel": "^2.2.0",
|
||||
"fastq": "^1.3.0",
|
||||
"fastseries": "^1.7.0",
|
||||
"reusify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/store": {
|
||||
"version": "2.0.12",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -10,6 +10,7 @@ SENTRY_ENVIRONMENT=staging
|
||||
AUTH0_CLIENT_ID=client_id_from_auth0_dashboard
|
||||
AUTH0_CLIENT_SECRET=client_secret_from_auth0_dashboard
|
||||
AUTH0_DOMAIN=example.auth0.com
|
||||
AUTH0_AUDIENCE=sample_audience
|
||||
|
||||
# Session, Cookie and JWT encryption strings
|
||||
SESSION_SECRET=a_session_secret
|
||||
|
||||
Reference in New Issue
Block a user