fastify/fastify-oauth2

Google auth error: Invalid state

fozooni opened this issue · 4 comments

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.24.3

Plugin version

7.5.0

Node.js version

18.18

Operating system

macOS

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

Sonoma 14.0

Description

Hello dears,

This is the first time I use @fastify/oauth2,
After installing and configuring its settings to log in through Google, I encountered the Invalid State error.
I'm sure I entered the Google Console settings correctly.

Steps to Reproduce

This's my plugin setup:

declare module 'fastify' {
    interface FastifyInstance {
        GoogleOAuth2: OAuth2Namespace;
    }
}

const googleOAuth2Options = {
    name: 'GoogleOAuth2',
    scope: ['profile', 'email'],
    credentials: {
        client: {
            id: config.GOOGLE_OAUTH_ID,
            secret: config.GOOGLE_OAUTH_SECRET
        },
        auth: oAuth.GOOGLE_CONFIGURATION
    },
    startRedirectPath: '/login/google',
    callbackUri: 'http://localhost:8000/login/google/callback'
};

This's my router handler:

app.get('/google/callback',async function (request: FastifyRequest, reply: FastifyReply) {
      const { token } = await app.GoogleOAuth2.getAccessTokenFromAuthorizationCodeFlow(request)
      reply.send({ token })
  });

And this's the exact error I'm getting as JSON Response and Console Response:

{
  "statusCode": 500,
  "error": "Internal Server Error",
  "message": "Invalid state"
}
Error: Invalid state
    at defaultCheckStateFunction (/Users/xxx/node_modules/@fastify/oauth2/index.js:24:12)
    at getAccessTokenFromAuthorizationCodeFlowCallbacked (/Users/xxx/node_modules/@fastify/oauth2/index.js:143:5)
    at Object.getAccessTokenFromAuthorizationCodeFlow (/Users/xxx/node_modules/@fastify/oauth2/index.js:158:5)
    at Object.<anonymous> (/Users/xxx/src/modules/user/user.route.ts:22:27)
    at preHandlerCallback (/Users/xxx/node_modules/fastify/lib/handleRequest.js:137:37)
    at validationCompleted (/Users/xxx/node_modules/fastify/lib/handleRequest.js:121:5)
    at preValidationCallback (/Users/xxx/node_modules/fastify/lib/handleRequest.js:98:5)
    at handler (/Users/xxx/node_modules/fastify/lib/handleRequest.js:75:7)
    at handleRequest (/Users/xxx/node_modules/fastify/lib/handleRequest.js:24:5)
    at runPreParsing (/Users/xxx/node_modules/fastify/lib/route.js:589:5)

I don't know exactly where the problem is, but I don't think it's from my codes.

Expected Behavior

No response

Eomm commented

Read here: #218 (comment)

I think we should fix our documentation tho

yes we should

Read here: #218 (comment)

I think we should fix our documentation tho

Thank you so much 🙏

I found the solution!

When we set callbackUri to exact uri like: 'http://localhost:8000/api/login/google/callback', it does not take the Query Parameters for validating some of stuff!
So we need to pass the state to request with generateStateFunction and validate the state with checkStateFunction!

Just like this:

app.register(oAuth, {
    name: 'GoogleOAuth2',
    scope: ['profile', 'email'],
    credentials: {
        client: {
            id: config.GOOGLE_OAUTH_ID,
            secret: config.GOOGLE_OAUTH_SECRET
        },
        auth: oAuth.GOOGLE_CONFIGURATION
    },
    startRedirectPath: '/login/google',
    callbackUri: 'http://localhost:8000/api/login/google/callback',
    generateStateFunction: (request: FastifyRequest, reply: FastifyReply) => {
        return request.query.state
    },
    checkStateFunction: (request: FastifyRequest, callback: any) => {
        if (request.query.state) {
            callback()
            return;
        }
        callback(new Error('Invalid state'))
    }
})

I hope this solution solves the problem of others. 👍