GithubHelp home page GithubHelp logo

fastify / fastify-passport Goto Github PK

View Code? Open in Web Editor NEW
236.0 236.0 42.0 3.37 MB

Use passport strategies for authentication within a fastify application

License: MIT License

JavaScript 2.01% TypeScript 97.99%
authentication fastify fastify-plugin passport

fastify-passport's Introduction

CI Package Manager CI Web SIte js-standard-style CII Best Practices

NPM version NPM downloads Security Responsible Disclosure Discord Contribute with Gitpod Open Collective backers and sponsors


An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users. How can you efficiently handle the resources of your server, knowing that you are serving the highest number of requests as possible, without sacrificing security validations and handy development?

Enter Fastify. Fastify is a web framework highly focused on providing the best developer experience with the least overhead and a powerful plugin architecture. It is inspired by Hapi and Express and as far as we know, it is one of the fastest web frameworks in town.

The main branch refers to the Fastify v4 release. Check out the v3.x branch for v3.

Table of Contents

Quick start

Create a folder and make it your current working directory:

mkdir my-app
cd my-app

Generate a fastify project with npm init:

npm init fastify

Install dependencies:

npm i

To start the app in dev mode:

npm run dev

For production mode:

npm start

Under the hood npm init downloads and runs Fastify Create, which in turn uses the generate functionality of Fastify CLI.

Install

To install Fastify in an existing project as a dependency:

Install with npm:

npm i fastify

Install with yarn:

yarn add fastify

Example

// Require the framework and instantiate it

// ESM
import Fastify from 'fastify'
const fastify = Fastify({
  logger: true
})
// CommonJs
const fastify = require('fastify')({
  logger: true
})

// Declare a route
fastify.get('/', (request, reply) => {
  reply.send({ hello: 'world' })
})

// Run the server!
fastify.listen({ port: 3000 }, (err, address) => {
  if (err) throw err
  // Server is now listening on ${address}
})

with async-await:

// ESM
import Fastify from 'fastify'
const fastify = Fastify({
  logger: true
})
// CommonJs
const fastify = require('fastify')({
  logger: true
})

fastify.get('/', async (request, reply) => {
  reply.type('application/json').code(200)
  return { hello: 'world' }
})

fastify.listen({ port: 3000 }, (err, address) => {
  if (err) throw err
  // Server is now listening on ${address}
})

Do you want to know more? Head to the Getting Started.

Note

.listen binds to the local host, localhost, interface by default (127.0.0.1 or ::1, depending on the operating system configuration). If you are running Fastify in a container (Docker, GCP, etc.), you may need to bind to 0.0.0.0. Be careful when deciding to listen on all interfaces; it comes with inherent security risks. See the documentation for more information.

Core features

  • Highly performant: as far as we know, Fastify is one of the fastest web frameworks in town, depending on the code complexity we can serve up to 76+ thousand requests per second.
  • Extensible: Fastify is fully extensible via its hooks, plugins and decorators.
  • Schema based: even if it is not mandatory we recommend to use JSON Schema to validate your routes and serialize your outputs, internally Fastify compiles the schema in a highly performant function.
  • Logging: logs are extremely important but are costly; we chose the best logger to almost remove this cost, Pino!
  • Developer friendly: the framework is built to be very expressive and help the developer in their daily use, without sacrificing performance and security.

Benchmarks

Machine: EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD.

Method:: autocannon -c 100 -d 40 -p 10 localhost:3000 * 2, taking the second average

Framework Version Router? Requests/sec
Express 4.17.3 14,200
hapi 20.2.1 42,284
Restify 8.6.1 50,363
Koa 2.13.0 54,272
Fastify 4.0.0 77,193
-
http.Server 16.14.2 74,513

Benchmarks taken using https://github.com/fastify/benchmarks. This is a synthetic, "hello world" benchmark that aims to evaluate the framework overhead. The overhead that each framework has on your application depends on your application, you should always benchmark if performance matters to you.

Documentation

中文文档地址

Ecosystem

  • Core - Core plugins maintained by the Fastify team.
  • Community - Community supported plugins.
  • Live Examples - Multirepo with a broad set of real working examples.
  • Discord - Join our discord server and chat with the maintainers.

Support

Please visit Fastify help to view prior support issues and to ask new support questions.

Contributing

Whether reporting bugs, discussing improvements and new ideas or writing code, we welcome contributions from anyone and everyone. Please read the CONTRIBUTING guidelines before submitting pull requests.

Team

Fastify is the result of the work of a great community. Team members are listed in alphabetical order.

Lead Maintainers:

Fastify Core team

Fastify Plugins team

Great Contributors

Great contributors on a specific area in the Fastify ecosystem will be invited to join this group by Lead Maintainers.

Past Collaborators

Hosted by

We are a At-Large Project in the OpenJS Foundation.

Sponsors

Support this project by becoming a SPONSOR! Fastify has an Open Collective page where we accept and manage financial contributions.

Acknowledgements

This project is kindly sponsored by:

Past Sponsors:

This list includes all companies that support one or more of the team members in the maintenance of this project.

License

Licensed under MIT.

For your convenience, here is a list of all the licenses of our production dependencies:

  • MIT
  • ISC
  • BSD-3-Clause
  • BSD-2-Clause

fastify-passport's People

Contributors

airhorns avatar climba03003 avatar delvedor avatar dependabot[bot] avatar fdawgs avatar fox1t avatar github-actions[bot] avatar is2ei avatar jcbain avatar jonaskello avatar jsumners avatar l2jliga avatar louisnk avatar lucianovirmes avatar mcollina avatar mgcrea avatar mmahkamov avatar philipwee avatar rafaelgss avatar reilem avatar salmanm avatar sameer-coder avatar serayaeryn avatar simoneb avatar uzlopak avatar wojcikt avatar zekth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastify-passport's Issues

`state` param is not included in the Typescript interface for AuthenticateOptions

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.x

Plugin version

No response

Node.js version

18.x

Operating system

Linux

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

Ubuntu 22.04

Description

This is a Typescript bug.

When using the Passport Google Oauth2 package to implement a Google auth strategy, we are unable to pass the state property though the passport.authenticate options object.

This works code-wise, but does not compile because the interface definition for AuthenticateOptions does not include state.

Working non-TS example here

This is basically an extension of #376 that only appears when devs have the misfortune of using typescript.

Steps to Reproduce

Example code:

const preValidation = async (
    request: FastifyRequest<{
      Querystring: {
        state?: string
      }
    }>,
    reply: FastifyReply,
  ): Promise<void> => {
   const state: string = request.query?.state || ""

  // return passport.authenticate("google", { state, assignProperty: 'state' })(request, reply)
  return passport.authenticate("google", { state, assignProperty: 'state' }, (() => null))(request, reply)
}
...
fastify.get("/auth/google", { preValidation }, async () => "never returns anywhere")

