From 48d2e7919a40afbc6e5e150e37266de337695d02 Mon Sep 17 00:00:00 2001 From: Raymond Cheng Date: Thu, 14 Mar 2024 17:35:57 -0700 Subject: [PATCH] feat: adjust api auth route (#1062) * Elevate to user role, if you have a developer key but not on kariba data collective. previously this was stuck at anon role * Add JWT token decoding, just for seeing if we can get this to work * Up some API limits --- apps/frontend/app/api/auth/route.ts | 26 ++++++++++++++++++-------- apps/frontend/package.json | 1 + apps/hasura/metadata/api_limits.yaml | 4 ++-- pnpm-lock.yaml | 13 ++++++++++--- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/apps/frontend/app/api/auth/route.ts b/apps/frontend/app/api/auth/route.ts index e472f349a..05f173bfe 100644 --- a/apps/frontend/app/api/auth/route.ts +++ b/apps/frontend/app/api/auth/route.ts @@ -1,11 +1,13 @@ import { NextResponse, type NextRequest } from "next/server"; import { supabasePrivileged } from "../../../lib/clients/supabase"; +import { jwtDecode } from "jwt-decode"; //import { logger } from "../../../lib/logger"; export const runtime = "edge"; // 'nodejs' (default) | 'edge' //export const dynamic = "force-dynamic"; export const revalidate = 0; const CACHE_CONTROL = "max-age=3600"; // in seconds +const AUTH_PREFIX = "bearer"; const DATA_COLLECTIVE_TABLE = "data_collective"; const API_KEY_TABLE = "api_keys"; const USER_ID_COLUMN = "user_id"; @@ -15,13 +17,13 @@ const ALL_COLUMNS = `${USER_ID_COLUMN},${API_KEY_COLUMN},${DELETED_COLUMN}`; const makeAnonRole = () => ({ "x-hasura-role": "anonymous", }); -/** const makeUserRole = (userId: string) => ({ - "x-hasura-default-role": "user", - "x-hasura-allowed-roles": ["user"], + //"x-hasura-default-role": "user", + //"x-hasura-allowed-roles": ["user"], + "x-hasura-role": "user", "x-hasura-user-id": userId, + "cache-control": CACHE_CONTROL, }); -**/ const makeDevRole = (userId: string) => ({ "x-hasura-role": "developer", "x-hasura-user-id": userId, @@ -45,10 +47,18 @@ export async function GET(request: NextRequest) { // Get the token const trimmedAuth = auth.trim(); - const token = trimmedAuth.toLowerCase().startsWith("bearer") - ? trimmedAuth.slice(6).trim() + const token = trimmedAuth.toLowerCase().startsWith(AUTH_PREFIX) + ? trimmedAuth.slice(AUTH_PREFIX.length).trim() : trimmedAuth; + // Try JWT decoding + try { + const decoded = jwtDecode(token); + console.log("JWT token:", decoded); + } catch (e) { + console.warn("JWT error: ", e); + } + // Get the user const { data: keyData, error: keyError } = await supabasePrivileged .from(API_KEY_TABLE) @@ -79,10 +89,10 @@ export async function GET(request: NextRequest) { "Error retrieving data collective membership", collectiveError, ); - return NextResponse.json(makeAnonRole()); + return NextResponse.json(makeUserRole(userId)); } else if (collectiveData.length < 1) { // Not a member - return NextResponse.json(makeAnonRole()); + return NextResponse.json(makeUserRole(userId)); } // Passes all checks, elevate to developer role diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 1b250b893..0baeb70fc 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -45,6 +45,7 @@ "generate-api-key": "^1.0.2", "graphql": "^16.8.1", "instantsearch.css": "^8.1.0", + "jwt-decode": "^4.0.0", "next": "^14.1.0", "qs": "^6.11.2", "random-words": "^2.0.0", diff --git a/apps/hasura/metadata/api_limits.yaml b/apps/hasura/metadata/api_limits.yaml index e6ef1edbd..31747f9e3 100644 --- a/apps/hasura/metadata/api_limits.yaml +++ b/apps/hasura/metadata/api_limits.yaml @@ -3,8 +3,8 @@ node_limit: global: 100 per_role: anonymous: 10 - user: 10 - developer: 100 + user: 100 + developer: 1000 rate_limit: global: max_reqs_per_min: 1000 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3df342d80..984d6c1fe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,6 +150,9 @@ importers: instantsearch.css: specifier: ^8.1.0 version: 8.1.0 + jwt-decode: + specifier: ^4.0.0 + version: 4.0.0 next: specifier: ^14.1.0 version: 14.1.0(@babel/core@7.23.7)(react-dom@18.2.0)(react@18.2.0) @@ -3164,7 +3167,7 @@ packages: peerDependencies: react: '*' dependencies: - '@types/react': 18.2.64 + '@types/react': 18.2.65 prop-types: 15.8.1 react: 18.2.0 @@ -7852,7 +7855,7 @@ packages: resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.64 + '@types/react': 18.2.65 /@types/react-transition-group@4.4.10: resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} @@ -7880,7 +7883,6 @@ packages: '@types/prop-types': 15.7.11 '@types/scheduler': 0.16.8 csstype: 3.1.3 - dev: false /@types/readable-stream@2.3.15: resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} @@ -14557,6 +14559,11 @@ packages: safe-buffer: 5.2.1 dev: false + /jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} + dev: false + /keccak@3.0.4: resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} engines: {node: '>=10.0.0'}