
Security News
Open Source Maintainers Demand Ability to Block Copilot-Generated Issues and PRs
Open source maintainers are urging GitHub to let them block Copilot from submitting AI-generated issues and pull requests to their repositories.
sveltekit-keyloak-multitenant
Advanced tools
Multi-tenant authentication and authorization for SvelteKit apps using KeyCloak.
Multi-tenant (fully federated) authentication and authorization in SvelteKit apps using KeyCloak. Intended for apps that need fully federated authentication for typically B2B apps serving enterprise customers with varying authentication requirements. Uses a Hybrid Authentication flow and JWT tokens. Provides enables role-based-access-controls using Keycloak role managemewnt for SvelteKit apps to leverage.
Wanted a cost effective solution for multitenant authentication in SvelteKit apps intended to run in a containerized environment.
Most solutions are built for single-tenancy, or quickly expanding on authentication providers and social logins. (B2C applicataions.)
Keycloak is a great open source solution enabling fully federated authentication. But, most examples online using Keycloak and Sveltekit are implemented as single-tenant.
This library enables apps to use multiple keycloak realms mapping customer user email domains to realms for federated authentication services. (B2B apps)
Some added benefits of this library:
npm install -S sveltkit-keycloak-multitenant
Variable | Purpose | Example (Default) |
---|---|---|
KEYCLOAK_URL | URL of your Keycloak server taking OIDC authentication calls. | https://auth.mayapp |
KEYCLOAK_INTERNAL_URL | Intenal URL of your Keycloak server within containerized network. | http://keycloak:8085 |
LOGIN_PATH | Relative path to user email form pre-login. | /auth/login |
LOGOUT_PATH | path where you want to redirect to post logout. (Route must have a server side +page.server.ts/js file) | /auth/logout |
POST_LOGIN_PATH | (Optional) post authentication redirect if initial landing was not a deep link. (default / if not set) | /homepage |
User info and user roles is stored in locals by hooks.server.ts.
// See https://kit.svelte.dev/docs/types#app
/// <reference types="@auth/sveltekit" />
import type { UserInfo } from '$lib/server/keycloakservice';
declare global {
namespace App {
interface Locals {
user: UserInfo | null,
}
}
}
export {};
import type { Handle } from "@sveltejs/kit";
import { KeyCloakHandle } from "$lib/server/keycloakservice";
export const handle: Handle = KeyCloakHandle;
Or, if you have multiple handle functions running in all server-side calls, you can use sequence.
import { sequence } from '@sveltejs/kit/hooks';
import type { Handle } from "@sveltejs/kit";
import { KeyCloakHandle } from "$lib/server/keycloakservice";
export const handle: Handle = sequence(
KeyCloakHandle,
// Your other handle functions here...
);
Define a route that matches the ENV variable LOGIN_PATH that includes the basic email submission form. KeyCloakHandle will map the user to a tenant using email (domain), and redirect the user to the appropriate realm for authenication. Will also pass the email to the authentication for convenience so user does not have to specify that twice.
Form requires:
<script lang="ts"></script>
<div>
<form method="post" action="?/login">
<label for="email">email</label>
<input type="email" name="email" />
<button>Sign In</button>
</form>
</div>
<style>
... your style here ...
<style>
Implement a route for whatever LOGOUT_PATH is going to be set to. When a logout button/link will be clicked, KeyCloakHandle will do a response redirect to that. This route must have +page.svelte and +page.server.ts file in order to force a server-side after logout. It does not matter what you want to put on the logout page beyond having those files present. This is required so that a SSR call will clear the locals, which layout.svelte then hides unauthenticated routes. It will also ensure the refresh cookie is expired on page render in the browser before they do anything else.
Pass through locals variables out as page data in +layout.server.ts. (Note, for pages that hide/show features within the page by role, you can pass the UserInfo object to the page renderer in that pages load method as well.)
import type { LayoutServerLoad } from "./$types"
export const load: LayoutServerLoad = async (event) => {
return {
user: event.locals.user,
}
}
Example +layout.svelte file. (You can do anything with the UserInfo metadata returned in the laste step.) This shows:
<script lang="ts">
import type { PageData } from './$types';
export let data: PageData;
</script>
<nav>
{#if data.user}
<span>Welcome: {data.user.username}</span>
<span>tenant: {data.user.tenant}</span>
<a href="/">Home</a>
<a href="/protectedRoute1">Some Protected Route</a>
<a href="/protectedRoute2">Another Protected Route</a>
{#if data.user.roles && data.user.roles.includes('admin')}
<a href="/admin">Admin</a>
{/if}
<a href="/auth/logout" data-sveltekit-preload-data="off">Logout</a>
{/if}
</nav>
<slot />
<style>
... your style here ...
</style>
Structure your metadata as follows... the key in the first level is the assumed "tenant name". (Might do this different in the future an leverage a service account in the master realm to get all this, for now this is simple enough. Easy enough to update the dependency in a container in Kubernetes or Docker. login route will try to refresh pulling this so the lookupt won't get out-of-sync if the file is updated.)
mustangs:
client_id: 'webapp'
client_secret: 'yourclientsecrethere'
realm: 'mustangs'
email_domain: 'mustangs.com'
camaros:
client_id: 'webapp'
client_secret: 'yourclientsecrethere'
realm: 'camaros'
email_domain: 'camaros.io'
Optional: Extend this with any additional attributes to pass into locals.
mustangs:
client_id: 'webapp'
client_secret: 'yourclientsecrethere'
realm: 'mustangs'
email_domain: 'mustangs.com'
customer_logo: '',
default_locale: 'en-US'
Note: If you want type support for those attributes in +layout.svelte/+page.svelte, you can extend the definition in app.d.ts:
import type { UserInfo } from '$lib/server/keycloakservice';
interface MyAppUserInfo extends UserInfo {
customer_logo:string;
default_locale:string;
}
declare global {
namespace App {
interface Locals {
user: MyAppUserInfo | null,
}
}
}
export {};
FAQs
Multi-tenant authentication and authorization for SvelteKit apps using KeyCloak.
The npm package sveltekit-keyloak-multitenant receives a total of 3 weekly downloads. As such, sveltekit-keyloak-multitenant popularity was classified as not popular.
We found that sveltekit-keyloak-multitenant demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Open source maintainers are urging GitHub to let them block Copilot from submitting AI-generated issues and pull requests to their repositories.
Research
Security News
Malicious Koishi plugin silently exfiltrates messages with hex strings to a hardcoded QQ account, exposing secrets in chatbots across platforms.
Research
Security News
Malicious PyPI checkers validate stolen emails against TikTok and Instagram APIs, enabling targeted account attacks and dark web credential sales.