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"
} ]
}
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.
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:
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