Xero - beautiful accounting software

Xero Developer Help Center

Xero Developer Community

Community > API Authentication >

Delphi oauth authentication

Started by Hashitha Subasinghe -   in API Authentication

Does anyone know how to authenticate using delphi. I used the oauth for delphi library (http://chuckbeasley.wordpress.com/2009/04/29/using-oauth-for-delphi/)
but im stuck at getting the access token
Hi Hashi. I had a quick look at Chuck Beasley's library recently but found it difficult to work with and possibly incomplete. I've since started working with OAuth myself from first principles (in Delphi) and have just (literally today!) got things working with the Xero API.

I'm doing 2-legged auth (Private App) with RSA-SHA1 signing, but the principles are basically the same. The major difference is the lack of any need for the Request/Access Token dance, but I have done that with other OAuth providers too.

I'd like to help, if I can. What exactly is the problem you are having with obtaining the Access Token ?
 

Flow Software (Xero Demo)  

Thanks for your reply.
I was getting 401 access denied when I put in the access token.
anyways I have completed the project in .net as I had no choice (I love Delphi).
I am interested in you private app authentication if you are happy to share the code.
 

Hashitha Subasinghe  

I am building a client for a private application. I looked at Chuck's work and found it a good introduction. I then started building from first principles but am stuck with Unauthorized and Internal Server Error responses.
If Hashi or Flow Software can share any code/ideas I would appreciate it.
 

Bryan Wilkins  

Just an update... I have run my url string from OAuth Playground and it confirms that it is my signature that is invalid.
I am trying Lockbox3 and Chilkat to create the signature string. Even though I supply each with the same string they return different results... frustrating. I am about to try StreamSec.
Then moving on to base64 coding the string... I am trying DCPbase64 and TIdEncoderMIME.EncodeBytes. These at least appear consistent. But don't ask LockBox3 to return a utf8 string and then base64 it because you get a different result from just doing the base64 in Lockbox3...
So I guess I am asking what components have you used that work.
My base string appears to meet OAuth Core 1.0 Revision A specifications; I have only checked it a million times and made half a million fixes :-)
Soap web services are soooo simple.
 

Bryan Wilkins  

I have successfully made a GET call. I am using ChilKat's RSA component. The door is open.
 

Bryan Wilkins  

I am new to Xero. Previously programmed in Delphi to MYOB AccountRight and retail Manager. I'm happy to pay for some training if any of you guys have the time to help. I am based in Adelaide South Australia, not that is overly important.
Eric March
httpd://www.ebmpl.com.au/

 

Eric March  

Hi Eric, I can let you have some code if you want.
I tried every bit of 3rd party software for the encoding and the only one that was compatible with Xero was Chilkat. Costs money but if I remember correctly they give a 30 day free trial. Plus, their support is excellent.
Guess the easiest way would be for me to email the code to you. (bryan_wilkins@bigpond.com) Send em an email if you would like it.
Bryan
 

Bryan Wilkins  

Hello Bryan,

is Chilkat a VCL solution? I though it is an ActiveX component?
I have used SecureBlackbox® from EldoS Corporation, which is a bit more expensive than Chilkat but is a pure Delphi VCL solution. I think one can learn a lot when having access to the souce code of the implementation, which clearly isn't the case with an ActiveX component.

Here is an overview of SSL components for Delphi:
http://www.eldos.com/sbb/sslcompare.php

Salut,
Mathias
 

Mathias Burbach  

Thanks Bryan & Mathias.
Any pointers and simple source would be much appreciated.
Eric
 

Eric March  

Hey Mathias, I would have liked to have talked to you this time last year :-) Would have saved me a lot of pain. I think that I tried SecureBlackbox but it was not the one that worked first.
Anyway Eric, if you would like some code then email me.
Bryan
 

Bryan Wilkins  

I've asked Mathias if I can buy some lessons off him. I'll wait and see what he can do.
 

Eric March  

Good. Please post how you get on.
 

Bryan Wilkins  

Hi Mathias and Bryan,

we have a requirement to integrate with Xero, Delphi 7 standalone app. Is there some code you could provide(free or not free) so we could get started?

Thanks,
Dmitry
 

Dmitry Stukov  

Hi Dmitry,
My solution uses Chilkat ActiveX and Delphi 2010. You are welcome to the code. It should compile in 2007 with a few modifications.
I have supplied the code to another developer who has upgraded it to XE4 and Chilkat's Delphi DLL (no ActiveX). I think the DLL is only available for XE4.
Email me at bryan_wilkins@bigpond.com if you would like the code.
Regards,
Bryan
 

Bryan Wilkins  

I have released our (Flow Software) native Delphi code for OAuth with Xero, as this code essentially wraps others open source code that does most of the heavy lifting.

You can download from ftp://ftp.flow.net.nz/release/code/OAuthWithXero.zip.

Hope this helps someone...
 

Cameron Hart  

Hi Cameron
Thanks for supplying the code I have managed to get everything working but continue to get Unautherized Response back for Private Apps. The request looks correct so I wonder if its the RSA encoding. Any thoughts much appreciated.