When swapping the commented out lines we get varying errors that state is not defined on the interface for either the SingleStrategyCallback or AuthenticateOptions.

Example: Object literal may only specify known properties, and 'state' does not exist in type 'AuthenticateOptions'.

Expected Behavior

A Typescript developer can pass a state property through the AuthenticateOptions object without error.

Authenticate callback function does not work

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure it has not already been reported

Fastify version

3.19.2

Plugin version

0.4.3

Node.js version

16.2.0

Operating system

Windows

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

10

Description

Callback in fastifyPassport.authenticate function does not trigger if authorization is incorrect, and has only request, reply parameters in case of success authorization.

Steps to Reproduce

import fastify from "fastify";
import fastifySecureSession from "fastify-secure-session";
import fastifyPassport from "fastify-passport";
import LocalStrategy from "passport-local";

fastify.register(fastifySecureSession, {
 cookieName: "ses",
 key: "464d01eddfc334cfebb5d69612554e1b270a7b1493213d84af986db586692f07",
 cookie: { path: "/" },
});
fastify.register(fastifyPassport.initialize());
fastify.register(fastifyPassport.secureSession());

fastifyPassport.use( "local", new LocalStrategy(
   { usernameField: "email", passwordField: "password" },
   (username, password, done) => { done(null, false) },
 ),
);

fastify.post(
 "/login",
 { preValidation: fastifyPassport.authenticate("local", { authInfo: false, session: false })},
 async (request, reply, err, user, info, status) => { reply.send({ hello: "world" }) },
);

Expected Behavior

The callback function is triggered on any request

using fastify-passport with passport-jwt strategy

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

I am using fastify-passport so that I can use many strategies available in passport.js ecosystem. I started to use JWT authentication using passport-jwt and I have a problem wiring things up. Looking at the fastify-passport documentation and passport-jwt documentation in above link has confused me.

So, I have wired up the fastify server as per your documentation

  const fs = require('fs')
  const path = require('path')
  const jwtStrategy = require('passport-jwt').Strategy // installed passport-jwt from npm
  const extractJwt = require('passport-jwt').ExtractJwt; //this is needed according to passport-jwt documentation

then I setup the options for passport-jwt

  var opts = {
    jwtFromRequest : extractJwt.fromAuthHeaderAsBearerToken(),
    secretOrKey : 'secret',
    issuer : 'accounts.examplesoft.com',
    audience : 'yoursite.net',
 }

then register the plugins as mentioned in fastify-passport documentation

  await server.register(fastifySecureSession, { key: fs.readFileSync('./secret-key') })
  await server.register(fastifyPassport.initialize());
  await server.register(fastifyPassport.secureSession())

Then I setup the jwt strategy like below

[Question - 1] - Is this call back needed (as per passport-jwt documentation?)

  fastifyPassport.use('jwt',new jwtStrategy(opts,function(jwt_payload: any, done: any) {
        console.log("test")
  }))

Finally in my route I have;

[Question - 2] - Is below call back the proper place to validate the jwt and authenticate user against database?

  {
        method: 'POST',
        url: '/users',
        schema: postUserSchema,
        handler: createUser(userRepository),
        preValidation: fastifyPassport.authenticate('jwt', { successRedirect: '/', authInfo: false },  async (request, reply, err, user, info, status) => {
        if (err !== null) {
          console.warn(err)
        } else if (user) {
          console.log(`Hello`)
        }
      }
    )}

There is no error and if I put a break point to the call back in my route, it hits the breakpoint and the [info] object says jwt malformed which is ok because I just send some garbage as bearer data.

My question is out of the two places (mentioned in Question -1 & Question -2) what is the correct place I should use to do the user authentication/validation.

Cannot publish new module

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

Requires a build process that looks for other modules:

> @fastify/[email protected] build
> rimraf ./dist && mkdir dist && tsc --outDir dist && git rev-parse HEAD > BUILD_SHA

src/AuthenticationRoute.ts:1:23 - error TS2688: Cannot find type definition file for 'fastify-secure-session'.

1 /// <reference types="fastify-secure-session" />
                        ~~~~~~~~~~~~~~~~~~~~~~

src/AuthenticationRoute.ts:16:33 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

16   const existing: any = request.session.get('messages')
                                   ~~~~~~~

src/AuthenticationRoute.ts:18:11 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

18   request.session.set('messages', messages)
             ~~~~~~~

src/AuthenticationRoute.ts:156:29 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

