redirect to api key page when access gateway in browser

This commit is contained in:
miloschwartz
2026-08-12 11:15:50 -04:00
parent 833b27ab4a
commit 379b53bcca
4 changed files with 36 additions and 7 deletions
+9 -3
View File
@@ -337,10 +337,16 @@ export async function verifyResourceSession(
// Only offer a browser redirect to clients that can actually follow one and log in // Only offer a browser redirect to clients that can actually follow one and log in
// (an interactive browser). Non-browser clients (curl, scripts, bots, etc.) just get // (an interactive browser). Non-browser clients (curl, scripts, bots, etc.) just get
// an unauthorized response from Badger instead of a login redirect URL. // an unauthorized response from Badger instead of a login redirect URL.
// Inference browsers go to the dashboard keys page (not back to the inference host)
// so a valid session cannot create a redirect loop.
const redirectPath = clientIsBrowser const redirectPath = clientIsBrowser
? `/auth/resource/${encodeURIComponent( ? mode === "inference"
resource.resourceGuid ? `/${resource.orgId}/resource/${encodeURIComponent(
)}?redirect=${encodeURIComponent(originalRequestURL)}` resource.resourceGuid
)}/keys`
: `/auth/resource/${encodeURIComponent(
resource.resourceGuid
)}?redirect=${encodeURIComponent(originalRequestURL)}`
: undefined; : undefined;
// Virtual API keys for public inference resources (provider-style auth headers). // Virtual API keys for public inference resources (provider-style auth headers).
@@ -42,6 +42,7 @@ export type GetResourceAuthInfoResponse = {
skipToIdpId: number | null; skipToIdpId: number | null;
orgId: string; orgId: string;
postAuthPath: string | null; postAuthPath: string | null;
mode: string;
}; };
export async function getResourceAuthInfo( export async function getResourceAuthInfo(
@@ -227,7 +228,8 @@ export async function getResourceAuthInfo(
whitelist: effectivePolicy?.emailWhitelistEnabled ?? false, whitelist: effectivePolicy?.emailWhitelistEnabled ?? false,
skipToIdpId: effectivePolicy?.idpId ?? resource.skipToIdpId, skipToIdpId: effectivePolicy?.idpId ?? resource.skipToIdpId,
orgId: resource.orgId, orgId: resource.orgId,
postAuthPath: resource.postAuthPath ?? null postAuthPath: resource.postAuthPath ?? null,
mode: resource.mode
}, },
success: true, success: true,
error: false, error: false,
@@ -41,7 +41,9 @@ export default async function ResourceKeysPage(props: ResourceKeysPageProps) {
const user = await getUser(); const user = await getUser();
if (!user) { if (!user) {
redirect("/"); redirect(
`/auth/login?redirect=/${orgId}/resource/${resourceGuid}/keys`
);
} }
const cookieHeader = await authCookieHeader(); const cookieHeader = await authCookieHeader();
+21 -2
View File
@@ -71,6 +71,9 @@ export default async function ResourceAuthPage(props: {
); );
} }
const isInference = authInfo.mode === "inference";
const keysPath = `/${authInfo.orgId}/resource/${authInfo.resourceGuid}/keys`;
const hasLoginPageDomain = await isOrgSubscribed( const hasLoginPageDomain = await isOrgSubscribed(
authInfo.orgId, authInfo.orgId,
tierMatrix.loginPageDomain tierMatrix.loginPageDomain
@@ -159,10 +162,18 @@ export default async function ResourceAuthPage(props: {
if (user && !user.emailVerified && env.flags.emailVerificationRequired) { if (user && !user.emailVerified && env.flags.emailVerificationRequired) {
redirect( redirect(
`/auth/verify-email?redirect=/auth/resource/${authInfo.resourceGuid}` `/auth/verify-email?redirect=${encodeURIComponent(
isInference
? keysPath
: `/auth/resource/${authInfo.resourceGuid}`
)}`
); );
} }
if (isInference && !user) {
redirect(`/auth/login?redirect=${encodeURIComponent(keysPath)}`);
}
const cookie = await authCookieHeader(); const cookie = await authCookieHeader();
// Check org policy compliance before proceeding // Check org policy compliance before proceeding
@@ -181,7 +192,9 @@ export default async function ResourceAuthPage(props: {
// If user is not compliant with org policies, show policy requirements // If user is not compliant with org policies, show policy requirements
if (orgPolicyCheck && !orgPolicyCheck.allowed && orgPolicyCheck.policies) { if (orgPolicyCheck && !orgPolicyCheck.allowed && orgPolicyCheck.policies) {
const resourceAuthPageUrl = `/auth/resource/${authInfo.resourceGuid}${redirectUrl !== authInfo.url ? `?redirect=${encodeURIComponent(redirectUrl)}` : ""}`; const resourceAuthPageUrl = isInference
? keysPath
: `/auth/resource/${authInfo.resourceGuid}${redirectUrl !== authInfo.url ? `?redirect=${encodeURIComponent(redirectUrl)}` : ""}`;
return ( return (
<div className="w-full max-w-md"> <div className="w-full max-w-md">
<OrgPolicyRequired <OrgPolicyRequired
@@ -193,6 +206,12 @@ export default async function ResourceAuthPage(props: {
); );
} }
// Inference resources never establish a resource session on the inference
// host. Authenticated users retrieve their virtual API key on the dashboard.
if (isInference) {
redirect(keysPath);
}
if (!hasAuth) { if (!hasAuth) {
// no authentication so always go straight to the resource // no authentication so always go straight to the resource
redirect(redirectUrl); redirect(redirectUrl);