Xero - beautiful accounting software

Xero Developer Help Center

Xero Developer Community

Community > Getting Started >

PKCE authentication - sample required

Started by Gerard D'Rozario -   in Getting Started

I'm trying to write a C# .NET Core desktop/console app and so I'm looking to get started with a simple but complete PKCE app. I'm having all sorts of trouble following the bits and pieces of tutorials and sample code to get anywhere. Help!

The docs at https://github.com/XeroAPI/Xero-NetStandard show PKCE code but it's either outdated or faulty. Simple stuff like "List<Tenant> tenants = await client.GetConnections();" throws up an error because GetConnections does not exist (presume it should be the async version). One snippet refers to a 'code' variable which I have to presume has to be copied by hand from the redirect params, except the code obtained only works while that session is active. If the app is stopped and restarted the code fails with invalid_grant.

That line:

await client.RequestAccessTokenPkceAsync(code, codeVerifier);

makes a call to a function RequestAccessTokenPkceAsync for which there is no documentation. What does it do? Does it have to called before each call to an invoice api function for example?

One snippet creates a random codeVerifier value while the very next snippet uses a hardcoded "Aaaaaaaaaa.Bbbbbbbbbb.0000000000.1111111111" value. What's that about?

All help appreciated - cheers, Gerard
We've built an example app here: https://github.com/XeroAPI/net-desktop-pkce-example

Apologies that we haven't linked to it very heavily yet. I'll try to get that resolved so that it can be easily found.
 

Robin Blackstone (Community Manager)  

Hey Robin,

That's awesome, thanks. That provides some great insights and allows easily tinkering with. And works beautifully.

Couple of questions though, if I may...

I'm not sure what the story is, but I would have thought that once I have the code that's returned after login (and we have the access and refresh tokens, as well as a tenant ID I want to target) I can use those values forever and a day without having to go through all the steps.

That is: if I copy the tokens and code, save those values in a config file, then run the app, read and reuse those values, I should be able to simply click ''Refresh Tokens', and make an API call.

But that's not the case - if the tokens expire (after half an hour) and I click on refresh tokens it fails with a grant error. Am I misunderstanding what's supposed to happen?

Secondly, the sample works completely outside the Xero.NetStandard.OAuth2 libs. How could I incorporate the into this model. There's no PCKE authentication built into the libs and this sample works outside those libraries. So if I want to use all the handy API call wrappers to create invoices, find customers, etc but with PKCE authentication in (for example) a .NET core console app or a .NET winforms app what's the best way forward?

Thanks so much.

Gerard

PS - I think I've sorted myself out myself out on both scores. But if you have any suggestions on the 2nd one I'd welcome them, in case I'm going about things the wrong way.
 

Gerard D'Rozario  

Hi Robin,

Struggling again to understand what's happening - am I not right in assuming that once I get the return code via the listener, I can save those values for permanent reuse with that particular app and code verifier, and should then be able to click 'retrieve Tokens' without going through step 1a? My code verifier is a constant string btw.

I am finding that I have to go through step 1a again after 30 mins (hard to keep track of time but at a guess). All I get back if I reuse the old return code is "invalid_grant".

Thanks - Gerard


 

Gerard D'Rozario  

I am a little rusty on this, but once the login has been completed the first time, you should just be able to keep refreshing the tokens as they expire, yes.

I use PKCE, but from VB. I store the access token, the refresh token, and a calculated expiry date/time internally in the app, and every time I go to interact with Xero, I check my internal expiry date/time to see if a refresh is needed. This works whether the token has just expired, or if I was testing it last Friday and only came back to it the next Monday. The only problem I've run into is trying to refresh a token that's already been refreshed - if for some reason the latest refresh token isn't stored (in testing / dev usually), the previous one won't refresh again.
 

Mike Edwards  

https://community.xero.com/developer/discussion/125903777/
 

Darren Lawrence  

Hey Mike - thanks very much for the assistance. I've followed that model and it's working quite well. And thanks Darren for the input. I am pretty much using that approach too (combination of http listener and NuGet OAuth2 package).
Chees - Gerard
 

Gerard D'Rozario  

Sorry for not getting back to you all sooner.

Once you've obtained the access and refresh tokens the earlier steps become redundant. In production you would store the tokens somewhere safe for future use.

On refreshing the tokens you would overwrite the existing tokens with the new ones. Each refresh resets the validity, so your latest refresh token will always be valid for 60 days from the moment it is issued.

@Gerard It is worth noting that when a refresh is performed the old set of tokens will expire. The Invalid grant error would typically appear if you are trying to refresh a previously used token.

In our sample app we've stopped short of integrating with the SDK, however it would appear that Darren is working in that direction here: https://community.xero.com/developer/discussion/125903777/
 

Robin Blackstone (Community Manager)