simov / grant

OAuth Proxy
MIT License
4.08k stars 257 forks source link

Intended method of accessing session.grant #276

Closed SunburntRock89 closed 2 years ago

SunburntRock89 commented 2 years ago

Migrating a project from Express + Passport in JS to Fastify + Grant in TS. Have hit a snag with transport: "session"

app
  ...
  .register(grant.fastify({
          defaults: {
              origin: config.webServer.url,
              transport: "session",
              prefix: "/login",
          },
          discord: {
              client_id: auth.discord.ID,
              secret: auth.discord.secret,
              scope: "identify",
              callback: "/dashboard",
          },
    }))
    ...

After having reviewed the grant-types repo, I am unable to understand how req.session.grant is typed. In the grant-types/examples/transport-session/fastify.ts file I can see the line const session: GrantSession = req.session.grant

When I try to translate that to my project, it doesn't work. Typescript prevents me from attempting to access .grant because it's not defined on the session object. ts(2339)

What is the best way to go about working with this?

simov commented 2 years ago

I see, maybe something like this one https://github.com/simov/grant-types/blob/master/examples/transport-session/express.ts#L10-L11 could work?

SunburntRock89 commented 2 years ago

Oh, I forgot this was open I ended up copying what fastify did to get the session module to work in the first place

// fastify.d.ts
import FastifySessionPlugin from "@fastify/session";
import type * as Fastify from "fastify";
import type { GrantSession } from "grant";

declare module "fastify" {
    interface FastifyRequest {
        /** Allows to access or modify the session data. */
        session: Fastify.Session;

        /** A session store. */
        sessionStore: Readonly<FastifySessionPlugin.SessionStore>;
    }

    interface Session extends SessionData {
        grant: GrantSession
    }
}
interface SessionData extends ExpressSessionData {
    sessionId: string;

    encryptedSessionId: string;

    /** Updates the `expires` property of the session. */
    touch(): void;

    /**
     * Regenerates the session by generating a new `sessionId`.
     */
    regenerate(callback: (err?: Error) => void): void;
    regenerate(): Promise<void>;

    /** Allows to destroy the session in the store. */
    destroy(callback: (err?: Error) => void): void;
    destroy(): Promise<void>;

    /** Reloads the session data from the store and re-populates the request.session object. */
    reload(callback: (err?: Error) => void): void;
    reload(): Promise<void>;

    /** Save the session back to the store, replacing the contents on the store with the contents in memory. */
    save(callback: (err?: Error) => void): void;
    save(): Promise<void>;

    /** sets values in the session. */
    set(key: string, value: unknown): void;

    /** gets values from the session. */
    get<T>(key: string): T;

    /** checks if session has been modified since it was generated or loaded from the store. */
    isModified(): boolean;
}

interface ExpressSessionData {
    cookie: FastifySessionPlugin.CookieOptions;
}

Felt it easier than having to retype a bunch of things. Session is accessible now (although every time I log in it's a 403 :)) Perhaps this solution could be applied by the library?