News & Announcements User Community Developer Community

Welcome to the RingCentral Community

Please note the community is currently under maintenance and is read-only.

Search
Make sure to review our Terms of Use and Community Guidelines.
  Please note the community is currently under maintenance and is read-only.
Home » Developers
Request for Token via JasonWebToken auth throws "unauthorized_client" error
Tags: errors
Sep 5, 2023 at 5:20pm   •   2 replies  •  0 likes
Tammy Wolski

I received an "End of Life" email from RingCentral about my "password-based auth" method of getting a token will no longer supported as of next March. I have been using this method of getting a token for a few years, so I know the code I am using is working correctly. The app my users use is a Windows .exe, built using the Lazarus IDE and the programming language FreePascal and the component I use is the Indy HTTP component. There is no SDK involved. To test my POST call, I use Postman along side my .exe just to eliminate the possibility that one or the other is coded/configured wrong. I have set up my POST request in Postman as explained in these instructions and I also changed the code in my own FreePascal app the same way. In both the Postman POST and my own Windows .exe, I get the exact same error message shown here:

{

"error": "unauthorized_client",

"errors": [

{

"errorCode": "OAU-251",

"message": "Unauthorized for this grant type"

}

],

"error_description": "Unauthorized for this grant type"

}

When making my JWT I chose "All apps from your organization"

I downloaded my production creds for this RingCentral production app into a JSON file. Here it is with the private info hidden:

{

"username": "+<HIDDEN>",

"password": "<YOUR ACCOUNT PASSWORD>",

"extension": "201",

"clientId": "<HIDDEN>",

"clientSecret": "<HIDDEN>",

"server": "https://platform.ringcentral.com",

"jwt": {

"RubiDialerJWT": "<HIDDEN>"

}

}

As you can see, the JWT was associated with this app, as I requested.

Here are the screen shots from my Postman attempt:

postman_sets.pdf

Here is the code I'm using in Lazarus:

procedure TfrmDialRC.GetTokenRCJasonWebToken;  
var
  htp: TIdHTTP;
  prms_stm: TStringStream;  s: String;
  tkn_ok: Boolean;
begin
  try
    htp := htpTkn;

    s := 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=' + GV.RingCentral.JWT;
    prms_stm := TStringStream.Create(s);

    if htp.Connected then
      htp.Request.Connection := 'close';
    htp.Request.Clear;

    htp.Request.Accept := 'application/json';
    htp.Request.ContentType := 'application/x-www-form-urlencoded';
    htp.Request.Username := GV.RingCentral.ClientID;
    htp.Request.Password := GV.RingCentral.ClientSecret;
    htp.Request.BasicAuthentication := True;

    htp.Post('https://platform.ringcentral.com/restapi/oauth/token', prms_stm);

  finally
    prms_stm.Free;
    htp.Request.Connection := 'close';
  end;

end;


Is there some other step that I have to take to make this work?

Thanks in advance for your help.



2 Answers
answered on Sep 8, 2023 at 4:31pm  

I was able to get the function to work, using the following code:

Reference: https://developers.ringcentral.com/guide/authentication/jwt-flow

procedure TfrmDialRC.GetTokenRCJasonWebToken; /

var

htp: TIdHTTP;

prms_stm: TStringStream;

s: String;

begin

// This works!

try

htp := htpTkn;


if htp.Connected then

htp.Request.Connection := 'close';

htp.Request.Clear;


s := 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=' + GV.RingCentral.JWT;

prms_stm := TStringStream.Create(s);

prms_stm.Position := 0;


htp.Request.Accept := 'application/json';

htp.Request.ContentType := 'application/x-www-form-urlencoded';


htp.Request.Username := GV.RingCentral.ClientID;

htp.Request.Password := GV.RingCentral.ClientSecret;

htp.Request.BasicAuthentication := True;


htp.Post( 'https://platform.ringcentral.com/restapi/oauth/token', prms_stm);


finally

prms_stm.Free;