156                 if (request.session && request.session.get('returnTo')) {
                                ~~~~~~~

src/AuthenticationRoute.ts:156:48 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

156                 if (request.session && request.session.get('returnTo')) {
                                                   ~~~~~~~

src/AuthenticationRoute.ts:157:33 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

157                   url = request.session.get('returnTo')
                                    ~~~~~~~

src/AuthenticationRoute.ts:158:27 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

158                   request.session.set('returnTo', undefined)
                              ~~~~~~~

src/session-managers/SecureSessionManager.ts:1:23 - error TS2688: Cannot find type definition file for 'fastify-secure-session'.

1 /// <reference types="fastify-secure-session" />
                        ~~~~~~~~~~~~~~~~~~~~~~

src/session-managers/SecureSessionManager.ts:23:13 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

23     request.session.set(this.key, object)
               ~~~~~~~

src/session-managers/SecureSessionManager.ts:27:13 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

27     request.session.set(this.key, undefined)
               ~~~~~~~

src/session-managers/SecureSessionManager.ts:31:20 - error TS2339: Property 'session' does not exist on type 'FastifyRequest<RouteGenericInterface, Server, IncomingMessage, unknown, FastifyLoggerInstance>'.

31     return request.session.get(this.key)
                      ~~~~~~~

src/type-extensions.ts:2:30 - error TS2307: Cannot find module 'fastify-flash/lib/flash' or its corresponding type declarations.

2 import { flashFactory } from 'fastify-flash/lib/flash'
                               ~~~~~~~~~~~~~~~~~~~~~~~~~


Found 12 errors in 3 files.

Errors  Files
     7  src/AuthenticationRoute.ts:1
     4  src/session-managers/SecureSessionManager.ts:1
     1  src/type-extensions.ts:2
npm ERR! code 1
npm ERR! path /private/tmp/fastify-passport
npm ERR! command failed
npm ERR! command sh -c npm run build

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/jsumners/.npm/_logs/2022-04-27T14_04_08_506Z-debug-0.log

fastify-passport on  main took 10s
❯

Request user is null when reading from within Mercurius

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.20.2

Plugin version

0.4.3

Node.js version

14.16.0

Operating system

macOS

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

10.15.7

Description

I've been trying to integrate Mercurius with my Rest API backend. I have it working without auth, and I really would like to be able to read the request.user field from the Mercurius context. I don't understand why the value is always null.

instance.register(passportSetup);
instance.register(
  Mercurius,
  {
    schema,
    graphiql: true,
    async context(request) {
      return {
        user: request.user, // always null
        origin: getRequestOrigin(request)
      };
    }
  }
);
export const passportSetup = fp(async (instance) => {
  instance.register(fastifySecureSession, {
    key: Buffer.from(COOKIE_SECRET, 'hex'),
    cookieName: 'session',
    cookie: {
      maxAge: 24 * 60 * 60 * 1000 * 30,
      // Do not change the lines below, they make cy.auth() work in e2e tests
      secure: process.env.NODE_ENV !== 'development' && !process.env.INSECURE_AUTH,
      signed: process.env.NODE_ENV !== 'development' && !process.env.INSECURE_AUTH,
    },
  });
  instance.register(passport.initialize());
  instance.register(passport.secureSession());

  passport.registerUserSerializer(async (passportUser: { email: string, redirect: string }) => {
    const { email, redirect } = passportUser;
    await instance
      .db('users')
      .insert({
        email,
        confirmed_at: new Date(),
      })
      .onConflict('email')
      .ignore();

    const [user] = await instance
      .db<{ id: string, email: string }>('users')
      .where('email', email)
      .select('id');

    return { userId: user.id, redirect };
  });

  passport.registerUserDeserializer(async ({ userId, redirect }: { userId: string, redirect: string }) => {
    const [user] = await instance.db('users').where('id', userId);
    return { ...user, redirect };
  });

  passport.use(STRATEGY, magicLink);
});

Steps to Reproduce

Create a custom context and try to access the passportUser from within the request or the reply.request objects.

Expected Behavior

It should be possible to access the session user after deserialization by passport.

passport-github verify callback never called?

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

Use Case

  • An app that will make calls to the GitHub API on behalf of user (e.g. git commits, gists, etc.)
  • I want to use the GitHub strategy, both for AutheNtication (who is user?) and AuthoriZation (which repos belonging to user does app have access to?).

Problem

  • AuthN layer works as in a user is redirected to login if they are not logged in.
  • But I cannot figure out how to get the access token or user profile

Example Code

Here is a reduced code sample. In my testing, the console.log(profile) is never called in Fastify. The same setup and code works in Express.

The /protected route will redirect to GitHub, which will redirect to the /auth/github/callback route, but the verify callback is never called :-(

Getting Access Tokens

Per GitHub Docs I can take the code from the callback URL, e.g. http://127.0.0.1:3000/auth/github/callback?code=12fxxxxxx to fetch the access and refresh tokens. But I don't want to if passport can do it for me.

I did rush this this morning. So maybe I am doing it wrong?

const PORT = process.env.port || 3000

const fastify = require('fastify')({ logger: true })
const fastifyPassport = require('fastify-passport')
const fastifySecureSession = require('fastify-secure-session')

const GitHubStrategy = require('passport-github').Strategy
const strategyOpts = {
  clientID: process.env.GITHUB_CLIENT_ID,
  clientSecret: process.env.GITHUB_CLIENT_SECRET,
  callbackURL: 'http://127.0.0.1:3000/auth/github/callback'
}

const notForProductionKey = 'no-encryption-key-for-local-dev-min-32-bytes'
fastify.register(fastifySecureSession, { key: notForProductionKey })
fastify.register(fastifyPassport.initialize())
fastify.register(fastifyPassport.secureSession())

fastifyPassport.use('github', new GitHubStrategy(strategyOpts, function (accessToken, refreshToken, profile, cb) {
  console.log('**** Is this ever called??? *******') // <-- NEVER called in Fastify ⁉️
  console.log(profile) // <-- for testing only
  return cb(null, profile)
}
))


/**
 * Routes
 */

fastify.get('/', function (request, reply) {
  reply.send({
    hello: 'world',
    protected: false
  })
})

fastify.get('/protected', { preValidation: fastifyPassport.authenticate('github', { authInfo: false }) }, async (request, reply, err, user, info, status) => {
  if (err !== null) {
    console.warn(err)
  } else if (user) {
    console.log(`Hello ${user.name}!`)
    reply.send(user)
  }

  reply.send({
    hello: 'protected',
    protected: true
  })
})

fastify.get('/auth/github/callback', (req, reply) => {
  // reply.redirect('/')
  reply.send('called back')
})


/**
 * Run the Server
 */
fastify.listen(PORT, function (err, address) {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
})

Move fastify-secure-session dependency to devDependencies

🚀 Feature Proposal

Currently fastify-passport has fastify-secure-session as a dependency.

However, the package is only ever used to import its types or for testing.

Would be great to move the dep to devDependencies.

Motivation

You can use fastify-passport with another session provider than fastify-secure-session (as long as you keep a compatible session API), in that case, fastify-secure-session won't ever be used. This can lead to issues if you have to target systems where building native modules is not an option (eg. windows devices where you don't fully control the system) since it depends on sodium-native.

Example

On most of my projects, I need a Redis storage + signed cookie so I went with a custom solution fitting my needs:

On another one that must target windows-based devices, I'm using only

However I encountered the libsodium build issue and discovered it was a hard dependency of this project.

Will gladly send a PR if you consider my request.

fastifyPassport.initialize is not a function

🐛 Bug Report

A clear and concise description of what the bug is.

To Reproduce

Steps to reproduce the behavior:

// Paste your code here
const fastify = require('fastify')();
const fastifyPassport= require('fastify-passport')
const fastifySecureSession= require('fastify-secure-session')
// set up secure sessions for fastify-passport to store data in
fastify.register(fastifySecureSession, { key: fs.readFileSync(path.join(__dirname, "secret-key")) });
// initialize fastify-passport and connect it to the secure-session storage. Note: both of these plugins are mandatory.
fastify.register(fastifyPassport.initialize());
fastify.register(fastifyPassport.secureSession());
console.log(fastifyPassport);

Error FastifyPassport.initialize is not a function

image

Expected behavior

A clear and concise description of what you expected to happen.

fastifyPassport.initialize should initialize passport
also on same note when someone console `fastifyPassport`
below appears
{
  Strategy: [Getter],
  default: Authenticator {
    key: 'passport',
    userProperty: 'user',
    strategies: { session: [SessionStrategy] },
    serializers: [],
    deserializers: [],
    infoTransformers: [],
    sessionManager: SecureSessionManager {
      key: 'passport',
      serializeUser: [Function: bound serializeUser] AsyncFunction
    }
  }
}

Your Environment

  • node version: v14.15.1
  • fastify version: >=^3.9.1
  • os: windows-wsl-ubuntu

the user property remains occupied by the type when userProperty is changed

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.5.2

Plugin version

2.2.0

Node.js version

18.12.1

Operating system

Linux

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

20.04

Description

The user property remains occupied by the type PassportUser when userProperty is changed

import { Authenticator } from "@fastify/passport";
const fastifyPassport = new Authenticator({
    userProperty: "authUser",
});
//...
const userGroup = await Group.findOne({
    where: {
          name: req.user?.group,
     },
});

image

image

Steps to Reproduce

import { Authenticator } from "@fastify/passport";
const fastifyPassport = new Authenticator({
    userProperty: "authUser",
});
//...
const userGroup = await Group.findOne({
    where: {
          name: req.user?.group,
     },
});

Expected Behavior

The property user should not have remained a busy type for further use

How to print custom error message instead of default "Unauthorized" or "Bad request"

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

Hi,

I'm trying to setup @fastify/passport with @fastify/cookie and @fastify/secure-session. I'm using the local strategy passport-local

After many hits and trials, I was able to set up everything, now only one issue, how to send a custom error message instead of "Unauthorized".

Below is my code for LocalStrategy

fastifyPassport.use("local", new LocalStrategy({
    usernameField: "email",
    passwordField: "password"
  }, async (email, password, done) => {
    if (!email || !password) {
      return done(null, false, { message: "Missing email or password" });
    }
    await methods.FindRecord("users", { email }).then(user => {
      if (!user) {
        return done(null, false, { message: "User not found", status: 404 });
      }
      bcrypt.compare(password, user.password, (err, isValid) => {
        if (err) {
          return done(err);
        }
        if (!isValid) {
          return done(null, false, { message: "Invalid password", status: 401 });
        }
        return done(null, user);
      });
    });
  }));

fastifyPassport.registerUserSerializer(async (user, request) => {
    return user;
})

fastifyPassport.registerUserDeserializer(async (user, request,) => {
    return user
});

This is code in fastify /login route

fastify.post("/login", { 
    preValidation: fastifyPassport.authenticate("local", {
        failureMessage: 'Invalid email or password',
        successMessage: 'Logged in successfully',
        authInfo: false,
    })
}, async (request, reply) => {
    reply.send({ message: "Logged in successfully from new response" });
})

In response i can only see "Unauthorized" instead of any other message when password/username is wrong, I can see
my custom message Logged in successfully from new response only after credentials are correnct. Any help or guidance on this?

I tried fastify-flash but that was giving me some kind of decorator error.

Socket IO middleware Support

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the feature has not already been requested

🚀 Feature Proposal

Right now fastifyPassport registers as a fastify plugin, but it is incompatible with Socket IO middleware

I don't mind helping to implement this feature

Motivation

I don't want to have to register the passport strategies twice for socket IO and fastify passport

Example

Assuming you are using fastify socket io:
`
server.register(fastifySecureSession, { key: fs.readFileSync(path.join(__dirname, 'secret-key')) })
// initialize fastify-passport and connect it to the secure-session storage. Note: both of these plugins are mandatory.
server.register(fastifyPassport.initialize())
server.register(fastifyPassport.secureSession())

server.io.use(fastifyPassport.io.initialize())
server.io.use(fastifyPassport.io.secureSession())
`

Handler does not seem to be called

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure it has not already been reported

Fastify version

3.19.1

Plugin version

0.4.2

Node.js version

16.5.0

Operating system

Linux

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

20.04

Description

At my company, we decide to move from expressjs to Fastify.

With express we use Passport for auth our users, but now with Fastify is little bit more compliced...
It why I try this plugin, but event with this plugin I can't have a successfull login.

I try to login with Google oauth2, but I never get the user on the "auth google callback" (and no passport callback fired too).

Steps to Reproduce

function getInGoogleC (req, res, err, user, status) {
  console.log('FastifyPassport Callback of GoogleStrategy Passport fired...');
  console.log('err:', err);
  console.log('user:', user);
  console.log('status:', status);

  console.log('getInGoogle finish...');
}

function getCallbackGoogleC (req, res) {
  res.redirect(`${APP_URL + AUTHENTICATION_BACK_PATH}?u=${encodeURIComponent(JSON.stringify(req.user))}`)
}

const defRoutes = [
    {
      method: 'GET',
      url: `/get-in/google`,
      preValidation: passport.authenticate('google', { session: true, scope: ['profile', 'email'] }),
      handler: getInGoogleC              // Never fired -_-
    },
    {
      method: 'GET',
      url: `/auth/google/callback`,
      handler: getCallbackGoogleC  // no data into user decorator -_-
    }
]

Expected Behavior

With expressjs and Passport we get user infos

Calling Strategy.fail with 2 arguments is misinterpreted by the compiler

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.2.1

Plugin version

2.1.0

Node.js version

16.4.2

Operating system

Windows

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

10

Description

Here's the declaration of the fail() method in the base Strategy class: https://github.com/fastify/fastify-passport/blob/main/src/strategies/base.ts#L55

fail!: ((challenge?: any, status?: number) => void) | ((status?: number) => void)

When calling with 1 number argument, there's no problem:

this.fail(403);

But TypeScript is failing to find the variant with 2 arguments:

return this.fail({
  message: request.query['error_description'],
}, 400);

getting an error:

TS2554: Expected 0-1 arguments, but got 2

Steps to Reproduce

  1. Create a custom strategy subclassed from the Strategy class of @fastify/passport
  2. Call this.fail(null, 401)

Expected Behavior

The code should compile when calling Strategy.fail() with 2 arguments.

Support @fastify/session out of the box

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the feature has not already been requested

🚀 Feature Proposal

As https://github.com/fastify/session became part of the org, we should list it here as one of the default session manager. I think it would just work, but it still needs tests and docs.

Motivation

No response

Example

No response

Invalid Typings for PassportUser in Typescript

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.20.0

Plugin version

2.3.0

Node.js version

16.17.0

Operating system

macOS

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

Ventura 13.4

Description

In my log in route, I wish to send back to the user their id (therefore I must access the id). I used request.user to attempt achieve this (of type PassportUser) but found that PassportUser has no properties (see below)
Screenshot 2023-07-19 at 23 42 36

Hence, when trying to access id (a property of User – what I'm expecting type PassportUser to be & is [if you console log it]) I run into this problem:

Screenshot 2023-07-19 at 23 38 30

Steps to Reproduce

Relevant server.ts code:

// Sessions
app.register(fastifySecureSession, {
  key: fs.readFileSync(path.join(__dirname, "../example-key")),
});

app.register(fastifyPassport.initialize());
app.register(fastifyPassport.secureSession());

// On login
fastifyPassport.use(
  new passportLocal.Strategy(
    {
      usernameField: "email",
      passwordField: "password",
    },
    // login method
    async (email, password, cb) => {
      const user = await app.prisma.user.findFirst({
        where: {
          email,
        },
      });

      if (!user) {
        return cb("User with this email doesn't exist");
      }

      const isCorrectPassword = await bcrypt.compare(password, user.password);

      if (!isCorrectPassword) {
        return cb("Incorrect password");
      }

      // null and false for all other cases
      return cb(null, user);
    }
  )
);

// register a serializer that stores the user object's id in the session ...
fastifyPassport.registerUserSerializer<User, string>(
  async (user, request) => user.id
);

// ... and then a deserializer that will fetch that user from the database when a request with an id in the session arrives

// TODO: what is unknown??
fastifyPassport.registerUserDeserializer<string, unknown>(
  async (id, request) => {
    return await app.prisma.user.findFirst({
      where: {
        id,
      },
    });
  }
);

Relevant route code:

fastify.post(
    "/",
    {
      preHandler: passport.authenticate("local"),
    },
    async (request, reply) => {
      const user = request.user;

      if (!user) {
        throw new Error(); // Something went wrong...
      }

      stdReply(reply, {
        clientMessage: `Successfully logged in as ${user.id}`,
      });
    }
  );

Expected Behavior

I should be able to access the same user object as registered here (of type User).

Screenshot 2023-07-19 at 23 40 39

Let's talk about, goals, features and porting quirks

Hi, I am in the process of porting passport to Fastify. The goal of this project is to have 100% compatibility with all the passport strategies already developed.
I just finished porting the code 1:1 to TypeScript and now I am going to rewrite some parts that are not suitable anymore:

  1. original project doesn't use strict mode
  2. almost all types are wrong
  3. some parts could be optimized and speed up

There are some part of the code that need to be approached carefully and I'll use this thread to talk about them. First of all, there are two folders that need our attention, framework and middleware. These folders contains all the implementation that is bound to connect middleware, used by passport. As we can see on this.framework(connect()), in the authenticator module, this, so called "framework", is pluggable using framework() method. All the Fastify's specific implementation must be done inside a "compatible framework".
Unfortunately there are some issues.

  1. Let's start with req.flash. Passport uses flash messages to notify success or failure during authentication process (line 173 and 281). Are we gonna support this?
  2. Passport's connect framework monkey patch http.IncomingMessage just to add some helpers methods, as logIn and authenticate. I really do not want to do that and, instead, I want to add it to Fastify's request object. However we need to be sure that all strategies will still work.
  3. Speaking of that, SessionStrategy, the only included with passport, support pausing IncomingMessage, if options.pauseStream is passed. This works because req is a express.Request, that is extended from IncomingMessage. This is, of course, a problem for Fastify's request object.

Local Strategy bad request

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3

Plugin version

0.4.3

Node.js version

14

Operating system

Linux

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

20

Description

Hi, I trying to use LocalStrategy.
I succeeded to do login but the other request return a Bad Request.

Steps to Reproduce

module.exports = fp(async function (fastify, opts) {
    fastify.register(fastifySecureSession, {
        key: fs.readFileSync(path.join(__dirname, '../secret-key')),
    })
    fastify.register(fastifyPassport.initialize())
    fastify.register(fastifyPassport.secureSession())

    fastifyPassport.use("local", new LocalStrategy(
        function (username, password, done) {
            User.findOne({email: username}, function (err, user) {
                if (err) {
                    return done(err);
                }
                if (!user) {
                    return done(null, false);
                }
                if (!user.comparePassword(password)) {
                    return done(null, false);
                }
                return done(null, user);
            });
        }
    ));
    // register a serializer that stores the user object's id in the session ...
    fastifyPassport.registerUserSerializer(async (user, request) => user.id);

    // ... and then a deserializer that will fetch that user from the database when a request with an id in the session arrives
    fastifyPassport.registerUserDeserializer(async (id, request,) =>{
        return await User.findById(id);
    });

})

and this is my route

  // always return Bad Request
    fastify.get('/auth', {preValidation:  fastifyPassport.authenticate('local',{ successFlash: 'Welcome!' })},
        async (req) => {
            return {
                "title": 'hello world!',
                user: req.user

            }
        }
    )
    
    //work good!
    fastify.post(
        '/login',
        {
            preValidation: fastifyPassport.authenticate('local', {
                successRedirect: "/",
                failureRedirect: "/login",
                failureFlash: true,
            })
        },
        () => {
            return {hello: "world"}
        }
    )

Expected Behavior

Expected to get the user and not Bad Request

Duplicate 'passport' decorator error when instantiating multiple Authenticator instances

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.17.0

Plugin version

2.3.0

Node.js version

16.2

Operating system

macOS

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

14.2.1

Description

Hello,

I followed instructions as per documentation but the Fastify server does not start up with the error quoted below:

{
    "level": 50,
    "time": 1706381991730,
    "pid": 19819,
    "hostname": "<redacted>",
    "err":
    {
        "type": "FastifyError",
        "message": "The decorator 'passport' has already been added!",
        "stack": "FastifyError: The decorator 'passport' has already been added!\n    at decorateConstructor (/Users/<redacted>/Work/<redacted>/node_modules/fastify/lib/decorate.js:41:11)\n    at Object.decorateRequest (/Users/<redacted>/Work/<redacted>/node_modules/fastify/lib/decorate.js:123:3)\n    at /Users/<redacted>/Work/<redacted>/node_modules/@fastify/passport/dist/CreateInitializePlugin.js:10:17\n    at Plugin.exec (/Users/<redacted>/Work/<redacted>/node_modules/avvio/plugin.js:130:19)\n    at Boot.loadPlugin (/Users/<redacted>/Work/<redacted>/node_modules/avvio/plugin.js:272:10)\n    at processTicksAndRejections (node:internal/process/task_queues:83:21)",
        "name": "FastifyError",
        "code": "FST_ERR_DEC_ALREADY_PRESENT",
        "statusCode": 500
    },
    "msg": "The decorator 'passport' has already been added!"
}

Best regards,

David

Steps to Reproduce

'use strict'

const fastify = require('fastify')({
    disableRequestLogging: true,
    logger: true,
    level: 'info'
});

const {Authenticator} = require('@fastify/passport');

const fastifyCookie = require('@fastify/cookie');
const fastifySession = require('@fastify/session');
fastify.register(fastifyCookie);
fastify.register(fastifySession, {
    secret: '6b8de8c5-2440-4903-8157-595adeaed92e',
    cookie: { secure: false },
    expires: 1800000
})

const _username1='user1';
const _password1 = 'password1';

const _username2 = 'user2';
const _password2 = 'password2';

const LocalStrategy = require('passport-local');

let passport1 = new Authenticator({ key: 'userAuth1', userProperty: 'user1' })
passport1.use('local-1', new LocalStrategy({},
    function (username, password, done) {
        if (username === _username1 && password == _password1) {
            return done(null, {username});
        }
        return done('local-1: You got this wrong');
    }));
fastify.register(passport1.initialize());
fastify.register(passport1.secureSession());


let passport2 = new Authenticator({ key: 'userAuth2', userProperty: 'user2' })
passport2.use('local-2', new LocalStrategy({},
    function (username, password, done) {
        if (username === _username2 && password == _password2) {
            return done(null, {username});
        }
        return done('local-2: You got this wrong');
    }));
fastify.register(passport2.initialize());
fastify.register(passport2.secureSession());

passport1.registerUserSerializer(async (user, request) => user);
passport1.registerUserDeserializer(async (serUser, request) => {
    return {...serUser}
});

passport2.registerUserSerializer(async (user, request) => user);
passport2.registerUserDeserializer(async (serUser, request) => {
    return {...serUser}
});

fastify.post("/login-password-1", {
    preValidation: passport1.authenticate('local-1', {
        failureMessage: true,
        failWithError: true,
    })
}, async function (request, reply) {
    console.log(request.user)
    reply.code(200).send({...request.user1})
})

fastify.post("/login-password-2", {
    preValidation: passport2.authenticate('local-2', {
        failureMessage: true,
        failWithError: true,
    })
}, async function (request, reply) {
    console.log(request.user)
    reply.code(200).send({...request.user2})
})

fastify.post("/auth-test", {
}, async function (request, reply) {
    console.log(request.user)
    reply.code(200).send({...request.user})
})

fastify.listen({ port: 3000, host: '0.0.0.0' }, function (err, address) {
    if (err) {
        fastify.log.error(err)
        process.exit(1)
    }
})

Expected Behavior

The fastify server should start up and I should have 2 authentication stacks.

Use another session manager other than fastify-secure-session

🚀 Feature Proposal

Using another session manager other than the only supported fastify-secure-session.

Motivation

Motivation is that, one can easily switch to a stateful session manager such as fastify-session and store the sessions on the supported session stores in fastify-session.

Example

Example will be when people want to use fastify-passport but still want the power to manually control sessions and store them.

I see that there is already a pull request going on #93 which will implement same feature, but any update on it?

Fastify Custom Strategy, redirect method not working - TypeError: res.setHeader is not a function

Prerequisites

  • I have searched existing issues to ensure the bug has not already been reported

  • I have written a descriptive issue title

Fastify version

4.6.3

Plugin version

No response

Node.js version

16

Operating system

Windows

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

11.3

Description

Hi,
I am trying to develop a custom strategy for Paypal. I am using [email protected].

I am using Fastify with Nest.js.

Here is my Strategy:

import { Strategy as FastifyStrategy } from '@fastify/passport';
import * as paypal from 'paypal-node-sdk';

class Strategy extends FastifyStrategy {
  private options;
  public name: string;
  private callback;
  constructor(options, callback) {
    super('paypal');
    this.options = options;
    this.name = 'paypal';
    this.callback = callback;
    paypal.configure({});
  }
  async authenticate(
    req,
    options?: any,
  ) {
    if (req.query && req.query['error']) {
      throw 'Query Error';
    }
    if (req.query && req.query['code']) {
      let code = req.query['code'];
      try {
        return this.getUserProfile(code);
      } catch (e) {
        return this.error(e);
      }
    }
    const location = await paypal.openIdConnect.authorizeUrl({
      scope: this.options.scope,
    });

    return this.redirect(location, 302);
   // the line above causes a problem 
  }

  verified(err, user, info) {
    if (err) {
      return this.error(err);
    }
    if (!user) {
      return this.fail(info);
    }
    this.success(user, info);
  }

  getUserProfile = async (code) => {
    // function to get the user data from Paypal;
  };
}

export default Strategy;

the redirect method seems to have a bug or something, it causes this error:

res.setHeader('Location', url);
            ^
TypeError: res.setHeader is not a function

Steps to Reproduce

Just try to implement a strategy and call the redirect method.

Expected Behavior

I expect the redirect method to work properly and redirect to the intended destination.

Incomplete docs for "authenticate" function

🐛 Bug Report

(Sorry if this is not the correct issue type)

The authenticate function has an optional callback parameter, but the signature is not provided. Maybe I am not looking carefully, but the docs say "The callback has the following signature", but I can't seem to see the signature anywhere.

I had to look in the source code to find out what was going wrong, and only then realised that the user is given as 4th parameter in the callback and is not available in the request object.

Just adding something like this to the docs would've made my life a lot easier 30 minutes ago 😅

Callback: (request, reply, err, user?, info?, status | statuses?) => Promise<void>

Let me know if there is any way I can help.

Flash plugin requires a valid session error

I'm trying to use this plugin with NestJS. My session works fine.

// main.ts
await app.register(fastifySecureSession, {...})

// auth.controller.ts
login(@Req() req): any {
  console.log(!!req.session) // print true
  return true
}

But after adding passport I get error "Flash plugin requires a valid session." https://github.com/fastify/fastify-flash/blob/master/src/index.ts#L12

await app.register(fastifySecureSession, {...})
await app.register(fastifyPassport.initialize())
await app.register(fastifyPassport.secureSession())

How I can fix it?

The second question: is it possible to make fastify-flash optional? In my project I don't need any flash.

fastifyPassport.initialize is not a function

As soon as fastifyPassport starts i get "fastifyPassport.initialize is not a function", if a debug fastifyPassport i have only default and strategy present

Steps to reproduce

  app.register(fastifySecureSession, { key: "akey" });
  
  app.register(fastifyPassport.initialize());
  app.register(fastifyPassport.secureSession());
  • node version: 15.0.1
  • fastify version: >=3.8.0
  • os: Linux

Error: passport.initialize() plugin not in use

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure it has not already been reported

Fastify version

3.19.1

Plugin version

0.4.2

Node.js version

16.4.2

Operating system

macOS

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

11.4

Description

The error location:
node_modules/fastify-passport/dist/AuthenticationRoute.js:18:23

I made the setup for fastifyPassport like this:

  await app.register(fastifyHelmet);

  await app.register(fastifySecureSession, {
    key: fs.readFileSync(path.join(__dirname, '../secret.key')),
  });
  await app.register(fastifyPassport.initialize());
  await app.register(fastifyPassport.secureSession());

  await app.listen(3000);

And i tried the passport-google-oauth20 strategy:

import { Strategy as GoogleOAuth2Strategy } from 'passport-google-oauth20';

.
.
.

fastifyPassport.use(
    'google',
    new GoogleOAuth2Strategy(googleConfig.strategy, this.validate.bind(this)),
  );

But when i use the middleware

    fastifyPassport.authenticate('google', {
          scope: googleConfig.scope,
        })

It fails.

Steps to Reproduce

Setup the passport, add the passport-google-oauth20 and try the redirect middleware to google's login page.

Expected Behavior

To redirect to the google's login page.

Using fastify-secure-session with openid-client strategy

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

I'm trying to use fastify-secure-session with openid-client passport strategy.

It redirects correctly to the OIDC provider and redirects back correctly but then I get this error:

did not find expected authorization request details in session, req.session[\"oidc:xxxx\"] is undefined

I've looked into the source code for possible causes of this and I found something that I think may be the cause. Looking at how fastify-secure-session requires you to set session values using the request.session.set(key, value) method like this (example from the readme):

  request.session.set('data', request.body)
})

And then looking into the source code for openid-client which expects to be able to do req.session[key] = value as for example in this line:

 req.session[sessionKey] = pick(params, 'nonce', 'state', 'max_age', 'response_type');

I think this cannot really be compatible? On the one side req.session.set(key, value) is required, and on the other side req.session[key] = value is used. Or is there some adaptation going on inside of fastify-passport to make this compatible?

passport types not exists when using ESM + Typescript

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.15.0

Plugin version

2.2.0

Node.js version

18

Operating system

macOS

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

13.2.1

Description

When using ESM with TypeScript the types are missing.

Example with this code:

import fastifyPassport from '@fastify/passport';

fastifyPassport.initialize()
fastifyPassport.secureSession()

fastifyPassport.use(undefined as any, undefined as any);

I get:

$ tsc --notEmit
src/index.ts:3:17 - error TS2339: Property 'initialize' does not exist on type 'typeof import("<repo-path>/node_modules/@fastify/passport/dist/index")'.

3 fastifyPassport.initialize()
                  ~~~~~~~~~~

src/index.ts:4:17 - error TS2339: Property 'secureSession' does not exist on type 'typeof import("<repo-path>/node_modules/@fastify/passport/dist/index")'.

4 fastifyPassport.secureSession()
                  ~~~~~~~~~~~~~

src/index.ts:6:17 - error TS2339: Property 'use' does not exist on type 'typeof import("<repo-path>/node_modules/@fastify/passport/dist/index")'.

6 fastifyPassport.use(undefined as any, undefined as any);
                  ~~~


Found 3 errors in the same file, starting at: src/index.ts:3

Steps to Reproduce

Repro

or:

  1. run:
npm init -y

npm i typescript fastify @fastify/passport @types/node

./node_modules/.bin/tsc --init
  1. add this to src/index.ts file:
import fastifyPassport from '@fastify/passport';

fastifyPassport.initialize()
fastifyPassport.secureSession()

fastifyPassport.use(undefined as any, undefined as any);
  1. Add "type": "module" in package.json
  2. in tsconfig.json replace "module": "commonjs" with "module": "Node16"
  3. run tsc

Expected Behavior

should compile without errors

`state` for passport causes `fastify-passport` to fail

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.22.1

Plugin version

0.4.3

Node.js version

16.x

Operating system

macOS

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

macOS Big Sure 11.3.1

Description

When I am trying to pass some encoded state to the strategy the callback URLs shows the user as unauthenticated, it's also unclear how I could pass the encoded state from the redirect endpoint dynamically.

Steps to Reproduce

fastifyPassport.use(
    "github",
    new Github.Strategy(
      {
        clientID: "xxx",
        clientSecret: "xxx",
        callbackURL: "http://lvh.me:3000/callback",
        scope: ["user:email", "user,user:email"],
        userProfileURL: "https://api.github.com/user",
        state: Buffer.from(JSON.stringify({ returnTo: "/mypage" })).toString(
          "base64"
        ),
        passReqToCallback: true,
      },
      function (req, accessToken, refreshToken, profile, done) {
        done(null, { ...profile, accessToken, query });
      }
    )
  );

server.get(
    "/github",
    {
      preValidation: fastifyPassport.authenticate("github", {
        successRedirect: "/callback",
        authInfo: false,
        assignProperty: "user",
      }),
    },
    () => {}
  );
  
  server.get(
  "/callback",
  {
    preValidation: fastifyPassport.authenticate("github", {
      authInfo: false,
      session: false,
    }),
  },
  async (request, reply, err, user = {}, info = {}, status = {}) => {
    reply.send({ user: request.user || {} });
  }
);

Expected Behavior

Step through the prevalidation hook and return the encoded state to the endpoint.

passport-auth0 provider callback route not triggered

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure it has not already been reported

Fastify version

^3.18.1

Plugin version

No response

Node.js version

16.3.0

Operating system

Linux

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

Ubuntu 20.04

Description

Using passport-auth0 things seem to work fine until it comes to the callback route, the callback route is not triggered, in the browser when checking the console, errors below show:

message: "Timeout after calling success log."
description: "Should have closed the web view."

Steps to Reproduce

For this project I set up an auth0 regular web application, then I followed the passport-auth0 and fastify-passport docs to set up the provider, when I go to the auth0 route, I can sign in and in the console I see a success message with an authResult object, however after a while a white page is shown with console errors as shown in this issue description

fastifyPassport.use(
  new Auth0Strategy(
    {
      domain: process.env.AUTH0_DOMAIN,
      clientID: process.env.AUTH0_CLIENT_ID,
      clientSecret: process.env.AUTH0_CLIENT_SECRET,
      callbackURL: `${process.env.SERVER_URL}/auth/auth0/callback`,
    },
    (_accessToken, _refreshToken, _extraParams, profile, done) => {
      return done(undefined, profile)
    }
  )
)

fastify.get(
  "/auth0",
  {
    preValidation: fastifyPassport.authenticate("auth0", {
      scope: "openid email profile",
    }),
  },
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async () => {}
)

fastify.get(
  "/auth0/callback",
  {
    preValidation: fastifyPassport.authenticate("auth0"),
  },
  async (_request, reply) => {
    return reply.send(JSON.stringify(_request.user, undefined, 2))
  }
)

Expected Behavior

I would expect to be redirected to the callback route

[TypeScript] Unable to override type of request.user

🐛 Bug Report

Not sure if this is an actual bug or a typescript misconfiguration on my side but I haven't found a way to properly override the type of the request.user, and it is not explained in the docs:

To Reproduce

Steps to reproduce the behavior:

import { User } from 'src/typings';

declare module 'fastify' {
  interface FastifyRequest {
    user: User;
  }
}

Triggers an error:

Subsequent property declarations must have the same type.  Property 'user' must be of type 'unknown', but here has type 'User'.ts(2717)

Expected behavior

Working override

Your Environment

  • node version: 14
  • fastify-passport version: ^0.1.0
  • os: Mac
  • TypeScript: 4.1.2

Consider releasing to NPM or adding precompiled dist or removing package.json "files" property

First off: Great work! Been waiting for something like this and can't wait for the first release.

🚀 Feature Proposal

I am currently testing this package locally with NestJS and it is working great so far. However, it is kind of cumbersome to add this package as a dependency. It is currently not released to NPM and the "files" property in the package.json would require a precompiled "dist" directory to install this package directly via npm as a github dependency (it currently is just installing an empty directory with the readme and package.json as there is no "dist" directory).

We could handle this in one of three ways:

  • Release to NPM
  • Add precompiled dist to the repository
  • Remove "files" property from package.json (which would require the consumer to compile it first)

Motivation

To be able to test this dependency more comfortably by just installing it as a dependency.

Failed to serialize user into session

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.28.0

Plugin version

0.5.0

Node.js version

17.8.0

Operating system

Windows

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

21H2

Description

when i use registerUserSerializer and registerUserDeserializer i get this error
image

Steps to Reproduce

code:
code

Expected Behavior

I need help please

`Forbidden` error after getting authorization code from okta using `passport-okta-oauth` library as a strategy

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

^3.25.2

Plugin version

No response

Node.js version

16.13.1

Operating system

macOS

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

11.6.1

Description

I am using OKTA as a authenticator in my project.In fastify-passport, I used the passport-okta-oauth library as an strategy. After user succesfully logins with okta.The okta provides authorization code to my callback URL.After receiving code,fastify-passport have to send the post request to the OKTA with code and client_secret as parameter. But in my case this post request is not hitting instead of this its showing forbidden error.

Screenshot 2021-12-24 at 4 10 27 PM

Steps to Reproduce

const fastify = require("fastify")({ logger: true });
const fastifyPassport = require("fastify-passport");
const oktaStrategy = require("passport-okta-oauth").Strategy;
const fastifySecureSession = require("fastify-secure-session");
const fs = require("fs");
const path = require("path");

fastify.register(fastifySecureSession, {
  key: fs.readFileSync(path.join(__dirname, "not-so-secret-key.txt")),
});
fastify.register(fastifyPassport.initialize());
fastify.register(fastifyPassport.secureSession());

fastifyPassport.use(
  "okta",
  new oktaStrategy(
    {
      audience: "YOUR_AUDIENCE_URL",
      clientID: "CLIENT_ID",
      clientSecret: "CLIENT_SECRET",
      scope: ["openid", "email", "profile"],
      response_type: "code",
      callbackURL: "http://localhost:3000/auth/okta/callback",
    },
    function (accessToken, refreshToken, profile, done) {
      console.log("I am in OKTA");
      done(undefined, profile);
      return profile;
    }
  )
);

fastify.get("/", (req, res) => res.send("hii"));
fastify.get("/success", (req, res) => res.send("Success OKTA"));
fastify.get("/failure", (req, res) => res.send("Okta Oauth failure"));

fastify.get(
  "/okta",
  {
    preValidation: fastifyPassport.authenticate("okta", {
      failureRedirect: "/failure",
      session: "false",
    }),
  },
  (req, res) => {}
);
fastify.get(
  "/auth/okta/callback",
  { preValidation: fastifyPassport.authenticate("okta") },
  (req, res) => {
    res.redirect("/success");
  }
);

fastify.listen(3000);

Expected Behavior

After receiving the code from okta, the fastify-passport have to hit the post request and user details will receive in callback function

Release v0.2.0

@mcollina a few key fixes have landed on main that I'd like to release! I thought I might have had publish permissions to the fastify-passport npm package but I don't seem to. Would you mind adding me or releasing v0.2.0 (which has been tagged and pushed)? Thanks!

Use session or not as an option

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the feature has not already been requested

🚀 Feature Proposal

  1. I am writing a hasura side project, in this application scenario, the auth server only provides the remote schema and the necessary redirect url, the user does not have the opportunity to save or use the session, all the authentication will be done through jwt
  2. passport itself supports "disable session"

Based on the above two points, I would like to make it a choice whether to use session or not
but,for now, If I don't register ‘fastify-secure-session’

2022-01-03T06:19:44.289Z *9884 @ElvisMini.local - error: #req-1 Flash plugin requires a valid session.
                         ×Error 500: Flash plugin requires a valid session.
    at Object.<anonymous> (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/fastify-flash/lib/index.js:13:18)
    at hookIterator (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/fastify/lib/hooks.js:237:10)
    at next (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/fastify/lib/hooks.js:164:16)
    at contentSecurityPolicyMiddleware (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/helmet/dist/middlewares/content-security-policy/index.js:124:4)
    at Object.<anonymous> (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/fastify-helmet/index.js:45:7)
    at hookIterator (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/fastify/lib/hooks.js:237:10)
    at next (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/fastify/lib/hooks.js:164:16)
    at internalNext (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/helmet/dist/index.js:142:6)
    at xXssProtectionMiddleware (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/helmet/dist/middlewares/x-xss-protection/index.js:6:3)
    at internalNext (/Volumes/Root/Users/Elvis/WIP/SeaLight/server/node_modules/.pnpm/[email protected]/node_modules/helmet/dist/index.js:145:6)
                         & {"req":{"method":"GET","url":"/","hostname":"0.0.0.0:3001","remoteAddress":"127.0.0.1","remotePort":55152},"res":{"statusCode":500}}
2022-01-03T06:19:44.296Z *9884 @ElvisMini.local -  info: #req-1 request completed
                         & {"res":{"statusCode":500},"responseTime":8.393865000456572}
2022-01-03T06:19:45.311Z *9884 @ElvisMini.local - trace: client error
                         ×Error 500: Parse Error: Invalid method encountered

Boom ~ 🤷‍♂️

Motivation

No response

Example

No response

@fastify/jwt and @fastify/passport FST_ERR_DEC_ALREADY_PRESENT

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.17.0

Plugin version

2.3.0

Node.js version

18.15.0

Operating system

macOS

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

13.3.1

Description

I installed @fastify/jwt and @fastify/passport plugins but getting an error if I use them both. If I remove one of them everything works good.
My motivation was to use fastify ecosystem as much as possible and I wanted to use passport for oauth2 and jwt to requests.

When running with both plugins getting this error:

FastifyError [Error]: The decorator 'user' has already been added!
    at decorateConstructor (/backend/node_modules/fastify/lib/decorate.js:41:11)
    at Object.decorateRequest (/backend/node_modules/fastify/lib/decorate.js:123:3)
    at fastifyJwt (/backend/node_modules/@fastify/jwt/jwt.js:174:13)
    at Plugin.exec (/backend/node_modules/avvio/plugin.js:130:19)
    at Boot.loadPlugin (/backend/node_modules/avvio/plugin.js:272:10)
    at processTicksAndRejections (node:internal/process/task_queues:82:21) {
  code: 'FST_ERR_DEC_ALREADY_PRESENT',
  statusCode: 500
}

I read documentation about plugins and decorators but I don't know if it applies to installed plugins.

Steps to Reproduce

  • Install @fastify/jwt and @fastify/passport
  • Register plugins
  • Run app

Expected Behavior

App is not crushing and I can use passport for oauth2 and jwt for signing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.