fastify / csrf-protection

A fastify csrf plugin.
Other
151 stars 19 forks source link

Property 'sessionPlugin' is missing in type '{ cookieOpts: { signed: true; }; }' but required in type 'FastifyCsrfProtectionOptionsFastifySecureSession' #133

Closed alabbas-ali closed 1 year ago

alabbas-ali commented 1 year ago

Prerequisites

Fastify version

8.2.1

Plugin version

6.3.0

Node.js version

16.13.2

Operating system

Windows

Operating system version (i.e. 20.04, 11.3, 10)

11

Description

app.register(fastifyCsrfProtection, { cookieOpts: { signed: true } }) 

Typescript is throwing the following error:

Argument of type '{ cookieOpts: { signed: true; }; }' is not assignable to parameter of type 'FastifyRegisterOptions<FastifyCsrfProtectionOptions>'.
  Type '{ cookieOpts: { signed: true; }; }' is not assignable to type 'RegisterOptions & FastifyCsrfProtectionOptionsBase & FastifyCsrfProtectionOptionsFastifySecureSession'.
    Property 'sessionPlugin' is missing in type '{ cookieOpts: { signed: true; }; }' but required in type 'FastifyCsrfProtectionOptionsFastifySecureSession'.

Steps to Reproduce

prepare a project with NestJs and Fastify. then use the @fastify/cookie with @fastify/csrf-protection.

in the mean file include:

     app.register(fastifyCookie, {
        secret: configService.get<string>('COOKIE_SECRET')
    })

    app.register(fastifyHelmet)

    app.register(fastifyCsrfProtection, { cookieOpts: { signed: true } })

Expected Behavior

not to see such an error. according to you the documentation adding { cookieOpts: { signed: true } } as second parameter should be sufficient.

FastifyCsrfProtectionOptionsFastifySecureSession is defined in fastifyCsrfProtection . as the following:

interface FastifyCsrfProtectionOptionsFastifySecureSession {
    sessionPlugin: '@fastify/secure-session';
    csrfOpts?: CSRFOptions;
  }

as sessionPlugin has already a default value of '@fastify/secure-session'. shouldn't it be optional in the definition ??

mcollina commented 1 year ago

Thanks for reporting. We do not have the resources to support Nest.js users. Please refer to the Nest Discord channel (support) for such questions.

jmcdo29 commented 1 year ago

This isn't strictly related to NestJS, but to the Typescript types. According to the README it's possible to use the plugin without passing a sessionPlugin option to the register's second parameter. However, the types say that the sessionPlugin property is required and should be '@fastify/session', @fastify/session-secure' or '@fastify/cookie'. Now, when adding sessionPlugin: '@fastify/cookie', there's a Typescript error

src/main.ts:48:5 - error TS2322: Type '"@fastify/cookie"' is not assignable to type '"@fastify/secure-session"'.

48     sessionPlugin: "@fastify/cookie",
       ~~~~~~~~~~~~~

[2:14:16 PM] Found 1 error. Watching for file changes.

I'll put together a a minimal non-NestJS reproduction in a moment. I found this after providing some support to a StackOverflow Question

jmcdo29 commented 1 year ago

@mcollina here's that reproduction I mentioned. No usage of NestJS, just Fastify and Typescript :) https://github.com/jmcdo29/fastify-crf-issue

alabbas-ali commented 1 year ago

for me, a work around the problem was to provide the property sessionPlugin in the call to register the fastifyCsrfprotection, like:

void app.register(fastifyCsrfProtection, {
        sessionPlugin: '@fastify/secure-session',
        cookieOpts: { signed: true }
    })

but here is what I don't get it. in the type def csrf-protection/types/index.d.ts you define the interface like the following:

interface FastifyCsrfProtectionOptionsFastifySession {
    sessionPlugin: '@fastify/session';
    csrfOpts?: CSRFOptions;
  }

  interface FastifyCsrfProtectionOptionsFastifySecureSession {
    sessionPlugin: '@fastify/secure-session';
    csrfOpts?: CSRFOptions;
  }

why you will need a constant value sessionPlugin in the interface definition, shouldn't the value be assigned in the concreate implementation instead?. I would expect the interfaces def to looks something like:

    interface FastifyCsrfProtectionOptions {
          sessionPlugin?: string
    }

interface FastifyCsrfProtectionOptionsFastifySession extends FastifyCsrfProtectionOptions {
    csrfOpts?: CSRFOptions;
  }

  interface FastifyCsrfProtectionOptionsFastifySecureSession extends FastifyCsrfProtectionOptions{
    csrfOpts?: CSRFOptions;
  }
climba03003 commented 1 year ago

Why you will need a constant value sessionPlugin in the interface definition

The default session plugin is @fastify/cookie. So, it is required to explicitly specify the name of session plugin in the other two variant of option.

The major problem is described in here https://github.com/fastify/csrf-protection/issues/135#issuecomment-1534966764 Basically, it required to update the types into

type RequiredCSRFHmac = Omit<CSRFOptions, 'hmacKey' | 'userInfo'> & Required<Pick<CSRFOptions, 'hmacKey'>> & { userInfo: true }
interface FastifyCsrfProtectionOptionsFastifyCookie {
  sessionPlugin?: '@fastify/cookie';
  csrfOpts?: CSRFOptions | RequiredCSRFHmac;
}