question

Jeff Craig avatar image
Jeff Craig asked Jeff Craig commented

Getting OAU-213 Error When Using Newly Generated Token

I'm having an issue where I authorize through the C# SDK, serialize that token to a database and then on subsequent calls, deseserialize it and try to use it and immediately get an OAU-213 Token Not Found Error. We want to forward phone calls on a dynamic basis so in the code below I instantiate a RestClient and then check to see if I have a token I can use, if I do, I then set it as the RestClient's token and make an API to forward the call. Whenever I use the token generated by calling rc.Authorize() my code works correctly, but if I store it to the database and then use the exact same token, I get the error down below. Any help would be appreciated.


Thanks!


public async Task<bool> ForwardPhoneCall(string userName, string firmId, string telephonySessionId, string partyId)
        {
            var phoneNumber = await _UserRepo.GetMainPhoneNumberFromUserName(userName, firmId);

            if (phoneNumber != null)
            {
                RingCentralCredentials creds = await GetRingCentralCredentials(firmId);

                ForwardTarget forwardTarget = new ForwardTarget() { phoneNumber = phoneNumber.FormatPhoneNoSpaces() };

                using (var rc = new RestClient(creds.clientID, creds.clientSecret, creds.serverURL))
                {
                    rc.token = await Authorize(creds, rc, firmId);
                    await rc.Restapi().Account().Telephony().Sessions(telephonySessionId).Parties(partyId).Forward().Post(forwardTarget);

                    return true;
                }
            }

            return false;
        }
 private async Task<RingCentral.TokenInfo> Authorize(RingCentralCredentials creds, RestClient rc, string firmId)
        {
            RingCentral.TokenInfo token;
            var currentTime = DateTimeOffset.Now.ToUnixTimeSeconds();

            if (creds?.tokenExpiration == null || string.IsNullOrEmpty(creds?.currentToken) || creds.tokenExpiration < currentTime)
            {
                token = await rc.Authorize(creds.username, creds.extension, creds.password);

                creds.currentToken = JsonConvert.SerializeObject(token);
                creds.tokenExpiration = DateTimeOffset.Now.ToUnixTimeSeconds() + token.expires_in - 300;

                await SaveRingCentralCredentials(firmId, creds);
            }
            else
            {
                token = JsonConvert.DeserializeObject<RingCentral.TokenInfo>(creds.currentToken);
            }

            return token;
        }


Here's the response:

RingCentral.RestException: Response:

StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:

{

Server: nginx

Date: Fri, 13 Dec 2019 17:54:41 GMT

Connection: keep-alive

X-Rate-Limit-Group: light

X-Rate-Limit-Limit: 50

X-Rate-Limit-Remaining: 49

X-Rate-Limit-Window: 60

WWW-Authenticate: Bearer realm="RingCentral REST API", error="OAU-213", error_description="Token not found"

RoutingKey: SJC12P01

RCRequestId: a3749b4e-1dd1-11ea-8694-005056bbcdd9

Content-Type: application/json

Content-Length: 154

Content-Language: en

}

Content: {

"errorCode" : "TokenInvalid",

"message" : "Token not found",

"errors" : [ {

"errorCode" : "OAU-213",

"message" : "Token not found"

} ]

}


sdk
1 comment
1 |3000

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

Phong Vu avatar image Phong Vu ♦♦ commented ·

1. Can you print the tokens right after you called rc.Authorize() successfully, and print the tokens you restored from your database. Just to make sure they are the same.

2. How long time did you make a consecutive calls using the saved tokens? Did you have other apps authorized between that period of time?

0 Likes 0 ·
Phong Vu avatar image
Phong Vu answered Jeff Craig commented

I think this is the root cause of your problem.

using (var rc = new RestClient(creds.clientID, creds.clientSecret, creds.serverURL))
{
  rc.token = await Authorize(creds, rc, firmId);
  await rc.Restapi().Account().Telephony().Sessions(telephonySessionId).Parties(partyId).Forward().Post(forwardTarget);
 
  return true;
}

You authorize your app inside the "using" brackets, and when your code exists, the object is disposed and the token will be revoked by the SDK

public async void Dispose()
        {
            await Revoke();
        }

Try avoid the "using" will solve the problem.

1 comment
1 |3000

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

Jeff Craig avatar image Jeff Craig commented ·

That was it. Thank you so much!

0 Likes 0 ·
Jeff Craig avatar image
Jeff Craig answered

yes, I printed both tokens and they are exactly the same and I can make calls within seconds of each other and the second one that reads the token from the database always fails.

I do use this same app for notifications, i.e. the AccountTelephony and Extension Telephony webhooks, but dont make any calls to the OAuth endpoint except to forward the phone. I noticed in my analytics that I have a bunch of calls to the revoke endpoint but never call that myself.

Here's my endpoint for the AccountTelephony webhook

        [Route("ringCentral/{firmId}")]
        [HttpPost]
        public async Task<ActionResult> GetAccountTelephony(string firmId)
        {
            _Logger.LogInformation("Starting Account Telephony");

            HttpContext.Request.Headers.TryGetValue("Validation-Token", out StringValues validationToken);
            HttpContext.Response.Headers.Add("Validation-Token", validationToken);

            _Logger.LogInformation("Got Account Telephony Validation Token");

            using (StreamReader reader = new StreamReader(HttpContext.Request.Body, Encoding.UTF8))
            {
                var requestBody = await reader.ReadToEndAsync();
                .
                .
                .
                return Ok();
            }
        }


Endpoints called by this app in past 24 hours:


1576265556481.png (49.3 KiB)
1 |3000

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

Developer sandbox tools

Using the RingCentral Phone for Desktop, you can dial or receive test calls, send and receive test SMS or Fax messages in your sandbox environment.

Download RingCentral Phone for Desktop:

Tip: switch to the "sandbox mode" before logging in the app:

  • On MacOS: press "fn + command + f2" keys
  • On Windows: press "Ctrl + F2" keys