From 47d1989ee58f47774a38cab0c61e96773f80dc94 Mon Sep 17 00:00:00 2001 From: Markus Thielker Date: Fri, 4 Apr 2025 16:20:32 +0200 Subject: [PATCH] NORY-59: add authentication and authorisation actions --- dashboard/src/lib/action/authentication.ts | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 dashboard/src/lib/action/authentication.ts diff --git a/dashboard/src/lib/action/authentication.ts b/dashboard/src/lib/action/authentication.ts new file mode 100644 index 0000000..d1d70e3 --- /dev/null +++ b/dashboard/src/lib/action/authentication.ts @@ -0,0 +1,106 @@ +'use server'; + +import { getFrontendApi, getPermissionApi } from '@/ory/sdk/server'; +import { cookies } from 'next/headers'; +import { redirect } from 'next/navigation'; + +export async function getSession() { + + const cookie = await cookies(); + + const frontendApi = await getFrontendApi(); + + return frontendApi + .toSession({ cookie: 'ory_kratos_session=' + cookie.get('ory_kratos_session')?.value }) + .then((response) => response.data) + .catch(() => null); +} + +export async function requireSession() { + + const session = await getSession(); + + if (!session) { + + // TODO: set return_to dynamically + const url = process.env.NEXT_PUBLIC_AUTHENTICATION_NODE_URL + + '/flow/login?return_to=' + process.env.NEXT_PUBLIC_DASHBOARD_NODE_URL; + + console.log('Intercepted request with missing session'); + console.log('Redirecting client to: ', url); + + redirect(url); + } + + return session; +} + + +export async function checkRole( + object: string, + subjectId: string, +) { + + const permissionApi = await getPermissionApi(); + return permissionApi.checkPermission({ + namespace: 'roles', + object, + relation: 'member', + subjectId, + }) + .then(({ data: { allowed } }) => allowed) + .catch(_ => false); +} + +export async function requireRole( + object: string, + subjectId: string, +) { + + const hasRole = await checkRole(object, subjectId); + + if (!hasRole) { + console.log(`Intercepted request with missing role ${object} for identity ${subjectId}`); + redirect('/unauthorised'); + } + + return hasRole; +} + + +export async function checkPermission( + object: string, + relation: string, + subjectId: string, +) { + + const permissionApi = await getPermissionApi(); + return permissionApi.checkPermission({ + namespace: 'permissions', + object, + relation, + subjectId, + }) + .then(({ data: { allowed } }) => allowed) + .catch(_ => false); +} + +export async function requirePermission( + object: string, + relation: string, + subjectId: string, +) { + + const allowed = await checkPermission( + object, + relation, + subjectId, + ); + + if (!allowed) { + console.log(`Intercepted request with insufficient permission (${object}#${relation}@${subjectId})`); + redirect('/unauthorised'); + } + + return allowed; +}