Skip to content

Commit

Permalink
refactor: simplify auth flow (#126)
Browse files Browse the repository at this point in the history
* refactor : remove unsued shared auth module

* refactor: authorize no longer be imported from auth util

* refactor: authenticate route no longer import from auth util

* refactor: get current auth use separate file

* feat: add try catch to catch unexcepted error

* fix: try catch on auth middleware

* fix: add checking when the response is not ok
  • Loading branch information
faiq-naufal authored Jan 17, 2024
1 parent 55bcc9c commit 97a4aa3
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 266 deletions.
126 changes: 0 additions & 126 deletions app/(server)/_shared/auth/auth.ts

This file was deleted.

7 changes: 0 additions & 7 deletions app/(server)/_shared/utils/auth.ts

This file was deleted.

36 changes: 36 additions & 0 deletions app/(server)/_shared/utils/get-current-authenticated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as Sentry from '@sentry/nextjs';
import { InliveApiFetcher } from '@/_shared/utils/fetcher';
import type { AuthType } from '@/_shared/types/auth';

export const getCurrentAuthenticated = async (token: string) => {
const response: AuthType.CurrentAuthExternalResponse =
await InliveApiFetcher.get('/auth/current', {
headers: {
Authorization: `Bearer ${token}`,
},
cache: 'no-cache',
});

if (!response || !response.ok) {
Sentry.captureMessage(
`API call error when trying to get current auth data`,
'error'
);
}

const data = response.data || {};

const result = {
code: response.code,
message: response.message || '',
ok: response.ok,
data: {
email: data.email || '',
id: data.id || 0,
name: data.name || '',
pictureUrl: data.picture_url || '',
},
};

return result;
};
128 changes: 86 additions & 42 deletions app/(server)/api/auth/[provider]/authenticate/route.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,97 @@
import { authenticate } from '@/(server)/_shared/utils/auth';
import { NextResponse, type NextRequest } from 'next/server';
import { cookies } from 'next/headers';
import * as Sentry from '@sentry/nextjs';
import { InliveApiFetcher } from '@/_shared/utils/fetcher';
import type { AuthType } from '@/_shared/types/auth';

const APP_ORIGIN = process.env.NEXT_PUBLIC_APP_ORIGIN || '';

export async function GET(
request: NextRequest,
{ params }: { params: { provider: string } }
) {
const url = new URL(request.url);
const currentPath = APP_ORIGIN + url.pathname;
const codeParam = url.searchParams.get('code') || '';
const stateParam = url.searchParams.get('state') || '';
const stateCookie = request.cookies.get('state')?.value || '';
const pathnameCookie = request.cookies.get('pathname')?.value || '';
const provider = params.provider;

if (stateParam === stateCookie) {
const authResponse = await authenticate(provider, currentPath, codeParam);

if (authResponse.data.token) {
const response = NextResponse.redirect(`${APP_ORIGIN}${pathnameCookie}`, {
status: 307,
});

const thirtyDays = 60 * 60 * 24 * 30;

response.cookies.set({
name: 'token',
value: authResponse.data.token,
path: '/',
sameSite: 'lax',
httpOnly: true,
maxAge: thirtyDays,
});

return response;
}
}
try {
const url = new URL(request.url);
const currentPath = APP_ORIGIN + url.pathname;
const codeParam = url.searchParams.get('code') || '';
const stateParam = url.searchParams.get('state') || '';
const stateCookie = request.cookies.get('state')?.value || '';
const pathnameCookie = request.cookies.get('pathname')?.value || '';
const provider = params.provider;

if (stateParam === stateCookie) {
const body = {
code: codeParam,
redirectURI: currentPath,
};

const authResponse: AuthType.AuthenticateExternalResponse =
await InliveApiFetcher.post(`/auth/${provider}/authenticate`, {
body: JSON.stringify(body),
});

if (!authResponse || !authResponse.ok) {
Sentry.captureMessage(
`API call error when trying to authenticate user. ${
authResponse?.message || ''
}`,
'error'
);

// If the authentication is not successful
return NextResponse.json(
{
code: 403,
message: 'Forbidden',
ok: false,
data: null,
},
{
status: 403,
throw new Error(
`Authentication error when trying to authenticate with ${provider} SSO`
);
}

if (!authResponse.data || !authResponse.data.token) {
Sentry.captureMessage(
`Authentication error. No token received from the server.`,
'error'
);
throw new Error(
`Authentication error. No token received from the server.`
);
} else {
const thirtyDays = 60 * 60 * 24 * 30;

cookies().set({
name: 'token',
value: authResponse.data.token,
path: '/',
sameSite: 'lax',
httpOnly: true,
maxAge: thirtyDays,
});

return NextResponse.redirect(`${APP_ORIGIN}${pathnameCookie}`, {
status: 307,
});
}
} else {
return NextResponse.json(
{
code: 403,
message:
'Forbidden to proceed further. Incorrect authentication state.',
ok: false,
data: null,
},
{
status: 403,
}
);
}
);
} catch (error: any) {
return NextResponse.json(
{
code: 500,
message: `Authentication error. ${error.message || ''}`,
ok: false,
data: null,
},
{
status: 500,
}
);
}
}
Loading

0 comments on commit 97a4aa3

Please sign in to comment.