question

todd125 avatar image
todd125 asked ·

Anyone have any C# sample code to authenicate to the API and make some requests?

Not sure how to do Oauth2 authentication to a web API in C#. If anyone has done so already, could please share some sample code, so I don't have to re-invent the wheel.
apic#oauth2authc sharp
1 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

benjamin-dean avatar image
benjamin-dean answered ·
Hey Todd,

There is an unofficial C# SDK available here which might be of help:  https://github.com/grokify/ringcentral-sdk-csharp-simple

There are examples for just obtaining the RingCentral SDK Client, and a simple example for sending an SMS message once you've authenticated.
10 comments Share
1 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

All we want to do is download incoming faxes. Can we use the SDK to accomplish this, or do we need to use a regular HttpWebRequest?

Thank you for you help!


0 Likes 0 · ·
You can use either the SDK, or a standard REST API request directly.
0 Likes 0 · ·
So, I was thinking we could use the standard REST API request directly. Which is why I asked if anyone has any sample code to authenticate. Sending and receiving JSON is pretty simple. They only tricky part is authenticating.

Do you have any code sample for how to do the authentication? Or do you suggest I just try to use the SDK?
0 Likes 0 · ·
Have you tried ripping the authentication code out of the community C# SDK?
0 Likes 0 · ·
No, I looked for the authentication code but could not find it.  It was calling the SDK. I found this but it was calling the SKD.

public Client(string appKey, string appSecret, string serverUrl) { Sdk = new RingCentral.SDK.SDK(appKey, appSecret, serverUrl); }

So where is the code in the SDK that does the authentication? That's all I need.


0 Likes 0 · ·
Show more comments
todd125 avatar image
todd125 answered ·
I downloaded the sample project from the link you provided me and when I run the code it says "Access Expired". Please advise. Thank you for all your help.
Share
1 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

vb avatar image
vb answered ·
Can you share the Response Message ? And what is the HTTP status code? 
9 comments Share
1 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

I tried following the tutorial first. https://developer.ringcentral.com/library/tutorials/get-started.html  Cause if I can make it work in the browser I should be able to replicate that in code.

The post is to https://platform.devtest.ringcentral.com/restapi/oauth/token

The response is.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><errorEntity><error>invalid_grant</error><error_description>Invalid resource owner credentials.</error_description></errorEntity>

I was using 12154223514 as the username. I don't want to put the password here, but it is the same user name and password I use to log in to developer.ringcentral.com.

Should I be using a different username and password? We aren't going to have a user, it will just be running from our server.

Thanks for your help.









0 Likes 0 · ·
Here are the headers...


Host: platform.devtest.ringcentral.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Authorization: Basic WnZYMG94YVlRbW1JcWVVd3FYWWZBZzo2MVhNblh3N1JaR3ItbXRzZjZLMDh3b2VNbWJ4V25TZ21UZjlCcl9aVWZvZw==
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 60
Cookie: _ga=GA1.2.1582640206.1445977993; RCRoutingInfo=B:JjvG963zMhLp2i9ovcWFNByPb5vRnRQA539tb0pH+XWHl8qMEhGXRFDcYy5wxzWX
Connection: keep-alive
Proxy-Authorization: Negotiate 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

0 Likes 0 · ·
Did you follow the documentation for obtaining the access token?

