How can i manually store the Session object after the login process?

Hi to everyone,

I’m currently working with the “@inrupt/solid-client-authn-node” library. I’m developing a sort of middleware server, that after an authentication stores the session of the login in memory.
The way in which i’m executing the login is by using

var session=await client.login( 
          idp:...
          username: .....
          password: ......
          oidcIusser: .....
)

The login actually works fine, but i’dont’ know how to manually store the Session object retrived from the process, in the session memory, in order to fetch the next calls.
Thank you for your help!

I know this is like a year too late, but you’d write a storage adapter; this isn’t particularly easy right now, but they lolk like this: solid-client-authn-js/InMemoryStorage.ts at main · inrupt/solid-client-authn-js · GitHub

They then get injected via the sessionOptions.storage option to the Session constructor, or, via secureStorage and insecureStorage options, if you wish to split them

3 Likes

Can you elaborate more on this? I know you mentioned it’s not easy, and I’m not all that experienced so :frowning:

I am currently working with solid-client-authn-node and have a middleware working in SvelteKit but getSessionFromStorage(sessionId) alone is painfully slow (1.7s on my localhost, and 0.7s on host).

After digging a bit I noticed IStorage and InMemoryStorage and assume reason my auth is slow cause I’m not passing in a storage option?

I’m not sure what could cause this delay. I’m using following code to store session in a json file (still a WIP but it works to reuse sessions). You can try and see if you have the same problem using this:

FileStorage.js

import type { IStorage } from "@inrupt/solid-client-authn-node";
import fs from 'fs/promises'


/**
 * Simple key-value file storage. Not safe to concurrent updates.
 */
export class FileStorage implements IStorage {
    constructor(private path: string, private store: Record<string, string>) { };

    static async atPath(path: string) {
        if (await fileExists(path)) {
            const data = await readJsonFile(path)
            return new FileStorage(path, data)
        }
        return new FileStorage(path, {})
    }

    async get(key: string): Promise<string | undefined> {
        return this.store[key]
    }

    async set(key: string, value: string): Promise<void> {
        this.store[key] = value
        await this.save()
    }

    async delete(key: string): Promise<void> {
        delete this.store[key]
        await this.save()
    }

    private async save(): Promise<void> {
        await writeJsonFile(this.path, this.store)
    }
}

async function readJsonFile(path: string) {
    const content = await fs.readFile(path, { encoding: 'utf-8' })
    return JSON.parse(content)
}

async function writeJsonFile(path: string, data: object) {
    const json = JSON.stringify(data, undefined, 2)
    await fs.writeFile(path, json)
}

async function fileExists(path: string) {
    try {
        await fs.access(path, fs.constants.F_OK);
        return true;
    } catch {
        return false;
    }
}

login.ts

export const login = async ({ oidcIssuer, sessionStorage }: ILoginOptions): Promise<Session> => {
    const sessionStorage = await FileStorage.atPath(sessionStoragePath)
    const [ firstSessionId ] = await getSessionIdFromStorageAll(sessionStorage)
    if (firstSessionId) {
        const session = await getSessionFromStorage(firstSessionId, sessionStorage)
        if (session) {
            return session
        }
    }

    const session = new Session({ storage: sessionStorage })
    // login ...
1 Like