Saltar al contenido

Scalekit y Astro

Scalekit es una plataforma de autenticación diseñada para aplicaciones B2B e IA. Proporciona inicio de sesión social, SSO empresarial, enlaces mágicos y más, gestionando el flujo completo de OAuth 2.0 / OIDC para que recibas tokens y un perfil de usuario sin construir ninguna interfaz de usuario de inicio de sesión. Un único entorno de Scalekit admite múltiples aplicaciones (por ejemplo, app.yourcompany.com y docs.yourcompany.com), por lo que tus usuarios se autentican una vez y comparten la misma sesión en todas tus propiedades.

  • Una cuenta y un entorno de Scalekit. Si no tienes uno, puedes registrarte de forma gratuita en scalekit.com y crear un nuevo entorno.
  • Un proyecto de Astro con output: 'server' habilitado para renderizado bajo demanda.
  • Scalekit credentials for your environment. You can find these in the Settings > API Credentials section of your Scalekit dashboard.
    • SCALEKIT_ENVIRONMENT_URL: La URL de tu entorno de Scalekit.
    • SCALEKIT_CLIENT_ID: Tu ID de cliente de Scalekit.
    • SCALEKIT_CLIENT_SECRET: Tu secreto de cliente de Scalekit.
    • SCALEKIT_REDIRECT_URI: La URL de devolución de llamada (callback URL) a la que redirigirá Scalekit después del inicio de sesión (por ejemplo, http://localhost:4321/api/auth/callback). Registra esto en tu panel de control de Scalekit en Configuración > Redirecciones.

Para añadir tus credenciales de Scalekit a tu proyecto de Astro, añade lo siguiente a tu archivo .env:

.env
SCALEKIT_ENVIRONMENT_URL=YOUR_SCALEKIT_ENVIRONMENT_URL
SCALEKIT_CLIENT_ID=YOUR_SCALEKIT_CLIENT_ID
SCALEKIT_CLIENT_SECRET=YOUR_SCALEKIT_CLIENT_SECRET
SCALEKIT_REDIRECT_URI=http://localhost:4321/api/auth/callback

Ahora, estas variables de entorno están disponibles en tu proyecto.

Si deseas tener IntelliSense para tus variables de entorno, edita o crea el archivo env.d.ts en tu directorio src/ y añade lo siguiente:

src/env.d.ts
/// <reference types="astro/client" />
interface ImportMetaEnv {
readonly SCALEKIT_ENVIRONMENT_URL: string;
readonly SCALEKIT_CLIENT_ID: string;
readonly SCALEKIT_CLIENT_SECRET: string;
readonly SCALEKIT_REDIRECT_URI: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
declare namespace App {
interface Locals {
user?: {
sub: string;
email?: string;
name?: string;
};
}
}
Lee más sobre variables de entorno y archivos .env en Astro.

Tu proyecto ahora debería incluir estos archivos:

  • Directoriosrc/
    • env.d.ts
  • .env
  • astro.config.mjs
  • package.json

Para conectarte a Scalekit, instala @scalekit-sdk/node en tu proyecto.

Ventana de la terminal
npm install @scalekit-sdk/node

A continuación, crea una carpeta llamada lib en tu directorio src/ y añade un archivo de cliente de Scalekit:

src/lib/scalekit.ts
import { ScalekitClient } from "@scalekit-sdk/node";
export const scalekit = new ScalekitClient(
import.meta.env.SCALEKIT_ENVIRONMENT_URL,
import.meta.env.SCALEKIT_CLIENT_ID,
import.meta.env.SCALEKIT_CLIENT_SECRET,
);
export const REDIRECT_URI =
import.meta.env.SCALEKIT_REDIRECT_URI ?? "http://localhost:4321/api/auth/callback";

Ahora, tu proyecto debería incluir estos archivos:

  • Directoriosrc/
    • Directoriolib/
      • scalekit.ts
    • env.d.ts
  • .env
  • package.json

Scalekit gestiona la autenticación a través de un flujo estándar de redirección de OAuth 2.0 / OIDC. Tu aplicación envía a los usuarios a Scalekit, ellos inician sesión y Scalekit los redirige de vuelta a tu URL de devolución de llamada con un código de autorización que tú intercambias por tokens. Esta guía utiliza el flujo de código de autorización con un secreto de cliente, el cual es apropiado para aplicaciones renderizadas en el lado del servidor.

Para añadir autenticación a tu proyecto, necesitarás crear tres endpoints de servidor:

  • GET /api/auth/login: redirige a los usuarios a Scalekit para iniciar sesión.
  • GET /api/auth/callback: intercambia el código de autorización por tokens y establece las cookies de sesión.
  • GET /api/auth/logout: limpia las cookies de sesión y finaliza la sesión de Scalekit.

Crea estos endpoints en el directorio src/pages/api/auth/ de tu proyecto. Tu proyecto debería incluir ahora estos nuevos archivos:

  • Directoriosrc/
    • Directoriolib/
      • scalekit.ts
    • Directoriopages/
      • Directorioapi/
        • Directorioauth/
          • login.ts
          • callback.ts
          • logout.ts
    • env.d.ts
  • .env
  • astro.config.mjs
  • package.json

login.ts genera una URL de autorización y redirige al usuario a Scalekit para iniciar sesión.

src/pages/api/auth/login.ts
import type { APIRoute } from "astro";
import { scalekit, REDIRECT_URI } from "../../../lib/scalekit";
export const GET: APIRoute = async () => {
const url = scalekit.getAuthorizationUrl(REDIRECT_URI, {
scopes: ["openid", "profile", "email", "offline_access"],
});
return Response.redirect(url);
};

callback.ts recibe el código de autorización de Scalekit, lo intercambia por tokens y los almacena en cookies HttpOnly.

src/pages/api/auth/callback.ts
import type { APIRoute } from "astro";
import { scalekit, REDIRECT_URI } from "../../../lib/scalekit";
export const GET: APIRoute = async ({ request, cookies }) => {
const url = new URL(request.url);
const code = url.searchParams.get("code");
if (!code) {
return Response.redirect(new URL("/", request.url).origin);
}
const { user, idToken, accessToken, refreshToken } =
await scalekit.authenticateWithCode(code, REDIRECT_URI);
const secure = url.protocol === "https:";
const cookieOptions = { httpOnly: true, path: "/", sameSite: "lax" as const, secure };
cookies.set("sk-id-token", idToken, cookieOptions);
cookies.set("sk-access-token", accessToken, cookieOptions);
cookies.set("sk-refresh-token", refreshToken, cookieOptions);
return Response.redirect(new URL("/", request.url).origin);
};

logout.ts limpia las cookies de sesión y redirige al endpoint de cierre de sesión de Scalekit para finalizar la sesión de Scalekit.

src/pages/api/auth/logout.ts
import type { APIRoute } from "astro";
import { scalekit } from "../../../lib/scalekit";
export const GET: APIRoute = async ({ request, cookies }) => {
const idToken = cookies.get("sk-id-token")?.value;
cookies.delete("sk-id-token", { path: "/" });
cookies.delete("sk-access-token", { path: "/" });
cookies.delete("sk-refresh-token", { path: "/" });
const logoutUrl = scalekit.getLogoutUrl({
idTokenHint: idToken,
postLogoutRedirectUri: new URL("/", request.url).origin,
});
return Response.redirect(logoutUrl);
};

Crea un archivo src/middleware.ts para validar el token de acceso en cada solicitud y rellenar Astro.locals.user con el perfil del usuario autenticado. Cuando el token de acceso ha expirado, el middleware lo refresca automáticamente usando el token de actualización.

src/middleware.ts
import { defineMiddleware } from "astro:middleware";
import type { IdTokenClaim } from "@scalekit-sdk/node";
import { scalekit } from "./lib/scalekit";
export const onRequest = defineMiddleware(async (context, next) => {
const accessToken = context.cookies.get("sk-access-token")?.value;
if (accessToken) {
try {
const claims = await scalekit.validateToken<IdTokenClaim>(accessToken);
context.locals.user = {
sub: claims.sub,
email: claims.email,
name: claims.name,
};
} catch {
// Access token invalid or expired — try to refresh
const refreshToken = context.cookies.get("sk-refresh-token")?.value;
if (refreshToken) {
try {
const { accessToken: newToken } =
await scalekit.refreshAccessToken(refreshToken);
const secure = new URL(context.request.url).protocol === "https:";
context.cookies.set("sk-access-token", newToken, {
httpOnly: true,
path: "/",
sameSite: "lax",
secure,
});
const claims = await scalekit.validateToken<IdTokenClaim>(newToken);
context.locals.user = {
sub: claims.sub,
email: claims.email,
name: claims.name,
};
} catch {
// Refresh failed — clear session cookies
context.cookies.delete("sk-id-token", { path: "/" });
context.cookies.delete("sk-access-token", { path: "/" });
context.cookies.delete("sk-refresh-token", { path: "/" });
}
}
}
}
return next();
});

Ahora que tu middleware rellena Astro.locals.user, puedes crear páginas que muestren contenido diferente según el estado de autenticación.

dashboard.astro es una página a la que solo pueden acceder los usuarios autenticados. Lee el usuario de Astro.locals, establecido por el middleware, y redirige a la página de inicio si el usuario no ha iniciado sesión.

src/pages/dashboard.astro
---
import Layout from "../layouts/Layout.astro";
const user = Astro.locals.user;
if (!user) {
return Astro.redirect("/");
}
---
<Layout title="Dashboard">
<h1>Welcome, {user.name ?? user.email}</h1>
<p>You are signed in.</p>
<a href="/api/auth/logout">Sign out</a>
</Layout>

Más guías de servicios de backend

Contribuir Comunidad Patrocinar