I think you're receiving the "Invalid Grant" and "Invalid Resource Owner Credentials" because you might not be using the proper values or URI in your POST request for the access token.

  1. To use the RingCentral API, an access and refresh token are needed. The simplest way to get an access token needed for production resources is to complete Two-legged Authorization Flow (OAuth 2.0). The required fields are below:

    • ApplicationKey  granted after successful application/developer registration. Required.

    • ApplicationSecret  granted after successful application/developer registration. Required.

    • UserName  main company number of a RingCentral account or direct extension phone number (unformatted, sequence of digits starting with country code). Required.

    • Extension  extension number to log into for the RingCentral account. Required if main company number is provided as a UserName.

    • Password  for the RingCentral account. Required.


  2. Once you have the ApplicationKey and ApplicationSecret for your app (You obtain these raw values from your application definition page available by selecting your application from the list of your defined apps here: https://developers.ringcentral.com/my-account.html#/applications ), you must Base64 encode them to be used in the request for an access/refresh token. A free tool is available at http://www.base64encode.org.

    In C# you can also create a method to encode base64 values:

     public static string Base64Encode(string plainText) {   var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);   return System.Convert.ToBase64String(plainTextBytes); }

  3. Once you have the payload data to obtain an access token, you'll want to create an HTTP POST request to: https://platform.devtest.ringcentral.com/restapi/oauth/token (notice this URI is for your Sandbox environment, for a production environment just remove "devtest." from the URI).

     //Be sure to run "Install-Package Newtonsoft.Json -Version 7.0.1" from your nuget command line. //Be sure to run "Install-Package System.Net.Http -Version 4.0.0" from your nuget command line.  HttpClient client = new HttpClient();  client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", "BASE64 ENCODED APPKEY:APPSECRET");<br> FormUrlEncodedContent form = new FormUrlEncodedContent(new Dictionary { { "username", "username" }, { "password", "password" }, { "grant_type": "password" }, { "extension": "extension" } } );  Task message = client.PostAsync( "https://platform.devtest.ringcentral.com/restapi/oauth/token", form ); String result = message.Result.Content.ReadAsStringAsync().Result;  JObject RCAuth = JObject.Parse( result ); string token = ( string )RCAuth["access_token"] string refreshToken = ( string )RCAuth["refresh_token"]; string tokenExpires = ( string )RCAuth["access_token_expires_in"]; string refreshTokenExpires = ( string )RCAuth["refresh_token_expires_in"]; 

  4. That should get you to the point you're able to begin making calls. You will want to use this token until around 80% of the expiration time, then you'll want to use the refresh token to request a new access and refresh token.
Let me know if this doesn't work for you, or if you hit snags.
0 Likes 0 · ·
Awesome! Thanks! I am working on other stuff, but I'll get to this sometime soon. I'll probably try it out from home first to rule out any corporate firewall issues. I'll let you know how it goes.
0 Likes 0 · ·
What should I be using for extension?
0 Likes 0 · ·
Show more comments
todd125 avatar image
todd125 answered ·
Today I finally got the answer my original question. The code snippet below.


    public class Worker
    {
        private static string Base64Encode(string plainText)
        {
            var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
            return System.Convert.ToBase64String(plainTextBytes);
        }

        private string _accessToken;
       
       public async void WaitForAuthToken()
        {
            using (var client = new HttpClient())
            {
                var request = new HttpRequestMessage()
                {
                    RequestUri = new System.Uri($"{Settings.ServerUrl}restapi/oauth/token"),
                    Method = HttpMethod.Post,
                };
                 request.Headers.TryAddWithoutValidation("Content-Type", @"application/x-www-form-urlencoded;charset=UTF-8");
                request.Headers.Add("Authorization", $"Basic {Base64Encode($"{Settings.AppKey}:{Settings.AppSecret}")}"); 
                request.Content = new FormUrlEncodedContent(new[] {
                new KeyValuePair<string, string>("grant_type", "password"),
                new KeyValuePair<string, string>("username", Settings.PhoneNumber),
                new KeyValuePair<string, string>("password", Settings.Password),
                new KeyValuePair<string, string>("extension", Settings.Extension)
            });

                var response = await client.SendAsync(request);
                var responseContent = await response.Content.ReadAsStringAsync();
                var d = (dynamic) Newtonsoft.Json.JsonConvert.DeserializeObject(responseContent);
                _accessToken = d.access_token;
            }
        }
    }




Simple really.
Share
1 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

benjamin-dean avatar image
benjamin-dean answered ·
Thanks for sharing this Todd...great help.

Love seeing the use of async in there that makes a ton of sense in addition to setting this up as a worker.
Share
1 |1000 characters needed characters left characters exceeded

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 10 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.