fastify / help

Need help with Fastify? File an Issue here.
https://www.fastify.io/
64 stars 8 forks source link

Cannot read properties of undefined (reading 'getAccessTokenFromAuthorizationCodeFlow') #1035

Closed clubside closed 3 months ago

clubside commented 3 months ago

You have already researched for similar issues?

I have done a bunch of searching but nothing in particluar comes up for this basic error.

What are you trying to achieve, or the steps to reproduce?

I'm trying to implement login with Google using the oauth2 plugin and the code in the Google example. The login page displays fine but after choosing a Google account it throws an error in the callback handler.

app.register(oauthPlugin, {
    name: 'googleOAuth2',
    scope: ['profile', 'email'],
    credentials: {
      client: {
            id: '** my client id **',
            secret: '** my secret **'
      },
      auth: oauthPlugin.GOOGLE_CONFIGURATION
    },
    startRedirectPath: '/login/google',
    callbackUri: 'http://localhost:3950/api/auth/google/callback'
})
app.get('/api/auth/google/callback', async (request, reply) => {
    this.googleOAuth2.getAccessTokenFromAuthorizationCodeFlow(request, async (err, result) => {
        if (err) {
            reply.send(err)
            return
        }
        const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
            method: 'GET',
            headers: { Authorization: `Bearer ${result.token.access_token}` }
        })
        if (response.ok) {
            const data = await response.json()
            reply.send(data)
        } else {
            reply.send(response.status)
        }
        return response.json()
    })
})

What was the result you received?

{"statusCode":500,"error":"Internal Server Error","message":"Cannot read properties of undefined (reading 'getAccessTokenFromAuthorizationCodeFlow')"}

What did you expect?

At this point I don't know, but result.token.access_token at the very least.

Context

clubside commented 3 months ago

If I use the default sample only changing the key, secret and callback to match my Google app I get a different error:

'use strict'

const fastify = require('fastify')({ logger: { level: 'trace' } })
const oauthPlugin = require('@fastify/oauth2')
const sget = require('simple-get')

// const oauthPlugin = require('fastify-oauth2')
fastify.register(oauthPlugin, {
  name: 'googleOAuth2',
  scope: ['profile', 'email'],
  credentials: {
    client: {
      id: '** my client id **',
      secret: '** my secret **'
    },
    auth: oauthPlugin.GOOGLE_CONFIGURATION
  },
  startRedirectPath: '/login/google',
  callbackUri: 'http://localhost:3950/api/auth/google/callback'
})

fastify.get('/api/auth/google/callback', async function (request, reply) {
  this.googleOAuth2.getAccessTokenFromAuthorizationCodeFlow(request, (err, result) => {
    if (err) {
      console.log(err)
      reply.send(err)
      return
    }

    sget.concat({
      url: 'https://www.googleapis.com/oauth2/v2/userinfo',
      method: 'GET',
      headers: {
        Authorization: 'Bearer ' + result.token.access_token
      },
      json: true
    }, function (err, res, data) {
      if (err) {
        reply.send(err)
        return
      }
      reply.send(data)
    })
  })
})

fastify.listen({ port: 3950 })

This is the Fastify log message:

{
    "level": 30,
    "time": 1720055047682,
    "pid": 56044,
    "hostname": "clubGamer",
    "reqId": "req-1",
    "req": {
        "method": "GET",
        "url": "/api/auth/google/callback?state=vZJdfQZWoqixD31cFqPs_w&code=4%2F0ATx3LY4HdN6JKzUvxRamvAhA84rrVinDGq5sXtTT7F1j3RlK7Kpnvfl7q-bgjewzsS8QpQ&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=consent",
        "hostname": "localhost:3950",
        "remoteAddress": "::1",
        "remotePort": 59136
    },
    "msg": "incoming request"
}

console.log error:

