+ Start a Discussion
cottonchoppercottonchopper 

SOAP and OAuth 2.0

I have read through the pdf files on the site and I have finally been able to retrieve my access token using OAuth 2.0.  Now I am trying to use that access token in the SOAP API.  There doesn't seem to be a place to specify the access token in the SForceService API.  The Large SalesForce doc says "For the SOAP API, the access token is placed in the Salesforce SOAP authentication header. See Web Services API Developer's Guide."

 

The Web Services API Developer's Guide says "For the SOAP API, the access token is placed in the Salesforce SOAP authentication header. See Web Services API Developer's Guide."  Which is the document I am in and doesn't provide any help.

 

Any help would be appreciated.

 

Thanks,

 

Darrell

forecast_is_cloudyforecast_is_cloudy

The OAuth access token has to be placed in the standard 'SessionId' SOAP Header of the SOAP API. More details about the 'SessionId' header here - http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_header_sessionheader.htm. 

 

To explain a bit more....

 

Normally, when using the old username/psswd authentication, you would invoke the login method of the SOAP API and then place the Session Id returned by that call in the 'SessionID' SOAP Header for all subsequent API calls. With OAuth, you don't have to invoke the login call anymore. Simply place the OAuth access token in the 'SessionId' SOAP header and all should be good. Sorry for confusing documentation (we're try and get that fixed) and hope this helps

ziltoidziltoid

Is the only thing that differs from the old-style login to the OAuth login replacing the sessionId?

 

I've followed the example here https://connect-demo.appspot.com/javascript to get the id (that is, the salesforce URL to access) and access_token.  I try requesting a resource from the salesforce server using the access_token as the sessionId, but I recieve a 403 forbidden error.  Am I missing something?

 

 

cottonchoppercottonchopper

Placing the Oauth access code into the sessionid does not seem to be working for me.  

 

I call the refresh to get a newer access code in case it has expired, then I am able to use that access code to perform a REST command, but when I attempt to set the access code as the SessionID for the APEX API, the web service seems to be returning a login page to the program through the web service.  Which causes a failure since the returned type of 'text/html' is not the expected return type of 'text/xml' as defined by the WSDL.

 

Am I missing something else that must be set in the APEX API to use the OAuth access?

 

Thanks,

 

Darrell

cottonchoppercottonchopper

I think I figured something out.  I think the problem I am running into is determining the URL to set the Binding to.  When calling the login command, the URL for the web service request is returned.  But when calling login, there is a different value returned for use in api calls.  If I do not call login, I get an error stating that the URL has not been reset by value from login.  If I set the URL to the instance_url from the OAuth calls, it goes to the login page.

 

How do I determine the URL to set the SForceService.URL value to?

 

Thanks,

 

Darrell

forecast_is_cloudyforecast_is_cloudy

Darrell - How exactly are you doing the OAuth 2.0 login and getting back the access token? Is it via the steps detailed here - http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_guidelines_yourtools.htm?

cottonchoppercottonchopper

The procedure laid out there is for OAuth 1.0 from what I understand about OAuth.  Except for the last 4 lines on the page which state that OAuth2.0 returns an access token and to use that with APEX I am redirected to the same document which doesn't have any information in it for what I want.

 

Here is the process I am folloing now.  With OAuth 2.0, I make a request to the AuthorizationURL https://test.salesforce.com/services/oauth2/authorize passing in response_type=code&client_id=[consumer_key]&redirect_uri=[callbackurl]

 

Then I get prompted for a login to the system to grant access.  Then the login calls back to my app through the callbackurl I provided and passes in a code.  I use that code and make different call to salesforce, this time to the TokenURL

https://test.salesforce.com/services/oauth2/token where I pass in code=[code from previous call]&grant_type=authorization_code&client_id=[consumer_key]&client_secret=[consumer_secret]&redirect_uri=[callbackuri]

 

The above part is just a one time thing.  I only will get prompted for inputing my user name and password if I call to the AuthorizationURL.  

 

That will return to me an access token, id, issued time, refresh token (to be used to request different access tokens in the future when the current one expires), an instance url (containing just the host name for the system) and a signature.

 

From there I am able to use the access token to make REST calls.  For APEX calls, I set the sessionheaderid to the access token.  I get an error about the URL needing to be reset to the value returned from login.  If I set the URL to the instance url returned from the Token URL call, the webservice gets redirected to the login page or in my case (https://cs8.salesforce.com), so the APEX will throw and error.

 

At this point I need to be able to programmatically determine the correct url to set the url in the web service to.

 

Thanks,

 

Darrell

chuckmortimorechuckmortimore

What URL are you using for the SOAP API?

 

cottonchoppercottonchopper

That is what I am trying to discover now.  At first I was using the default what was defined in the WSDL, but of course that isn't correct since that URL is only for the login process.  The login() would return the APEX API URL, but I am attempting to use OAuth 2.0.  I tried to just set the URL to the https://cs8.salesforce.com/.  That is the value returned from the call to the tokenURL.  That doesn't work as it tries to send the webservice to that page, which is a login page.

 

I could just run the login() and copy down the url it returns and hardcode that value my url, but there has to be a way to discover that programmatically or have that returned in the OAuth call or something.

 

We have to create interfaces to two separate instances of SalesForce, so hard coding isn't a long term solution for that.

 

Thanks,

 

Darrell

chuckmortimorechuckmortimore

Gotta.

 

So - the instance URL isn't the SOAP endpoint...it's just the server.  You need the full path to the SOAP endpoint you want to call.

 

One way we tried to make this easier for our OAuth users is the Identity URL we return from OAuth.   If you look at an Token Response, it includes a param called "id"   This is both an identifier for the user, as well as a RESTful webservice you can call using the access token for security.   If you pass in a version param of latest, you'll find the response contains full details on the URLs the user can access 

 

 

Here’s a token reponse ( notice this example uses My Domains, but it could also be an instance )


{
    "id": "https://login.salesforce.com/id/00D300000000mlxEAA/00530000000gKV8AAM",
    "issued_at": "1300730610265",
    "refresh_token": "5Aep8619juAXTkx27YveXtAeOkMhMVDoqj8bwg4Qe.vINxLWYjecO0CwJO_wccJZMNw7C1dfsFh2Q==",
    "instance_url": "https://cmort-developer-edition.my.salesforce.com",
    "signature": "sAzUka718JJK1KrP3ppz2/7W48K7XhQZPp4gbTCHIbY=",
    "access_token": "00D300000000mlx!AQoAQLszu53SID43zS24o89_njfAX70k1WBWRCMmo6TRSdgIuzkbOX2iC5qPw3t4tY2hFI4ZPxlAYidnSXISFu5puPO.liXs"
}

You can look up info on the user with the "id" that is passed back like this, and get their info and urls

{
    "id": "https://login.salesforce.com/id/00D300000000mlxEAA/00530000000gKV8AAM",
    "asserted_user": true,
    "user_id": "00530000000gKV8AAM",
    "organization_id": "00D300000000mlxEAA",
    "username": "charliemortimore@gmail.com",
    "nick_name": "cmort",
    "display_name": "Chuck Mortimore",
    "email": "charliemortimore@gmail.com",
    "status": {
        "created_date": "2011-01-21T23:13:51.000+0000",
        "body": "Does this work?"
    },
    "photos": {
        "picture": "https://cmort-developer-edition--c.na2.content.force.com/profilephoto/729400000004CAV/F",
        "thumbnail": "https://cmort-developer-edition--c.na2.content.force.com/profilephoto/729400000004CAV/T"
    },
    "urls": {
        "enterprise": "https://cmort-developer-edition.my.salesforce.com/services/Soap/c/21.0/00D300000000mlx",
        "metadata": "https://cmort-developer-edition.my.salesforce.com/services/Soap/m/21.0/00D300000000mlx",
        "partner": "https://cmort-developer-edition.my.salesforce.com/services/Soap/u/21.0/00D300000000mlx",
        "rest": "https://cmort-developer-edition.my.salesforce.com/services/data/v21.0/",
        "sobjects": "https://cmort-developer-edition.my.salesforce.com/services/data/v21.0/sobjects/",
        "search": "https://cmort-developer-edition.my.salesforce.com/services/data/v21.0/search/",
        "query": "https://cmort-developer-edition.my.salesforce.com/services/data/v21.0/query/",
        "recent": "https://cmort-developer-edition.my.salesforce.com/services/data/v21.0/recent/",
        "profile": "https://cmort-developer-edition.my.salesforce.com/00530000000gKV8AAM",
        "custom_domain": "https://cmort-developer-edition.my.salesforce.com"
    },
    "active": true,
    "user_type": "STANDARD",
    "language": "en_US",
    "locale": "en_US",
    "utcOffset": -28800000,
    "last_modified_date": "2011-02-18T22:36:16.000+0000"
}

 

 

ziltoidziltoid

"So - the instance URL isn't the SOAP endpoint...it's just the server.  You need the full path to the SOAP endpoint you want to call."

 

So how does one determine the SOAP endpoint given the token response?  The example you provided (and the one in the docs at http://wiki.developerforce.com/index.php/Digging_Deeper_into_OAuth_2.0_at_Salesforce.com ) seem to be for REST, not for SOAP.

chuckmortimorechuckmortimore

If you look at my example, you'll see you can call the Identity URL.   This will contain a list of URLs of API endpoints you can talk to.   urls.enterprise and urls.partner are the two SOAP APIs.   You of course can construct these URLs manually and use the instance URL as the host.