Xero - beautiful accounting software

Xero Developer Help Center

Xero Developer Community

Community > Wrapper libraries >

Xero.Api C# wrapper and the correct requestToken approach

Started by Steve Allan -   in Wrapper libraries

Hi,
I'm developing in C# and using the newer Xero.Api wrapper.
I can get the request process to work WITHOUT a oauth_callback parameter, ending up on the page that provides the random characters for the user to enter manually.
However, I want to use the callback approach. I have added localhost to the application's callback URI in my account and have attempted to add the oauth_callback parameter to the getToken request call but can't get it to work.

Firstly, can I just append the oauth call as a parameter to the URL and do nothing else?
Does the signature in the call need to include the oauth string as part of it? If it does, this is where I'm getting confused as the Dust class doesn't include it anywhere in its code and it isn't added by the wrapper as part of the call parameters. Is that just an example and shouldn't be included?

If anyone has experience with the Xero.Api wrapper and has done this before I would like to hear from you.

Thank you,
I should add that when I say 'I can't get it to work', the connection proceeds as if no oauth_callback is specified. That is, I click the button on the authorise page and I still get taken to the next screen with the random key ready for copy and pasting.
 

Steve Allan  

@Steve - there is a CallbackUrl setting you can utilise in the App.config file.
 

Tony Rule (Xero Staff)  

Thanks Tony,
I had some other errors going on as well but I can now callback to my localhost URL so I'm making progress.
 

Steve Allan  

Hi Tony,
I'm now stuck at the point of getting the access token after the callback occurs.
Below is an example of the base signature string and the resulting header. From what I have read about the spec I have the parameters right but when I do the request I keep getting "Failed to validate signature".

POST&https%3A%2F%2Fapi.xero.com%2Foauth%2FAccessToken
&oauth_consumer_key%3DXXXX
%26oauth_nonce%3Db58753e5-ba68-4c07-b4fa-d86b4265bce8
%26oauth_signature_method%3DHMAC-SHA1
%26oauth_timestamp%3D1406256806
%26oauth_version%3D1.0
%26oauth_token%3DPC9OOYB5TZY8HH9W4KC6YSROUIQXCC
%26oauth_verifier%3D4787235

OAuth realm="https://api.xero.com/",
oauth_consumer_key="XXXXX",
oauth_token="PC9OOYB5TZY8HH9W4KC6YSROUIQXCC",
oauth_signature_method="HMAC-SHA1",
oauth_signature="XbtYb%2B5YjWJ6IDWXzl7%2B%2FI0sdio%3D",
oauth_timestamp="1406256806",
oauth_nonce="b58753e5-ba68-4c07-b4fa-d86b4265bce8",
oauth_version="1.0",
oauth_verifier="4787235"

Does that look right?
 

Steve Allan  

Hi Steve,
I was wondering if you can confirm that the callback URL you put in the App.config (as suggested by Tony) worked without making any changes to Xero.Api code base?

As I understand the current code base “OAuthParameters” does not append callback url as an additional “oauth_callback” parameter when sending “RequestToken” request.

I went down the path and implemented the additional parameter and now I am getting the oauth_callback_confirmed=true as part of the response but when I authorise my app, I don’t get redirection back to my “callback url” instead I get displayed the “Pin” page.

I was wondering if you have resolved this issue, because from your above post I can see that you are in the process of requesting the access token.

Thanks for your help.
Cheers,
Rahman
 

Rahman Memon  

Hi Rahman,
I had the same issue as you with there being no callback used in the oAuthParameters so I wrote my own CreateSignature method that appends it on correctly and then passes onto the rest of the GetToken() code.

My Method was much simpler than the wrapper version. I simply build up a base signature string with the correct parameters, encode it and then build the header authorisation string from that.

the issue I'm having now is a follow on from that. Namely trying to get the string to pass validation when I've added the verifier to it (and removed the callback). And that's using my method or the wrapper's.

If you want to pass on your email, I'll send you a copy of the code.
 

Steve Allan  

I thing that might help you immediately that I just remembered.
Encode the callback URI by itself (in uppercase hex - URI.EscapeDataString() in .Net), before adding it to the parameters. My version only worked after doing the double encoding on the callback URI. Not sure why exactly but it did.
 

Steve Allan  

Thanks Steve,

I tried the URI.EscapeDataString() but no luck :-(

Appreciate your help.
Cheers,
Rahman
 

Rahman Memon  

Hi Steve,

Thanks for your help. I have managed to resolve the issue, it was related to double encoding of the callback URL.
I have put my code with full callback url implementation and yes I have managed to get access code and run few Find() queries.

https://www.dropbox.com/s/wx1b7wx3qy73jrq/Xero-Net.zip

When you download the code, try running the Xero.Api.Example.Counts project and don’t forget to change following in the app.config.

<add key="ConsumerKey" value="LQWS2UYPHTOC3OYM100LTRQJR4JCBX"/>
<add key="ConsumerSecret" value="TT4VD6JKUNZGSYKRWCP3MZ8YNZBEFY"/>
<add key="CallbackUrl" value="http://localhost"/>

After the call back redirection, you can enter the pin (verifier) on the command prompt window and it will do the rest of processing including getting the access code and run few find and get queries.
I am sure the next version of API will have the similar support but until then this may be some help.

Regards,
Rahman
 

Rahman Memon  

Thanks Rahman, I tried out your code and it does work with entering the PIN but I'm still trying to do away with that part entirely.
I now have the error "oauth_problem=permission_denied&oauth_problem_advice=The%20consumer%20was%20denied%20access%20to%20this%20resource."
So I'm not even sure I'm making progress.

the part I don;t get know is if I follow the api example and create a Core object and then make a call against an endpoint:
api.Accounts.Find().Count();
that starts the authentication process but with the callback do I need to forget about that api call and start another one when the callback method fires?? I'm missing something fundamental here...
 

Steve Allan  

Hi Steve,

I suggested the manual pin entry because I didn't have a sample web app for processing the call back redirection however in my own app I have done it so when callback redirection happens it proceeds with getting the access token automatically (instead of getting the user to enter the pin manually).

With regards to the Core object, in my case I just hold on to the “IToken” returned by Tokens.GetRequestToken call and when I get redirected response, I create a separate instance of Core object and pass the same IToken object in Tokens.GetAccessToken call. This completes the authentication protocol and we get the session token for 30 minutes.
This can be stored in a store for later usage while doing any Find() queries.

Hope it helps.
Cheers,
Rahman
 

Rahman Memon  

Rahman's pull request has been accepted for the callback url with the public authenticator - https://github.com/XeroAPI/Xero-Net/pull/14. Thanks Rahman.
 

Tony Rule (Xero Staff)  

Thanks for your assistance Tony, I will be in touch with regards to Partner token renewal part in near future. Cheers.
 

Rahman Memon  

Hi Rahman,

I am facing the same problem where it was not redirecting back to callback url (my partner app). I have tried your suggested solution but somehow it is not working for me and getting following response from Xero API

oauth_problem=parameter_rejected&oauth_problem_advice=When%20obtaining%20a%20request%20token%2C%20you%20must%20not%20supply%20the%20oauth_token%20parameter

Can you please take a look and let me know if I am making any mistake. Your earliest response will be highly appreciated.

Regards,

Tahir Ahmed
iSplendid
 

Tahir Ahmed  

Hi @Rahman. I am trying to implement the partner application and facing a problem which is to renew the access token.

According to the official wrapper library, there is a class which is called "OAuthTokens" that has given me some ideas to renew the token, however, i could not find a way to communicate from the user interface. Would you be able to share your experience with me?
Thank you
 

Duncan Grant