mirror of https://github.com/boxyhq/jackson.git
Use middleware to validate the API requests (#792)
* Update * Validate the API routes in the middleware * Validate the setuplink token by calling the API * Tweaks * unAuthorizedResponse method now accept a message * Update middleware * Cleanup * Update message * Removed CheckSession - Not needed anymore * Updates to API authentication middleware * Updates to API authentication middleware * Remove the use of checkSession from retraced admin APIs Co-authored-by: Deepak Prabhakara <deepak@boxyhq.com>
This commit is contained in:
parent
b4c98be9f4
commit
eb80fb5297
|
@ -1,7 +1,6 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
import type { SAMLFederationApp } from '@boxyhq/saml-jackson';
|
||||
import { strings } from '@lib/strings';
|
||||
|
||||
|
@ -101,4 +100,4 @@ const handleDELETE = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import { checkSession } from '@lib/middleware';
|
||||
import jackson from '@lib/jackson';
|
||||
import { strings } from '@lib/strings';
|
||||
|
||||
|
@ -65,4 +64,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
return res.json({ data: apps });
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import Cors from 'cors';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { getToken } from 'next-auth/jwt';
|
||||
import { sessionName } from './constants';
|
||||
|
||||
// Initializing the cors middleware
|
||||
const corsFunction = Cors({
|
||||
|
@ -25,19 +23,3 @@ function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: any) {
|
|||
export async function cors(req: NextApiRequest, res: NextApiResponse) {
|
||||
return await runMiddleware(req, res, corsFunction);
|
||||
}
|
||||
|
||||
export const checkSession = (handler) => async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const token = await getToken({
|
||||
req,
|
||||
cookieName: sessionName,
|
||||
});
|
||||
|
||||
if (token) {
|
||||
// Signed in
|
||||
return handler(req, res);
|
||||
} else {
|
||||
// Not Signed in
|
||||
res.status(401);
|
||||
}
|
||||
res.end();
|
||||
};
|
||||
|
|
|
@ -1,17 +1,69 @@
|
|||
// eslint-disable-next-line
|
||||
import type { NextRequest } from 'next/server';
|
||||
// eslint-disable-next-line
|
||||
import { NextResponse } from 'next/server';
|
||||
import { validateApiKey, extractAuthToken } from '@lib/auth';
|
||||
import { getToken } from 'next-auth/jwt';
|
||||
import { sessionName } from '@lib/constants';
|
||||
import micromatch from 'micromatch';
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const pathname = req.nextUrl.pathname;
|
||||
// Add API routes that don't require authentication
|
||||
const unAuthenticatedApiRoutes = [
|
||||
'/api/health',
|
||||
'/api/hello',
|
||||
'/api/auth/**',
|
||||
'/api/federated-saml/**',
|
||||
'/api/logout/**',
|
||||
'/api/oauth/**',
|
||||
'/api/scim/v2.0/**',
|
||||
'/api/well-known/**',
|
||||
'/api/setup/**',
|
||||
];
|
||||
|
||||
if (pathname.startsWith('/api/v1')) {
|
||||
if (!validateApiKey(extractAuthToken(req))) {
|
||||
return NextResponse.rewrite(new URL('/api/v1/unauthenticated', req.nextUrl));
|
||||
}
|
||||
export async function middleware(req: NextRequest) {
|
||||
const { pathname } = req.nextUrl;
|
||||
|
||||
// Bypass routes that don't require authentication
|
||||
if (micromatch.isMatch(pathname, unAuthenticatedApiRoutes)) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
// Validate API routes `/api/admin/**`
|
||||
if (micromatch.isMatch(pathname, '/api/admin/**')) {
|
||||
const adminToken = await getToken({
|
||||
req,
|
||||
cookieName: sessionName,
|
||||
});
|
||||
|
||||
if (!adminToken) {
|
||||
return sendUnAuthorizedResponse({ message: 'Unauthorized' });
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
// Validate API routes `/api/v1/**`
|
||||
if (micromatch.isMatch(pathname, '/api/v1/**')) {
|
||||
if (!validateApiKey(extractAuthToken(req))) {
|
||||
return sendUnAuthorizedResponse({ message: 'Unauthorized' });
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
// By default, deny access to all other routes
|
||||
return sendUnAuthorizedResponse({ message: 'Unauthorized' });
|
||||
}
|
||||
|
||||
// Send 401 response for unauthenticated requests
|
||||
const sendUnAuthorizedResponse = async (error: { message: string }) => {
|
||||
const response = JSON.stringify({ error });
|
||||
|
||||
return new NextResponse(response, {
|
||||
status: 401,
|
||||
headers: { 'content-type': 'application/json' },
|
||||
});
|
||||
};
|
||||
|
||||
// Limit the middleware to specific '/api/*' routes
|
||||
export const config = {
|
||||
matcher: ['/api/:path*'],
|
||||
};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -34,4 +33,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -6,7 +6,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
|
||||
switch (method) {
|
||||
case 'GET':
|
||||
return handleGET(req, res);
|
||||
return await handleGET(req, res);
|
||||
default:
|
||||
res.setHeader('Allow', 'GET');
|
||||
res.status(405).json({ error: { message: `Method ${method} Not Allowed` } });
|
||||
|
|
|
@ -2,7 +2,6 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
|||
|
||||
import jackson from '@lib/jackson';
|
||||
import { strategyChecker } from '@lib/utils';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -118,4 +117,4 @@ const handleDELETE = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -36,4 +35,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
return res.status(200).json({ data: event });
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -64,4 +63,4 @@ const handleDELETE = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
return res.status(200).json({ data: null });
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -39,4 +38,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -42,4 +41,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
export const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -58,4 +57,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -39,4 +38,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -42,4 +41,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import type { DirectoryType } from '@boxyhq/saml-jackson';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -59,4 +58,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -23,4 +22,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
return res.json({ data: providers });
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -3,7 +3,6 @@ import axios from 'axios';
|
|||
|
||||
import { getToken } from '@lib/retraced';
|
||||
import { retracedOptions } from '@lib/env';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { method } = req;
|
||||
|
@ -46,4 +45,4 @@ const getGroups = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
});
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -4,7 +4,6 @@ import axios from 'axios';
|
|||
import type { Project } from 'types/retraced';
|
||||
import { getToken } from '@lib/retraced';
|
||||
import { retracedOptions } from '@lib/env';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { method } = req;
|
||||
|
@ -41,4 +40,4 @@ const getProject = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
});
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -2,7 +2,6 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
|||
import * as Retraced from '@retracedhq/retraced';
|
||||
|
||||
import { retracedOptions } from '@lib/env';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { method } = req;
|
||||
|
@ -41,4 +40,4 @@ const getViewerToken = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
});
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -4,7 +4,6 @@ import axios from 'axios';
|
|||
import type { Project } from 'types/retraced';
|
||||
import { getToken } from '@lib/retraced';
|
||||
import { retracedOptions } from '@lib/env';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { method } = req;
|
||||
|
@ -74,4 +73,4 @@ const getProjects = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import jackson from '@lib/jackson';
|
||||
import { checkSession } from '@lib/middleware';
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { method } = req;
|
||||
|
@ -84,4 +83,4 @@ const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default checkSession(handler);
|
||||
export default handler;
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
return res.status(401).json({ data: null, error: { message: 'Unauthorized' } });
|
||||
}
|
Loading…
Reference in New Issue