allow access token in resource url

This commit is contained in:
Milo Schwartz 2025-01-11 19:47:07 -05:00
parent e32301ade4
commit f5fda5d8ea
No known key found for this signature in database
10 changed files with 226 additions and 55 deletions

View file

@ -7,6 +7,7 @@ import { response } from "@server/lib/response";
import { validateSessionToken } from "@server/auth/sessions/app";
import db from "@server/db";
import {
ResourceAccessToken,
resourceAccessToken,
resourcePassword,
resourcePincode,
@ -17,9 +18,15 @@ import {
} from "@server/db/schema";
import { and, eq } from "drizzle-orm";
import config from "@server/lib/config";
import { validateResourceSessionToken } from "@server/auth/sessions/resource";
import {
createResourceSession,
serializeResourceSessionCookie,
validateResourceSessionToken
} from "@server/auth/sessions/resource";
import { Resource, roleResources, userResources } from "@server/db/schema";
import logger from "@server/logger";
import { verifyResourceAccessToken } from "@server/auth/verifyResourceAccessToken";
import { generateSessionToken } from "@server/auth";
const verifyResourceSessionSchema = z.object({
sessions: z.record(z.string()).optional(),
@ -28,6 +35,7 @@ const verifyResourceSessionSchema = z.object({
host: z.string(),
path: z.string(),
method: z.string(),
accessToken: z.string().optional(),
tls: z.boolean()
});
@ -59,7 +67,8 @@ export async function verifyResourceSession(
}
try {
const { sessions, host, originalRequestURL } = parsedBody.data;
const { sessions, host, originalRequestURL, accessToken: token } =
parsedBody.data;
const [result] = await db
.select()
@ -103,11 +112,41 @@ export async function verifyResourceSession(
const redirectUrl = `${config.getRawConfig().app.dashboard_url}/auth/resource/${encodeURIComponent(resource.resourceId)}?redirect=${encodeURIComponent(originalRequestURL)}`;
// check for access token
let validAccessToken: ResourceAccessToken | undefined;
if (token) {
const [accessTokenId, accessToken] = token.split(".");
const { valid, error, tokenItem } = await verifyResourceAccessToken(
{
resource,
accessTokenId,
accessToken
}
);
if (error) {
logger.debug("Access token invalid: " + error);
}
if (valid && tokenItem) {
validAccessToken = tokenItem;
if (!sessions) {
return await createAccessTokenSession(
res,
resource,
tokenItem
);
}
}
}
if (!sessions) {
return notAllowed(res);
}
const sessionToken = sessions[config.getRawConfig().server.session_cookie_name];
const sessionToken =
sessions[config.getRawConfig().server.session_cookie_name];
// check for unified login
if (sso && sessionToken) {
@ -172,6 +211,16 @@ export async function verifyResourceSession(
}
}
// At this point we have checked all sessions, but since the access token is valid, we should allow access
// and create a new session.
if (validAccessToken) {
return await createAccessTokenSession(
res,
resource,
validAccessToken
);
}
logger.debug("No more auth to check, resource not allowed");
return notAllowed(res, redirectUrl);
} catch (e) {
@ -209,11 +258,41 @@ function allowed(res: Response) {
return response<VerifyUserResponse>(res, data);
}
async function createAccessTokenSession(
res: Response,
resource: Resource,
tokenItem: ResourceAccessToken
) {
const token = generateSessionToken();
await createResourceSession({
resourceId: resource.resourceId,
token,
accessTokenId: tokenItem.accessTokenId,
sessionLength: tokenItem.sessionLength,
expiresAt: tokenItem.expiresAt,
doNotExtend: tokenItem.expiresAt ? true : false
});
const cookieName = `${config.getRawConfig().server.resource_session_cookie_name}_${resource.resourceId}`;
const cookie = serializeResourceSessionCookie(cookieName, token);
res.appendHeader("Set-Cookie", cookie);
logger.debug("Access token is valid, creating new session")
return response<VerifyUserResponse>(res, {
data: { valid: true },
success: true,
error: false,
message: "Access allowed",
status: HttpCode.OK
});
}
async function isUserAllowedToAccessResource(
user: User,
resource: Resource
): Promise<boolean> {
if (config.getRawConfig().flags?.require_email_verification && !user.emailVerified) {
if (
config.getRawConfig().flags?.require_email_verification &&
!user.emailVerified
) {
return false;
}