htp.Request.Connection := 'close';

end;


end;







 0
answered on Sep 6, 2023 at 3:12pm  

I recommend you to submit a dev support ticket and someone can have a look at your app settings and help you out with postman API call too.


 1
answered on Sep 6, 2023 at 7:33am  

The function you implemented to use the JWT token is totally incorrect. Why do you still specify the user name and password? And I don't know how the Request.BasicAuthentication := True sets the Authorization header.

I don't have sample code in Python. But I have native code in PHP showing how to use the JWT token to exchange for access tokens.

private function authenticate(){
      $url = $_ENV["RC_SERVER_URL"] . "/restapi/oauth/token";
      $basic = $_ENV["RC_CLIENT_ID"] .":". $_ENV["RC_CLIENT_SECRET"];
      $headers = array (
              'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
              'Accept: application/json',
              'Authorization: Basic '.base64_encode($basic)
            );
      $body = http_build_query(array (
              'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
              'assertion' => $_ENV["JWT_TOKEN"]
            ));
      try {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_TIMEOUT, 600);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

        $strResponse = curl_exec($ch);
        $curlErrno = curl_errno($ch);
        if ($curlErrno) {
          throw new Exception($curlErrno);
        } else {
          $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          curl_close($ch);
          if ($httpCode == 200) {
            $date = new DateTime();
            $jsonObj = json_decode($strResponse);
            $tokensObj = array(
              "tokens" => $jsonObj,
              "timestamp" => $date->getTimestamp()
            );
            // Logged in successfully => Save tokens in session or write to file/database for reuse
            $_SESSION['sessionAccessToken'] =  json_encode($tokensObj, JSON_PRETTY_PRINT);
            return;
          }else{
            throw new Exception($strResponse);
          }
        }
      } catch (Exception $e) {
        throw $e;
      }
    }

You can get the entire project from here and convert the essential code to Python.


 0
on Sep 6, 2023 at 11:18am   •  0 likes

Hi Phong. Username and Password in my code, is equivalent to your line:

"RC_CLIENT_ID"] .":". $_ENV["RC_CLIENT_SECRET"];

I have to include that or I get an unknown client error message from the RingCentral server. It must be included. My Postman request is set up the same way, using Basic Auth and client ID (username) and Secret (password). Both Postman and my own Windows .exe result in the same error message: "message": "Unauthorized for this grant type"

I logged into my RingCentral account, located the production APP, went into it's Settings, then changed the "Auth" to "JWT auth flow", and clicked Submit.

I tried doing a RingOut, using Password Flow and the token was granted. (It shouldn't. It's supposed to fail, because the app is now supposed to only allow JST).

I then tried doing a RingOut using JWT as shown in my original post, and a token was not granted, and I got the same error message shown in my original post.

It seems there is something I'm supposed to do with the RingCentral APP to make this work. My request follows the instructions at

https://developers.ringcentral.com/guide/authentication/jwt-flow

Is there someone I can hire for the 20 or 30 minutes it would take to get this figured out? I need someone who can ensure my RingCentral APP and JWT is set up correctly, then, I need them to build a Postman request that works, that requests a token. From Postman, I should be able to translate into Freepascal's HTTP component.





A new Community is coming to RingCentral!

Posts are currently read-only as we transition into our new platform.

We thank you for your patience
during this downtime.

Try Workflow Builder

Did you know you can easily automate tasks like responding to SMS, team messages, and more? Plus it's included with RingCentral Video and RingEX plans!

Try RingCentral Workflow Builder

PRODUCTS
RingEX
Message
Video
Phone
OPEN ECOSYSTEM
Developer Platform
APIs
Integrated Apps
App Gallery
Developer support
Games and rewards

RESOURCES
Resource center
Blog
Product Releases
Accessibility
QUICK LINKS
App Download
RingCentral App login
Admin Portal Login
Contact Sales
© 1999-2024 RingCentral, Inc. All rights reserved. Legal Privacy Notice Site Map Contact Us