blitz-js / legacy-framework

MIT License
2 stars 2 forks source link

Verify Callback not being called with Salesforce Passport Strategy #168

Closed mrcampbell closed 2 years ago

mrcampbell commented 2 years ago

What is the problem?

I've tried using passport-forcedotcom and passport-salesforce, and although I get a successful authorization, my verify callback isn't being called, and so I'm not able to use the data being passed back from the OAuth Provider.

Is there something wrong with my code?

Paste all your error logs here:

...
event - build page: /api/auth/salesforce/callback
wait  - compiling...
event - compiled successfully
15:27:57.580 INFO  Starting authentication via salesforce... 
Starting authentication via salesforce...
wait  - compiling...
event - compiled successfully
event - build page: /api/auth/salesforce/callback
wait  - compiling...
event - compiled successfully
wait  - compiling...
event - compiled successfully
...

Paste all relevant code snippets here:

// <project name>/app/api/auth/[...auth].ts
import { passportAuth, VerifyCallbackResult } from "blitz"
import { Strategy as SalesforceStrategy } from "passport-salesforce"

export default passportAuth({
  successRedirectUrl: "/",
  errorRedirectUrl: "/",
  strategies: [
    {
      authenticateOptions: { scope: "id api" },
      strategy: new SalesforceStrategy(
        {
          clientID: process.env.SALESFORCE_KEY,
          clientSecret: process.env.SALESFORCE_SECRET,
          scope: ["id api"],
          callbackURL: process.env.SALESFORCE_REDIRECT_URL,
        },
        async function (_token, _tokenSecret, profile, done) {
          console.log("HERE")
          done(null, profile)
        }
      ),
    },
  ],
})

What are detailed steps to reproduce this?

  1. Correctly populate the .env vars (I've confirmed they're correct) and Salesforce's Connected App is configured correctly.
  2. In the browser, navigate to http://localhost:3000/api/auth/salesforce to Log In With Salesforce
  3. Enter credentials, and log in
  4. [Successful Login happens in backend]
  5. You end up at the Redirect URL location, without verify callback being called

Run blitz -v and paste the output here:

Loaded env from /home/mike/<project name>/.env
Linux 5.13 | linux-x64 | Node: v17.2.0

blitz: 0.44.3 (local)

  Package manager: yarn 
  System:
    OS: Linux 5.13 Ubuntu 21.10 21.10 (Impish Indri)
    CPU: (24) x64 AMD Ryzen 9 3900X 12-Core Processor
    Memory: 48.22 GB / 62.71 GB
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 17.2.0 - ~/.nvm/versions/node/v17.2.0/bin/node
    Yarn: 1.22.17 - ~/.nvm/versions/node/v17.2.0/bin/yarn
    npm: 8.1.4 - ~/.nvm/versions/node/v17.2.0/bin/npm
    Watchman: Not Found
  npmPackages:
    @prisma/client: 3.6.0 => 3.6.0 
    blitz: 0.44.3 => 0.44.3 
    prisma: 3.6.0 => 3.6.0 
    react: 18.0.0-beta-149b420f6-20211119 => 18.0.0-beta-149b420f6-20211119 
    react-dom: 18.0.0-alpha-5ca4b0433-20211020 => 18.0.0-alpha-5ca4b0433-20211020 
    typescript: ~4.5 => 4.5.2 

Please include below any other applicable logs and screenshots that show your problem:

No response

beerose commented 2 years ago

Your code looks correct, maybe it's an issue with the strategy code. Did you try this one: https://www.npmjs.com/package/passport-salesforce-oauth2 instead?

mrcampbell commented 2 years ago

Thank you for the recommendation! Let me try that one out right now. Since this doesn't seem to be blitz related, I'll close this issue.

beerose commented 2 years ago

Ok! Feel free to reopen if the issue is on the Blitz side.

mrcampbell commented 2 years ago

I still couldn't find what the issue was. I went so far as to copy the passport implementation into my own project, importing that rather than the npm package, and stepping through it. It indeed was being called in all the right ways, but for whatever reason, the verify function wasn't being called. In an effort to speed things up, I did this, which works great for now!

(Sharing for posterity, just in case anyone else needs this)

// <project name>/app/api/auth/salesforce/callback.ts
import { BlitzApiRequest, BlitzApiResponse, getSession, Routes } from "blitz"
import { Connection, IdentityInfo, UserInfo } from "jsforce"

const handler = async (req: BlitzApiRequest, res: BlitzApiResponse) => {
  var conn = new Connection({
    clientId: process.env.SALESFORCE_KEY,
    clientSecret: process.env.SALESFORCE_SECRET,
    redirectUri: process.env.SALESFORCE_REDIRECT_URL,
    instanceUrl: process.env.SALESFORCE_INSTANCE_URL,
  })

  // @ts-ignore
  const code: string | undefined = req.query.code

  // todo: handle, throw, etc
  if (!code) {
    res.statusCode = 500
    res.setHeader("Content-Type", "application/json")
    res.end(JSON.stringify({ name: "Code not found" }))
    return
  }

  await conn.authorize(code)
  .then((userInfo: UserInfo) => {
    console.log(userInfo)
  })

  // do stuff with the userInfo, or call identity for more info, 

  // random example below
  await conn.identity()
  .then((res: IdentityInfo) => {
    console.log("user ID: " + res.user_id);
    console.log("organization ID: " + res.organization_id);
    console.log("username: " + res.username);
    console.log("display name: " + res.display_name);
  });

  // then redirect to wherever!
  res.redirect('<route name>')
}

export default handler