This guide will take you through the basic steps of connecting your application to your passport client using Svelte and Immutable SDK. In order to deploy this example, you will need to configure SSL.
Clone the template repository
git clone https://github.com/Arturski/immutable-base-project-svelte.git
cd immutable-base-project-svelte
NOTE: It is a base template made with Vite and SvelteKit and also includes the Immutable SDK for implementing passport functionality and most of the essential web3 polyfills.
Install and test your environment
npm i
npm run dev -- --open
Create a store for the Passport provider object
Create a new file
src/store.ts
.Add the following code and modify the
passportConfig
object with your Passport configuration by replacing placeholders with actual values. We will demo a working deployment in this guide and we won't use the URLs yet.
import { writable } from "svelte/store";
import {config, passport} from "@imtbl/sdk";
const passportConfig = {
clientId: "APP_ID",
redirectUri: "CALLBACK URL",
logoutRedirectUri: "LOGOUT_URL",
scope: "transact openid offline_access email",
audience: "platform_api",
baseConfig: new config.ImmutableConfiguration({
environment: config.Environment.SANDBOX, // Set the appropriate environment value
apiKey: "", // Provide the apiKey if required
}),
};
const passportInstance = new passport.Passport(passportConfig);
export const providerStore = writable<undefined | null>(null);
export const passportStore = writable<passport.Passport>(passportInstance);
Create the Auth helper module (auth.ts):
Create a new file
src/auth.ts
.Define the
login
andhandleLoginCallback
functions using provided code to manage authentication.Connect options:
Immutable X:
connectImx();
Immutable zkEVM:
connectEvm();
Connect silently using existing session token:
connectSilent();
import { passportStore, providerStore } from "./store";
import { get } from "svelte/store";
export async function login(): Promise<void> {
const passportInstance = get(passportStore);
const providerInstance = await passportInstance.connectImx();
providerStore.set(providerInstance as any);
}
export async function handleLoginCallback(): Promise<void> {
const passport = get(passportStore);
await passport.loginCallback();
}
Create pages and routing
Inside the src/routes
directory, create Svelte components for different pages and layouts. the "index" page in this case is +page.svelte and any directory is a route so for the purpose of this tutorial we will modify some content in the index page and also add a /login
route for the callback.
We already have our index page therefore we will simply adjust the existing src/routes/+page.svelte
with the following code to add the login button.
Index Page
First, we will add some functions to the <script> tag. The onMount function will check if there is an existing session stored in the browser at the time the script was loaded. copyJsonToClipboard allows us to store the session JSON object into Clipboard memory if we want to inspect it later. Note that we are also importing the auth.ts
module we created earlier to use the login function.
import { onMount } from 'svelte';
import { login } from '../auth';
let jsonData: string | null = null;
let showStatus: boolean = false;
onMount(() => {
const keyPrefix = 'oidc.user:https://auth.immutable.com';
if (typeof sessionStorage !== 'undefined') {
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
if (key && key.startsWith(keyPrefix)) {
const sessionData = sessionStorage.getItem(key);
if (sessionData) {
try {
jsonData = JSON.parse(sessionData);
}
catch (error) {
console.error('Error parsing session data:', error);
}
}
break;
}
}
}
});
async function copyJsonToClipboard() {
if (jsonData) {
try {
await navigator.clipboard.writeText(JSON.stringify(jsonData, null, 2));
showStatus = true;
}
catch (error) {
console.error('Error copying to clipboard:', error);
}
}
}
Additionally, we will add some logic to the Index page rendering. We create a conditional display:
If a session already exists, don't show the login button (for demo purposes) but instead offer to copy the object to clipboard and show a confirmation message.
Add the following code just below the title.
{#if jsonData}
<button on:click={copyJsonToClipboard} class={showStatus ? 'hidden' : ''}>
Copy session to clipboard
</button>
{#if showStatus}
<p class="status">Logged in. Session data in clipboard. Ctrl+V in any text editor.</p>
{/if}
{:else}
<button on:click={login}>
Sign In with
<img
src="https://assets-global.website-files.com/62535c6262b90afd768b9b26/62536a8f8dc259548c11d1a9_immutable-logo.svg"
class="logo"
alt="IMX logo"
/>
</button>
{/if}
Login page
We also need to create a callback route which will receive all the necessary authentication data from the auth provider.
Create a new directory
src/routes/login
. This will automatically create a/login
routeAdd a new file called
+page.svelte
. This will serve as the index page for/login
Add the following code. We are using our helper module to execute the handling of the LoginCallback
<script lang="ts">
import { onMount } from 'svelte';
import { handleLoginCallback } from '../../auth';
onMount(async () => {
await handleLoginCallback();
});
</script>
Access Your App
Open your web browser and navigate to http://localhost:5173/
to view your SvelteKit app. The result should be similar to the screenshot below.
By following these steps and integrating the provided code samples, you've successfully created an Immutable Passport integrated application.
To see how to deploy this app, see Passport: Deploy your test app.