From 1e330e0333e5c591784673e9d736594f3cf1e724 Mon Sep 17 00:00:00 2001 From: Etienne Soulard-Geoffrion Date: Mon, 11 Mar 2024 10:42:00 -0400 Subject: [PATCH] feat: api route proxy --- .env.example | 22 ++++++++ .gitignore | 4 ++ package.json | 2 + pnpm-lock.yaml | 106 +++++++++++++++++++++++++++++++++++++ src/pages/api/[...path].ts | 10 +--- 5 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..efb7889 --- /dev/null +++ b/.env.example @@ -0,0 +1,22 @@ +API_URL=http://localhost:7999 + +# Enable or disable authentication if disabled it will mock the user and session +AUTH_ENABLE=false +# This is the client ID of this app +AUTH_CLIENT_ID= +# This is the client secret of this app +AUTH_CLIENT_SECRET= +# This is the URL of the auth server +AUTH_ISSUER_URL=https://auth.dev.clinia.com +# This is the secret used to sign the session cookie +AUTH_SECRET= +# This is the URL to redirect to after logout +AUTH_POST_LOGOUT_REDIRECT_URI=https://auth.dev.clinia.com/logout + + + +# Instrumentation +OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:55679 +OTEL_EXPORTER_OTLP_INSECURE=true +OTEL_EXPORTER_OTLP_PROTOCOL=grpc +NEXT_OTEL_VERBOSE=1 diff --git a/.gitignore b/.gitignore index fd3dbb5..de9f5ab 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,7 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +.env +.env.* +!.env.example \ No newline at end of file diff --git a/package.json b/package.json index fceaeda..9395efe 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "test": "vitest" }, "dependencies": { + "@auth0/nextjs-auth0": "^3.5.0", "@clinia-ui/icons": "^0.1.8", "@clinia-ui/react": "^0.1.8", "@clinia/search-sdk-core": "^0.1.0", @@ -32,6 +33,7 @@ "devDependencies": { "@testing-library/react": "^14.2.1", "@trivago/prettier-plugin-sort-imports": "^4.3.0", + "@types/http-proxy": "^1.17.14", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 81e6b1a..887e841 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@auth0/nextjs-auth0': + specifier: ^3.5.0 + version: 3.5.0(next@14.1.0) '@clinia-ui/icons': specifier: ^0.1.8 version: 0.1.8(react@18.2.0) @@ -61,6 +64,9 @@ devDependencies: '@trivago/prettier-plugin-sort-imports': specifier: ^4.3.0 version: 4.3.0(prettier@3.2.5) + '@types/http-proxy': + specifier: ^1.17.14 + version: 1.17.14 '@types/node': specifier: ^20 version: 20.11.24 @@ -128,6 +134,26 @@ packages: '@jridgewell/gen-mapping': 0.3.4 '@jridgewell/trace-mapping': 0.3.23 + /@auth0/nextjs-auth0@3.5.0(next@14.1.0): + resolution: {integrity: sha512-uFZEE2QQf1zU+jRK2fwqxRQt+WSqDPYF2tnr7d6BEa7b6L6tpPJ3evzoImbWSY1a7gFdvD7RD/Rvrsx7B5CKVg==} + engines: {node: '>=16'} + peerDependencies: + next: '>=10' + dependencies: + '@panva/hkdf': 1.1.1 + cookie: 0.6.0 + debug: 4.3.4 + joi: 17.12.2 + jose: 4.15.5 + next: 14.1.0(@babel/core@7.24.0)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + oauth4webapi: 2.10.3 + openid-client: 5.6.5 + tslib: 2.6.2 + url-join: 4.0.1 + transitivePeerDependencies: + - supports-color + dev: false + /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -832,6 +858,16 @@ packages: yargs: 17.7.2 dev: false + /@hapi/hoek@9.3.0: + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + dev: false + + /@hapi/topo@5.1.0: + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + dependencies: + '@hapi/hoek': 9.3.0 + dev: false + /@hookform/resolvers@3.3.4(react-hook-form@7.48.2): resolution: {integrity: sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==} peerDependencies: @@ -1371,6 +1407,10 @@ packages: engines: {node: '>=14'} dev: false + /@panva/hkdf@1.1.1: + resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} + dev: false + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -4156,6 +4196,20 @@ packages: resolution: {integrity: sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==} dev: true + /@sideway/address@4.1.5: + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + dependencies: + '@hapi/hoek': 9.3.0 + dev: false + + /@sideway/formula@3.0.1: + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + dev: false + + /@sideway/pinpoint@2.0.0: + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + dev: false + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -4264,6 +4318,12 @@ packages: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true + /@types/http-proxy@1.17.14: + resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} + dependencies: + '@types/node': 20.11.24 + dev: true + /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true @@ -4929,6 +4989,11 @@ packages: /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + /cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -6243,6 +6308,20 @@ packages: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true + /joi@17.12.2: + resolution: {integrity: sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==} + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 + dev: false + + /jose@4.15.5: + resolution: {integrity: sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==} + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -6618,10 +6697,19 @@ packages: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: true + /oauth4webapi@2.10.3: + resolution: {integrity: sha512-9FkXEXfzVKzH63GUOZz1zMr3wBaICSzk6DLXx+CGdrQ10ItNk2ePWzYYc1fdmKq1ayGFb2aX97sRCoZ2s0mkDw==} + dev: false + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + /object-hash@2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + dev: false + /object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -6697,6 +6785,11 @@ packages: es-abstract: 1.22.5 dev: true + /oidc-token-hash@5.0.3: + resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} + engines: {node: ^10.13.0 || >=12.0.0} + dev: false + /on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -6715,6 +6808,15 @@ packages: mimic-fn: 4.0.0 dev: true + /openid-client@5.6.5: + resolution: {integrity: sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w==} + dependencies: + jose: 4.15.5 + lru-cache: 6.0.0 + object-hash: 2.2.0 + oidc-token-hash: 5.0.3 + dev: false + /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -7961,6 +8063,10 @@ packages: punycode: 2.3.1 dev: true + /url-join@4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + dev: false + /url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} dependencies: diff --git a/src/pages/api/[...path].ts b/src/pages/api/[...path].ts index 9298a6f..659a6f6 100644 --- a/src/pages/api/[...path].ts +++ b/src/pages/api/[...path].ts @@ -1,4 +1,4 @@ -import { getSession, withApiAuthRequired } from '@/lib/auth'; +import { withApiAuthRequired } from '@/lib/auth'; import { logger } from '@/logger'; import httpProxy from 'http-proxy'; import type { NextApiRequest, NextApiResponse } from 'next'; @@ -14,22 +14,16 @@ export const config = { // We are currently using this proxy to avoid CORS issues with the API. // We are using api routes from the page directory as it is easier to have a catch all route and using a reverse proxy. async function proxy(req: NextApiRequest, res: NextApiResponse) { - const session = await getSession(req, res); return new Promise((resolve, reject) => { if (req.url) { req.url = req.url.replace('/api', ''); } - // Set the authorization header to the idToken from the session - if (session?.idToken) { - req.headers.authorization = `Bearer ${session.idToken}`; - } - proxyServer.web( req, res, { - target: process.env.API_URL ?? 'http://localhost:3000', + target: process.env.API_URL ?? 'http://localhost:7999', }, (err: Error | null | undefined) => { if (err) {