Skip to main content
Version: 2.0.0

Access Control

Authentication

Web authentication is handled as part of the framework; we pass authentication results down as a locals object, giving you control over how to use them throughout the lifecycle of a request.

+layout.server.ts
export async function load({ locals }) {
const authResult = locals.authResult;

if (authResult.success) {
log.debug("User is authenticated");

return {
user: authResult.claims,
};
} else {
log.debug("User is not authenticated, but since this is a public route, we allow the user anyway");
}
}

You may simply access the locals.authResult object in your layouts or pages to determine if a user is authenticated. It also contains all claims from the JWT, allowing you to perform any additional checks and guards you want in your pages or layouts.

The AuthResult Object

The AuthResult type can represent two possible outcomes: AuthResultSuccess and AuthResultFail.

auth.ts
type AuthResult = AuthResultSuccess | AuthResultFail;

type AuthResultSuccess = {
success: true;
claims: AuthClaims;
access_token?: string;
};

type AuthResultFail = {
success: false;
};

AuthResultSuccess

AuthResultSuccess indicates a successful authentication and provides:

  • A boolean success field that is always true, representing a successful authentication.
  • The user claims decoded from the access token (as provided by Keycloak).
  • The original access token itself, that can be used to make API requests to other backend services.

AuthResultFail

AuthResultFail indicates a failed authentication and contains a boolean success field that is always set to false, representing a failed authentication

note

This typing is to allow type narrowing to remind developers that claims and access_token are only available when the user is authenticated.

Guarding Routes

Simple Authentication-Based Protection

As the resulting authentication information is made available to your application through the locals object. It can be checked through the layout, pages, or even passed all the way to the browser to allow you to add conditional rendering logic (e.g., displaying user names, showing/hiding content based on login status, etc).

+server.ts
export const GET: RequestHandler = async ({ locals, fetch, url }) => {
// Access the user id from the authentication result.
const user_id: string = locals.authResult.claims.sub;

// Construct headers and passing the access token into the header using the result.
const headers: HeaderInit = {
Authentication: "Bearer" + locals.authResult.access_token,
};

// Call api...
const response = await fetch(url, {
headers,
});
};

Permission-based Protection

You can perform more than just simple successful / unsuccessful authentication guards, for example, you might want to enforce role-based access control directly within your API route handlers (which you can do so by checking the claims, as the role information is available there), or even make an API call to the IAMS-AAS service to check if the user is authorized to access a specific resource.

The following sample is how you might want to guard access to a specific page based on a user's permissions:

+page.server.ts
import type { PageServerLoad } from "./$types";
import { redirect } from "@sveltejs/kit";

const IAMS_AAS_URL = `http://iams-aas.example.com`;

export const load: PageServerLoad = async ({ fetch, locals }) => {
// Guard to redirect user on authentication failure
if (!locals.authResult.success) {
redirect(307, "/example_unauthorized_page");
}

const tenant_id = locals.authResult.claims.tenant_id;
const user_id = locals.authResult.claims.user_id;
const resource_name = "example_resource";
const scope_name = "example_scope";

// IAMS_AAS policy evaluation endpoint to determine if
// this user has access to a specific resource
const url = `${IAMS_AAS_URL}/admin/tenants/\
${tenant_id}/users/\
${user_id}/resources-by-name/\
${resource_name}/scopes-by-name/\
${scope_name}/evaluate`;

const response = await fetch(url, {
headers: {
Authorization: `Bearer example_nonsense_token`,
},
});

const result = await response.json();

// Guard to redirect user on authorization failure (permission denied)
if (result !== "PERMIT") {
redirect(307, "/example_unauthorized_page");
}

return {};
};
note

The same pattern can be applied to non-page (API) routes.

For more details on how to add find grained access control via permission-based guards, refer to the Fine-Grained Access Control documentation.