As most of you probably know by now, Salesforce supports the OAuth protocol for authenticating with Force.com. Check out Pat's excellent article for a deeper dive into OAuth 2.0 at Salesforce.com. What some of you may not know however is that you can use the access token acquired via OAuth to authenticate with the venerable SOAP API. So instead of invoking the 'login' method of the SOAP API by providing your username/password (and optionally security token), you can acquire an OAuth access token by implementing any one of the OAuth 2.0 flows described in Pat's article (say the 'Username-Password Flow'). You can then insert the OAuth access token into the standard 'sessionID' SOAP header to make subsequent calls to the SOAP API.
So far so good. There is however a small nuance to using OAuth authentication with the SOAP API that I wanted to highlight. In the traditional username/password authentication scheme (described in greater details here), the initial 'login' call is made to the https://login( or test).salesforce.com/services/Soap/….. URL. In response, Salesforce returns the server URL (e.g. https://na1-api.salesforce.com/services/Soap/c/21.0) that all subsequent API requests should be redirected to. With OAuth, since you're never invoking the 'login' method of the SOAP API, how do you know which URL to redirect your API calls to? If you simply directed your API calls to the generic https://login(or test).salesforce.com/services/Soap/….. URL, you'd get an authentication error.
What's that you say? Couldn't I just use the 'instance_url' that is returned along with the access token during the OAuth dance? (Quick non sequitur. I love when geeks try to describe technology to other geeks with metaphors like 'dance'. Like any of us geeks can relate to how it is to dance!). The 'instance_url' value acquired via OAuth 2.0 simply points to the Salesforce instance that your Org is hosted on (e.g. 'https://na1.salesforce.com'). It is not the SOAP endpoint that you should be redirecting your API requests to. Since the SOAP endpoint URI naming convention is well known, you could of course construct the SOAP endpoint in your client code by appending '/services/Soap/….' to the 'instance_url'. There is however a better option that doesn't require hard-coding the endpoint (and by extension the API version) in your code.
The answer lies in the magical, yet often overlooked 'id' parameter that is returned by OAuth 2.0 along with the access token. As described by Pat here, you can get a wealth of information by making a simple GET request to the 'id' URI. Among the pieces of information returned (in the 'urls' array to be exact) are the SOAP endpoints for the Enterprise and Partner WSDLs. Depending on whether you're consuming the Enterprise or Partner WSDL, these are the URLs that you should direct all subsequent SOAP calls to.
So, to recap, here is the sequence of events for using OAuth 2.0 with the SOAP API
1) Implement one of the 6 flows supported by OAuth 2.0 and receive the access token, 'id' and other parameters from Force.com.
2) Make a GET request (passing in the access token as the OAuth authorization HTTP header) to the 'id' URI.
3) Insert the access token into the 'sessionID' SOAP header and make all subsequent API calls to the enterprise or partner SOAP endpoints returned by the previous step.
As always, comments/brickbats/suggestions are welcome. Now its back to 'dancing' with my current project!