Skip to content

OAuth 2.0 for Web Server Applications, "auth Related Error (invalid_rapt)" error #1961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ujja opened this issue Apr 23, 2025 · 3 comments

Comments

@ujja
Copy link

ujja commented Apr 23, 2025

Hello,

I have implemented OAuth2 to access Dialogflow CX library (@google-cloud/dialogflow-cx) following this doc

Our application can have multiple dialogflow chatbots, so different refresh tokens. It can happen that 2 refresh tokens belongs to the same Google OAuth2 Client

I made 2 changes:

I initialize the auth to access dialogflow:

  const authClient = new OAuth2Client(CLIENT_ID, CLIENT_SECRET)
  authClient.setCredentials({
    refresh_token: REFRESH_TOKEN
  })

  const params = { authClient }

It works for a day, or so, but then I got auth Related Error (invalid_rapt)

I tried to refresh token manually following the tutorial, and i found a method for it:
authClient.refreshAccessToken()

Same result (I mean every failed with 400, but when I called refreshAccessToken(), I have seen this invalid_rapt )

@danieljbruce
Copy link
Contributor

Please give us full steps to reproduce the issue including everything you did starting from scratch. If this includes any code samples, please provide the full code sample so that we can copy/paste the code to try to reproduce the issue.

@danieljbruce danieljbruce added the needs more info This issue needs more information from the customer to proceed. label Apr 23, 2025
@ujja
Copy link
Author

ujja commented May 8, 2025

I can reproduce it this way:

  1. authenticate (http://localhost:8080/oauth2)
  2. call dialogflow (http://localhost:8080/dialogflowcx)
  3. wait a day
  4. call dialogflow (http://localhost:8080/dialogflowcx)

.env:

YOUR_CLIENT_ID=
YOUR_CLIENT_SECRET=

DIALOGFLOW_API_ENDPOINT=
DIALOGFLOW_AGENT_PATH=

package.json:

{
  "name": "google-dialogflow-oauth",
  "version": "1.0.0",
  "description": "",
  "author": "",
  "type": "commonjs",
  "dependencies": {
    "@google-cloud/dialogflow-cx": "^5.0.1",
    "@google-cloud/storage-transfer": "^4.0.1",
    "body-parser": "^2.2.0",
    "crypto": "^1.0.1",
    "dotenv": "^16.5.0",
    "express": "^4.21.2",
    "express-session": "^1.18.1",
    "google-auth-library": "^10.0.0-rc.1",
    "googleapis": "^148.0.0",
    "passport": "^0.7.0",
    "passport-local": "^1.0.0"
  }
}

js:

const http = require('http');
const https = require('https');
const fs = require('fs');
const url = require('url')
const crypto = require('crypto');

const express = require('express');
const session = require('express-session');

const dotenv = require('dotenv');
const { AgentsClient } = require("@google-cloud/dialogflow-cx");
const { google } = require('googleapis');
const { OAuth2Client } = require("google-auth-library");

const scopes = [
  'https://www.googleapis.com/auth/dialogflow'
];

const createOAuthClient = () => {
  return new google.auth.OAuth2(
    process.env.YOUR_CLIENT_ID,
    process.env.YOUR_CLIENT_SECRET,
    'http://localhost:8080/oauth2callback'
  );
}

async function main() {
  dotenv.config();
  const app = express();


  app.use(session({
    secret: 'your_secure_secret_key', // Replace with a strong secret
    resave: false,
    saveUninitialized: false,
  }));

  app.get('/oauth2', async (req, res) => {
    const state = crypto.randomBytes(32).toString('hex');
    req.session.state = state;

    const oauth2Client = createOAuthClient();
    const authorizationUrl = oauth2Client.generateAuthUrl({
      access_type: 'offline',
      scope: scopes,
      include_granted_scopes: true,
      state: state,
      // CHANGE: always ask for consent to get refresh token every time
      prompt: 'consent'
    });

    res.redirect(authorizationUrl);
  });

  app.get('/oauth2callback', async (req, res) => {
    let q = url.parse(req.url, true).query;

    if (q.error) {
      console.log('Error:' + q.error);
      res.status(500).json({ message: q.error })
    } else { // Get access and refresh tokens (if access_type is offline)
      const oauth2Client = createOAuthClient();
      let { tokens } = await oauth2Client.getToken(q.code);

      fs.writeFileSync('./tokens.json', JSON.stringify(tokens), 'utf8')
      res.status(200).json({ message: 'OK' })
    }
  });

  app.get('/dialogflowcx', async (req, res) => {
    try {
      const tokens = JSON.parse(fs.readFileSync('./tokens.json', 'utf8'))

      // Using 2 versions of google-auth-library because:
      // https://github.com/googleapis/google-auth-library-nodejs/issues/1952
      const oauth2Client = new OAuth2Client(
        process.env.YOUR_CLIENT_ID,
        process.env.YOUR_CLIENT_SECRET
      );
      oauth2Client.setCredentials({refresh_token: tokens.refresh_token})

      // same result, if i try to get access token
      // const refresTokenResult = await oauth2Client.refreshAccessToken()
      // console.log(`refresTokenResult ===> ${JSON.stringify(refresTokenResult)}`)

      const client = new AgentsClient({
        authClient: oauth2Client,
        apiEndpoint: process.env.DIALOGFLOW_API_ENDPOINT
      })

      const agentData = await client.getAgent({
        name: process.env.DIALOGFLOW_AGENT_PATH
      })

      res.status(200).json({ message: 'OK', displayName: agentData[0]?.displayName })
    } catch (e) {
      console.error('Error:', e)
      res.status(500).json({ message: 'Error', error: e.message })
    }
  });

  const server = http.createServer(app);
  console.log(`Authentication on http://localhost:8080/oauth2`)
  console.log(`Calling dialogflow on http://localhost:8080/dialogflowcx`)
  server.listen(8080);
}
main().catch(console.error);

@github-actions github-actions bot removed the needs more info This issue needs more information from the customer to proceed. label May 8, 2025
@ujja
Copy link
Author

ujja commented May 14, 2025

any news regarding this pls?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants