• ward
  • NEWBIE
  • 0 Points
  • Member since 2013

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 1
    Questions
  • 2
    Replies

I implemented Oauth 2.0 means using WebClient in C# to send GET and POST messages directly to Salesforce.

 

For those unfamilar with Oauth, maybe seeing my code samples will help them if I outline the steps in c# type syntax.

Maybe someone who know's a lot about configuring Salesforce will be able to tell me if they see something I'm doing wrong, at least I hope...

 

String oauth_scope = "refresh_token api full chatter_api id";

 

String url = String.Format( "{0}?client_id={1}&redirect_uri={2}&response_type=code&scope={3}", "https://login.salesforce.com/services/oauth2/authorize?", _consumerKey_web_app, nextanalytics.MyString.UrlEncode( SALESFORCE_REDIRECTS_TO_THIS_URL_AFTER_URL_AUTH ), nextanalytics.MyString.UrlEncode( oauth_scope ) ); HttpWebRequest myRequest = (HttpWebRequest) WebRequest.Create( url );;

 

 

 

This comes back fine. I get back a URL to my embedded browser with a code=VALUE on it.

I POST a response back to salesforce (again using WebClient.

 

WebClient client = new WebClient();
#if ! MONO
client.Proxy.Credentials = CredentialCache.DefaultCredentials;
#endif
try
{
NameValueCollection values = new NameValueCollection();
values.Add( "client_id", _consumerKey_web_app );
values.Add( "client_secret", _consumerSecret_web_app_offline );
values.Add( "grant_type", "authorization_code" );
values.Add( "redirect_uri", SALESFORCE_REDIRECTS_TO_THIS_URL_AFTER_URL_AUTH );
values.Add( "code", authorization_code );
Byte[] responseBytes = client.UploadValues( URL_TOKEN_ENDPOINT_SECOND, values );
String errMsg = parse_result_from_token_endpoint( Encoding.UTF8.GetString( responseBytes ) );

 

The parse_result function is just something I wrote that does the following:

HandlerForJSON parsed = new HandlerForJSON();
System.Collections.Hashtable hashtable = (System.Collections.Hashtable) parsed.JsonDecode( response );
short_lived_access_token = (String) parsed.hashtable["access_token"];
refresh_token = (String) parsed.hashtable["refresh_token"];
instance_url = (String) parsed.hashtable["instance_url"]; 
issued_at_num_secs_since_unix_epoc = (String) parsed.hashtable["issued_at"];

 

All my values look correct.

The refresh_token seems correct, and so does the short_lived_access_token. The instance_url is used (by me) to build other method calls. For example, I can submit this:

 

String new_url = instance_url + "/services/data/" + "?access_token=xyz..."

 

I get back a nice json string that is an array of versions, as documented.

I pick the the last one in the array, thinking it's going to be the most recent version.

With this dynamic "version" information, I'm supposed to be able construct a web url that looks like this:

 

"https://na11.salesforce.com/services/data/v28.0/"

 

From what I understand, if I submit that, with an un-expired access_token, it should give me back my "Resources" which would hypothetically look like:

{
"sobjects" : "/services/data/v28.0/sobjects",
"search" : "/services/data/v28.0/search",
"query" : "/services/data/v28.0/query",
"recent" : "/services/data/v28.0/recent"
}

 

But my problem is that I always get back an error 401 Unauthorized unless it the first call to get the version(s) 

 

With OAuth, 401 is often the error you get when your access_token expires and it's time to use the refresh_token. But my problem is that the access_token had just been issued, and used a split second earlier, so expiry is not likely the problem.  

 

I suspect it's something more fundamental, something about the configuration. Basically, I don't understand why I can query the versions but it fails on the immediate next call to get the Resources.

 

At first, I thought to look carefully at the scope(s) I was using.

String oauth_scope = "refresh_token api full chatter_api id"; 

I've tried different combinations and nothing seems to help.

 

I've double checked, and those scopes do match what I chose for the "connected App" that I created on the server. 

 

I also wondered if there is some security setting I'm supposed to do in the User Setup, App Setup, or Administration Setup. When I look, I can't see anything...

 

I'm stuck on this. I'm sure you know the feeling. Anyone out there knows how to get a connectedApp that uses Oauth 2.0 to be able to issue GET calls to various methods, more than just getting which instance_url to use?

 

 

 

  • August 02, 2013
  • Like
  • 0

I implemented Oauth 2.0 means using WebClient in C# to send GET and POST messages directly to Salesforce.

 

For those unfamilar with Oauth, maybe seeing my code samples will help them if I outline the steps in c# type syntax.

Maybe someone who know's a lot about configuring Salesforce will be able to tell me if they see something I'm doing wrong, at least I hope...

 

String oauth_scope = "refresh_token api full chatter_api id";

 

String url = String.Format( "{0}?client_id={1}&redirect_uri={2}&response_type=code&scope={3}", "https://login.salesforce.com/services/oauth2/authorize?", _consumerKey_web_app, nextanalytics.MyString.UrlEncode( SALESFORCE_REDIRECTS_TO_THIS_URL_AFTER_URL_AUTH ), nextanalytics.MyString.UrlEncode( oauth_scope ) ); HttpWebRequest myRequest = (HttpWebRequest) WebRequest.Create( url );;

 

 

 

This comes back fine. I get back a URL to my embedded browser with a code=VALUE on it.

I POST a response back to salesforce (again using WebClient.

 

WebClient client = new WebClient();
#if ! MONO
client.Proxy.Credentials = CredentialCache.DefaultCredentials;
#endif
try
{
NameValueCollection values = new NameValueCollection();
values.Add( "client_id", _consumerKey_web_app );
values.Add( "client_secret", _consumerSecret_web_app_offline );
values.Add( "grant_type", "authorization_code" );
values.Add( "redirect_uri", SALESFORCE_REDIRECTS_TO_THIS_URL_AFTER_URL_AUTH );
values.Add( "code", authorization_code );
Byte[] responseBytes = client.UploadValues( URL_TOKEN_ENDPOINT_SECOND, values );
String errMsg = parse_result_from_token_endpoint( Encoding.UTF8.GetString( responseBytes ) );

 

The parse_result function is just something I wrote that does the following:

HandlerForJSON parsed = new HandlerForJSON();
System.Collections.Hashtable hashtable = (System.Collections.Hashtable) parsed.JsonDecode( response );
short_lived_access_token = (String) parsed.hashtable["access_token"];
refresh_token = (String) parsed.hashtable["refresh_token"];
instance_url = (String) parsed.hashtable["instance_url"]; 
issued_at_num_secs_since_unix_epoc = (String) parsed.hashtable["issued_at"];

 

All my values look correct.

The refresh_token seems correct, and so does the short_lived_access_token. The instance_url is used (by me) to build other method calls. For example, I can submit this:

 

String new_url = instance_url + "/services/data/" + "?access_token=xyz..."

 

I get back a nice json string that is an array of versions, as documented.

I pick the the last one in the array, thinking it's going to be the most recent version.

With this dynamic "version" information, I'm supposed to be able construct a web url that looks like this:

 

"https://na11.salesforce.com/services/data/v28.0/"

 

From what I understand, if I submit that, with an un-expired access_token, it should give me back my "Resources" which would hypothetically look like:

{
"sobjects" : "/services/data/v28.0/sobjects",
"search" : "/services/data/v28.0/search",
"query" : "/services/data/v28.0/query",
"recent" : "/services/data/v28.0/recent"
}

 

But my problem is that I always get back an error 401 Unauthorized unless it the first call to get the version(s) 

 

With OAuth, 401 is often the error you get when your access_token expires and it's time to use the refresh_token. But my problem is that the access_token had just been issued, and used a split second earlier, so expiry is not likely the problem.  

 

I suspect it's something more fundamental, something about the configuration. Basically, I don't understand why I can query the versions but it fails on the immediate next call to get the Resources.

 

At first, I thought to look carefully at the scope(s) I was using.

String oauth_scope = "refresh_token api full chatter_api id"; 

I've tried different combinations and nothing seems to help.

 

I've double checked, and those scopes do match what I chose for the "connected App" that I created on the server. 

 

I also wondered if there is some security setting I'm supposed to do in the User Setup, App Setup, or Administration Setup. When I look, I can't see anything...

 

I'm stuck on this. I'm sure you know the feeling. Anyone out there knows how to get a connectedApp that uses Oauth 2.0 to be able to issue GET calls to various methods, more than just getting which instance_url to use?

 

 

 

  • August 02, 2013
  • Like
  • 0