Error: Invalid state
    at Object.defaultCheckStateFunction (V:\dev\oauth2\node_modules\@fastify\oauth2\index.js:33:12)
    at checkStateFunctionCallbacked (V:\dev\oauth2\node_modules\@fastify\oauth2\index.js:224:9)
    at getAccessTokenFromAuthorizationCodeFlowCallbacked (V:\dev\oauth2\node_modules\@fastify\oauth2\index.js:239:7)
    at Object.getAccessTokenFromAuthorizationCodeFlow (V:\dev\oauth2\node_modules\@fastify\oauth2\index.js:256:7)
    at Object.<anonymous> (V:\dev\oauth2\index.js:23:21)
    at preHandlerCallback (V:\dev\oauth2\node_modules\fastify\lib\handleRequest.js:138:37)
    at validationCompleted (V:\dev\oauth2\node_modules\fastify\lib\handleRequest.js:122:5)
    at preValidationCallback (V:\dev\oauth2\node_modules\fastify\lib\handleRequest.js:99:5)
    at handler (V:\dev\oauth2\node_modules\fastify\lib\handleRequest.js:76:7)
    at handleRequest (V:\dev\oauth2\node_modules\fastify\lib\handleRequest.js:24:5)     
{
    "level": 50,
    "time": 1720055047690,
    "pid": 56044,
    "hostname": "clubGamer",
    "reqId": "req-1",
    "req": {
        "method": "GET",
        "url": "/api/auth/google/callback?state=vZJdfQZWoqixD31cFqPs_w&code=4%2F0ATx3LY4HdN6JKzUvxRamvAhA84rrVinDGq5sXtTT7F1j3RlK7Kpnvfl7q-bgjewzsS8QpQ&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=consent",
        "hostname": "localhost:3950",
        "remoteAddress": "::1",
        "remotePort": 59136
    },
    "res": {
        "statusCode": 500
    },
    "err": {
        "type": "Error",
        "message": "Invalid state",
        "stack": "Error: Invalid state\n    at Object.defaultCheckStateFunction (V:\\dev\\oauth2\\node_modules\\@fastify\\oauth2\\index.js:33:12)\n    at checkStateFunctionCallbacked (V:\\dev\\oauth2\\node_modules\\@fastify\\oauth2\\index.js: 224: 9)\n    at getAccessTokenFromAuthorizationCodeFlowCallbacked (V:\\dev\\oauth2\\node_modules\\@fastify\\oauth2\\index.js: 239: 7)\n    at Object.getAccessTokenFromAuthorizationCodeFlow (V:\\dev\\oauth2\\node_modules\\@fastify\\oauth2\\index.js: 256: 7)\n    at Object.<anonymous> (V:\\dev\\oauth2\\index.js: 23: 21)\n    at preHandlerCallback (V:\\dev\\oauth2\\node_modules\\fastify\\lib\\handleRequest.js: 138: 37)\n    at validationCompleted (V:\\dev\\oauth2\\node_modules\\fastify\\lib\\handleRequest.js: 122: 5)\n    at preValidationCallback (V:\\dev\\oauth2\\node_modules\\fastify\\lib\\handleRequest.js: 99: 5)\n    at handler (V:\\dev\\oauth2\\node_modules\\fastify\\lib\\handleRequest.js: 76: 7)\n    at handleRequest (V:\\dev\\oauth2\\node_modules\\fastify\\lib\\handleRequest.js: 24: 5)"
    },
    "msg": "Invalid state"
}
Eomm commented 3 months ago

1) first error: you can't use this with arrow functions in this case.

-app.get('/api/auth/google/callback', async (request, reply) => {
+app.get('/api/auth/google/callback', async function (request, reply) {
    this.googleOAuth2.getAccessTokenFromAuthorizationCodeFlow(request, async (err, result) => {

2) it seems a duplicate of https://github.com/fastify/fastify-oauth2/issues/236

clubside commented 3 months ago

Thanks so much, that makes sense. I switched to Fastify Passport which worked fine using their example but I prefer this library’s design so I will use your fix for my next project.