2

I have currently implemented a NodeJs, express api with the xero-node sdk package, and I've run into an issue where it doesn't seem that the OAuth state parameter is not being used (though I see it is defined as an optional parameter for the XeroClient constructor:

export interface IXeroClientConfig {
  clientId: string,
  clientSecret: string,
  redirectUris: string[],
  scopes: string[],
  state?: string
}

Can anyone confirm if this has been implemented yet?

I am assuming it would work like this:

const xero = new XeroClient({
  clientId: xeroParams.clientId,
  clientSecret: xeroParams.clientSecret,
  redirectUris: [xeroParams.redirectUrl],
  scopes: xeroParams.scopes.split(' '),
  state: this.callback_state,
});

//then when building the consent url like this, the state param would be included
const consentUrl = await xero.buildConsentUrl();

And then when the callback gets triggered I was expecting to be able to access the state code as one of the query params. Something along the lines explained here

I have seen the session_state parameter being returned but this is not matching the state code I supplied.

Nathan
  • 90
  • 7

1 Answers1

2

Here is how you pass state through the OAuth flow using the xero-node SDK:

https://github.com/SerKnight/xero-node-basic-app/blob/master/index.js#L37

Example:

  • first generate the consentUrl, then append your custom params.
app.get('/connect', async function(req, res) {
  try {
    let consentUrl = await xero.buildConsentUrl();
    res.redirect(consentUrl + "&state=THIS_IS_A_STANDARD_OAUTH_2_STATE_PARAMETER"); // Append any type of state/params you would like
  } catch (err) {
    res.send("Sorry, something went wrong");
  }
})

...

app.get('/callback', async function(req, res) {
  let url = redirectUri + req.originalUrl;

  console.log('req.query: ', req.query) // this will the the same state/params you passed to the API

  // ...do api stuff..
  // ref: https://github.com/XeroAPI/xero-node-oauth2-app

  res.send(req.query);
})

https://github.com/SerKnight/xero-node-basic-app/blob/master/index.js#L37

Worth noting that the optional state: param of the XeroClient is reserved for openidclient stuff.. Don't use it. just append it to the consent url.

SerKnight
  • 2,502
  • 1
  • 16
  • 18
  • 1
    sorry I should have clarified, yes I am trying to get the state code back with the callback to identify the user – Nathan Jan 30 '20 at 20:51
  • 1
    Is it blowing up? I believe I fixed this way back in this commit: https://github.com/XeroAPI/xero-node/commit/62408551d35a75eb3630a5aef2cb529c9623c4c7#diff-feeb9bb1ac85af27d17bd54b75fc7285R11 What version are you using? – SerKnight Jan 31 '20 at 02:55
  • I'm using v4.0.7 of `xero-node` – Nathan Jan 31 '20 at 03:13
  • It is not blowing up, it is just that I am not getting the same state code back on the callback. There is a `session_state` parameter but it comes back as a completely different code to the one I supplied – Nathan Jan 31 '20 at 03:14
  • Maybe I am misunderstanding the purpose/use case for this state code...but my understanding was that it is there to validate that the callback is from the same user - i.e. I can parse it as a query param from the callback url and compare it with when I have stored locally to validate the user's "session" so to speak. – Nathan Jan 31 '20 at 03:26
  • 2
    So instead of passing state to the xero client, just append it to the authentication url! Thanks for your question - hopefully other folks can use this too :) – SerKnight Feb 05 '20 at 19:37