mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-09 12:00:37 -04:00
feat: mobile login enpoint (#51829)
Co-authored-by: Mrugesh Mohapatra <noreply@mrugesh.dev> Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
"@aws-sdk/client-ses": "3.441.0",
|
||||
"@fastify/cookie": "9.1.0",
|
||||
"@fastify/csrf-protection": "6.4.1",
|
||||
"@fastify/middie": "8.3",
|
||||
"@fastify/express": "^2.3.0",
|
||||
"@fastify/session": "10.5.0",
|
||||
"@fastify/swagger": "8.12.0",
|
||||
"@fastify/swagger-ui": "1.10.1",
|
||||
@@ -19,6 +19,7 @@
|
||||
"connect-mongo": "4.6.0",
|
||||
"date-fns": "2.30.0",
|
||||
"dotenv": "16.3.1",
|
||||
"express-rate-limit": "^6.7.0",
|
||||
"fast-uri": "2.3.0",
|
||||
"fastify": "4.24.3",
|
||||
"fastify-auth0-verify": "1.2.1",
|
||||
@@ -33,6 +34,7 @@
|
||||
"nodemon": "2.0.22",
|
||||
"pino-pretty": "10.2.3",
|
||||
"query-string": "7.1.3",
|
||||
"rate-limit-mongo": "^2.3.2",
|
||||
"stripe": "8.222.0"
|
||||
},
|
||||
"description": "The freeCodeCamp.org open-source codebase and curriculum",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fastifyCookie from '@fastify/cookie';
|
||||
import fastifyCsrfProtection from '@fastify/csrf-protection';
|
||||
import middie from '@fastify/middie';
|
||||
import express from '@fastify/express';
|
||||
import fastifySession from '@fastify/session';
|
||||
import fastifySwagger from '@fastify/swagger';
|
||||
import fastifySwaggerUI from '@fastify/swagger-ui';
|
||||
@@ -21,7 +21,6 @@ import Fastify, {
|
||||
import fastifyAuth0 from 'fastify-auth0-verify';
|
||||
|
||||
import prismaPlugin from './db/prisma';
|
||||
import { testMiddleware } from './middleware';
|
||||
import cors from './plugins/cors';
|
||||
import jwtAuthz from './plugins/fastify-jwt-authz';
|
||||
import { NodemailerProvider } from './plugins/mail-providers/nodemailer';
|
||||
@@ -33,7 +32,8 @@ import sessionAuth from './plugins/session-auth';
|
||||
import {
|
||||
auth0Routes,
|
||||
devLoginCallback,
|
||||
devLegacyAuthRoutes
|
||||
devLegacyAuthRoutes,
|
||||
mobileAuth0Routes
|
||||
} from './routes/auth';
|
||||
import { challengeRoutes } from './routes/challenge';
|
||||
import { deprecatedEndpoints } from './routes/deprecated-endpoints';
|
||||
@@ -106,7 +106,7 @@ export const build = async (
|
||||
return { hello: 'world' };
|
||||
});
|
||||
// NOTE: Awaited to ensure `.use` is registered on `fastify`
|
||||
await fastify.register(middie);
|
||||
await fastify.register(express);
|
||||
if (SENTRY_DSN) {
|
||||
await fastify.register(fastifySentry, { dsn: SENTRY_DSN });
|
||||
}
|
||||
@@ -202,11 +202,10 @@ export const build = async (
|
||||
void fastify.register(jwtAuthz);
|
||||
void fastify.register(sessionAuth);
|
||||
|
||||
void fastify.use('/test', testMiddleware);
|
||||
|
||||
void fastify.register(prismaPlugin);
|
||||
|
||||
void fastify.register(auth0Routes, { prefix: '/auth' });
|
||||
void fastify.register(mobileAuth0Routes);
|
||||
if (FCC_ENABLE_DEV_LOGIN_MODE) {
|
||||
void fastify.register(devLoginCallback, { prefix: '/auth' });
|
||||
void fastify.register(devLegacyAuthRoutes);
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import type { NextFunction, NextHandleFunction } from '@fastify/middie';
|
||||
|
||||
type MiddieRequest = Parameters<NextHandleFunction>[0];
|
||||
type MiddieResponse = Parameters<NextHandleFunction>[1];
|
||||
|
||||
/**
|
||||
* Test middleware used to log request and response data?
|
||||
*
|
||||
* @param req The request payload.
|
||||
* @param res The response to be sent back to the request.
|
||||
* @param next Callback function to indicate that the middleware logic is complete.
|
||||
*/
|
||||
export function testMiddleware(
|
||||
req: MiddieRequest,
|
||||
res: MiddieResponse,
|
||||
next: NextFunction
|
||||
): void {
|
||||
console.log('Test middleware running');
|
||||
console.log(req.headers);
|
||||
console.log(req.query);
|
||||
res.setHeader('X-Test-Header', 'test');
|
||||
next();
|
||||
}
|
||||
@@ -4,8 +4,12 @@ import {
|
||||
FastifyRequest
|
||||
} from 'fastify';
|
||||
|
||||
import rateLimit from 'express-rate-limit';
|
||||
// @ts-expect-error - no types
|
||||
import MongoStoreRL from 'rate-limit-mongo';
|
||||
|
||||
import { createUserInput } from '../utils/create-user';
|
||||
import { AUTH0_DOMAIN, HOME_LOCATION } from '../utils/env';
|
||||
import { AUTH0_DOMAIN, HOME_LOCATION, MONGOHQ_URL } from '../utils/env';
|
||||
|
||||
declare module 'fastify' {
|
||||
interface Session {
|
||||
@@ -85,7 +89,50 @@ export const devLoginCallback: FastifyPluginCallback = (
|
||||
export const auth0Routes: FastifyPluginCallback = (fastify, _options, done) => {
|
||||
fastify.addHook('onRequest', fastify.authenticate);
|
||||
|
||||
fastify.get('/callback', async req => {
|
||||
fastify.get('/auth0/callback', async req => {
|
||||
const email = await getEmailFromAuth0(req);
|
||||
|
||||
const { id } = await findOrCreateUser(fastify, email);
|
||||
req.session.user = { id };
|
||||
await req.session.save();
|
||||
});
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
/**
|
||||
* Route handler for Mobile authentication.
|
||||
*
|
||||
* @param fastify The Fastify instance.
|
||||
* @param _options Options passed to the plugin via `fastify.register(plugin, options)`.
|
||||
* @param done Callback to signal that the logic has completed.
|
||||
*/
|
||||
export const mobileAuth0Routes: FastifyPluginCallback = (
|
||||
fastify,
|
||||
_options,
|
||||
done
|
||||
) => {
|
||||
// Rate limit for mobile login
|
||||
// 10 requests per 15 minute windows
|
||||
void fastify.use(
|
||||
rateLimit({
|
||||
windowMs: 15 * 60 * 1000,
|
||||
max: 10,
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
keyGenerator: req => {
|
||||
return (req.headers['x-forwarded-for'] as string) || 'localhost';
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
||||
store: new MongoStoreRL({
|
||||
collectionName: 'UserRateLimit',
|
||||
uri: MONGOHQ_URL,
|
||||
expireTimeMs: 15 * 60 * 1000
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
fastify.get('/mobile-login', async req => {
|
||||
const email = await getEmailFromAuth0(req);
|
||||
|
||||
const { id } = await findOrCreateUser(fastify, email);
|
||||
|
||||
38
pnpm-lock.yaml
generated
38
pnpm-lock.yaml
generated
@@ -177,9 +177,9 @@ importers:
|
||||
'@fastify/csrf-protection':
|
||||
specifier: 6.4.1
|
||||
version: 6.4.1
|
||||
'@fastify/middie':
|
||||
specifier: '8.3'
|
||||
version: 8.3.0
|
||||
'@fastify/express':
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0
|
||||
'@fastify/session':
|
||||
specifier: 10.5.0
|
||||
version: 10.5.0
|
||||
@@ -213,6 +213,9 @@ importers:
|
||||
dotenv:
|
||||
specifier: 16.3.1
|
||||
version: 16.3.1
|
||||
express-rate-limit:
|
||||
specifier: ^6.7.0
|
||||
version: 6.7.0(express@4.18.2)
|
||||
fast-uri:
|
||||
specifier: 2.3.0
|
||||
version: 2.3.0
|
||||
@@ -255,6 +258,9 @@ importers:
|
||||
query-string:
|
||||
specifier: 7.1.3
|
||||
version: 7.1.3
|
||||
rate-limit-mongo:
|
||||
specifier: ^2.3.2
|
||||
version: 2.3.2
|
||||
stripe:
|
||||
specifier: 8.222.0
|
||||
version: 8.222.0
|
||||
@@ -6646,14 +6652,19 @@ packages:
|
||||
resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==}
|
||||
dev: false
|
||||
|
||||
/@fastify/error@3.3.0:
|
||||
resolution: {integrity: sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==}
|
||||
dev: false
|
||||
|
||||
/@fastify/error@3.4.1:
|
||||
resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==}
|
||||
dev: false
|
||||
|
||||
/@fastify/express@2.3.0:
|
||||
resolution: {integrity: sha512-jvvjlPPCfJsSHfF6tQDyARJ3+c3xXiqcxVZu6bi3xMWCWB3fl07vrjFDeaqnwqKhLZ9+m6cog5dw7gIMKEsTnQ==}
|
||||
dependencies:
|
||||
express: 4.18.2
|
||||
fastify-plugin: 4.5.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@fastify/fast-json-stringify-compiler@4.3.0:
|
||||
resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==}
|
||||
dependencies:
|
||||
@@ -6680,15 +6691,6 @@ packages:
|
||||
steed: 1.1.3
|
||||
dev: false
|
||||
|
||||
/@fastify/middie@8.3.0:
|
||||
resolution: {integrity: sha512-h+zBxCzMlkEkh4fM7pZaSGzqS7P9M0Z6rXnWPdUEPfe7x1BCj++wEk/pQ5jpyYY4pF8AknFqb77n7uwh8HdxEA==}
|
||||
dependencies:
|
||||
'@fastify/error': 3.3.0
|
||||
fastify-plugin: 4.5.1
|
||||
path-to-regexp: 6.2.1
|
||||
reusify: 1.0.4
|
||||
dev: false
|
||||
|
||||
/@fastify/send@2.1.0:
|
||||
resolution: {integrity: sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==}
|
||||
dependencies:
|
||||
@@ -25800,10 +25802,6 @@ packages:
|
||||
resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==}
|
||||
dev: true
|
||||
|
||||
/path-to-regexp@6.2.1:
|
||||
resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
|
||||
dev: false
|
||||
|
||||
/path-type@1.1.0:
|
||||
resolution: {integrity: sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
Reference in New Issue
Block a user