GET https://api.xero.com/api.xro/2.0/Accounts/ HTTP/1.1
Authorization: OAuth realm="https://api.xero.com/api.xro/2.0/Accounts", oauth_consumer_key="VYUDXML0...............1QXMZN1XMK", oauth_token="VYUDXML0Y6H...........1XMK", oauth_nonce="4449F326383B23AF1FC6D6137387C8A4", oauth_timestamp="1402954679", oauth_signature_method="RSA-SHA1", oauth_version="1.0", oauth_signature="VV%2Fsx..............LlIiInak3YUZpllnAfLGN8mSPzKc%3D"
Host: localhost:8888
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: identity
User-Agent: Mozilla/3.0 (compatible; Indy Library)

 

Peter O'Hanlon  

Hello Cameron,
I would also like to say thanks very much for posting your OAuthWithXero code. Unfortunately however I am having the exact same problem as Peter O'Hanlon - "401 Unauthorized" when attempting to access any of the Xero API URLs. I have the same problem with GET and POST.

I'm using Indy 10, latest version. I've tried Delphi 7 compiler as well as XE5. I get exactly the same result from both so I don't believe there is a problem with the environment.

I created a private app on the Xero site using the public key part of a valid certificate. In your TFloHTTPTransport.OAuthSignRequest() method, I put the private app's ConsumerKey value into the local variables conkey and tok, and the ConsumerSecret value into the consecret and toksecret variables.

The OAuthSignatureMethod is oaRSA (my understanding is it has to be for private apps), and the value passed in the aPrivateKey parameter to the classFloOAuth.OAuthSignRequest() method is the base64 unencrypted private key section of the same certificate used to initialise the private app.

I'm using a TIdHTTP component, coupled with a TIdSSLIOHandlerSocketOpenSSL. I have the latest Openssl dlls sitting in the project directory.

Can I ask how you're configuring the TIdHTTP component, or if there are any other special requirements in setting up for the web request?

Any insight or thoughts whatsoever would be great appreciated, I feel like I'm so close but not sure where to go from here.

Thanks,
Matt

 

Matt Handel  

Hi again - never mind I got it working. I had uploaded the wrong certificate to Xero when I setup the private app, duh! Perhaps I need more sleep...

Anyway thanks again Cameron for sharing the code, it works a treat!
Matt
 

Matt Handel  

Hi Matt I must be doing something wrong I can't get the private key to work my request looks like below. Any Ideas most welcome it will be something stupid I'm doing. I wonder if there's something wrong with my private / public keys.

GET https://api.xero.com/api.xro/2.0/Accounts HTTP/1.1
Authorization: OAuth realm="https://api.xero.com/api.xro/2.0/Accounts",
oauth_consumer_key="VYUDXML0Y6HTBGF98BWK1QXMZN1XMK",
oauth_token="VYUDXML......XMZN1XMK",
oauth_nonce="F848B297ADF0C5A2C900A6A0C929A1",
oauth_timestamp="1403240773",
oauth_signature_method="RSA-SHA1",
oauth_version="1.0",
oauth_signature="g17Ps24K5vcgIj5........JgGI%2BePxFQQ%3D"
Host: https://api.xero.com/api.xro/2.0/Accounts
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: identity
User-Agent: Mozilla/3.0 (compatible; Indy Library)

I
 

Peter O'Hanlon  

Just as I thought I'm an idiot my public and private certificates didn't match. I figured this out by extracting the public key from the private and comparing.
openssl x509 -in publickey.cer -modulus -noout > public.txt
openssl rsa -in privatekey.pem -modulus -noout > private.txt
The two txt files should be the same.
 

Peter O'Hanlon  

Hi Peter,
Good to hear you got it going. In my case I had used the openssl command line to convert the .pfx into a plaintext .cer, but when I copied and pasted the public certificate text into the xero form I accidentally picked up one of the other public certs that appear in the file instead of my own (i think it was the public cert of the certifying company itself). Stupid mistake...
Matt
 

Matt Handel  

Hi Matt,
I have managed to get HMAC-SHA256 signature working as well so feel I'm on a role , a feeling that historically quickly changes back to frustration. If you need the code my email address is peteroh@zac.co.nz
 

Peter O'Hanlon  

Hi Peter / Cameron,
Seems I spoke too soon - while everything is working fine with GET, I cannot get POST to work. I keep getting "401 Unauthorized".

I'm including the xml to send as a form parameter (as per the Xero docs) by url encoding the xml string (using the OAuthEncode() function from classFloOAuth.pas), prepending it with 'xml=' and putting it into a TStringStream. Then I'm signing the TIdHTTP request with OAuthSignRequest() and posting the stream.

I'm thinking that perhaps the POST data has to be somehow included in the signing process. I've tried including it in the aParams parameter of OAuthSignRequest, but that results in a "400 Bad request" error.

I'm sure it's something super simple, since GETs are working no problem. Any thoughts or suggestions?
 

Matt Handel  

Ok figured it out. You do have to include the "xml=..." form parameter in the aParams argument to OAuthSignRequest, without url encoding. Then post the data using the TStrings overload of TIdHTTP.Post (instead of TStream) and let indy do the encoding.

I'm pretty sure I had tried this approach earlier but dismissed it because it resulted in a "Bad Request" error, but by using Fiddler I discovered that this was actually due to a validation issue within the xml data I was sending, not because of OAuth or an otherwise badly formed request. Misleading error message IMO...

Anyway finally got there. Hope this helps anyone else having trouble. It's a shame Xero don't provide a Delphi wrapper.
 

Matt Handel  

Just making Delphi users aware of this
https://sourceforge.net/projects/delphixero/
 

Tristan Marlow