-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUG] AccessTokenInvalid for valid tokens #110
Comments
Hi @luddd3 , Twilio Developer Educator here. How are you updating the clients' AccessTokens when their internet is flaky? |
When a client reconnects, it sends a login-request to our back-end. The back-end generates a new token and calls device.updateToken() with the new token. If the device is in state 'unregistered', device.register() is called. I have tested extensively during the day and can get AccessTokenInvalid regardless of any drifting clock. This is my minimally reproducible code: import { Call, Device } from '@twilio/voice-sdk'
async function getToken(): Promise<string> {
// fetch and return new valid token
}
const setupTwilio = (token): void => {
const device = new Device(token, {
edge: ['frankfurt', 'dublin', 'roaming'],
logLevel: 1,
codecPreferences: ['opus' as Call.Codec, 'pcmu' as Call.Codec],
tokenRefreshMs: 40_000, // refresh 40 seconds before token expires, default is 10 seconds
maxCallSignalingTimeoutMs: 25_000, // this opts in to Call reconnection instead of using only basic media reconnection
})
const updateToken = async () => {
try {
const token = await getToken()
device.updateToken(token)
if (device.state === 'unregistered') {
await device.register()
}
} catch (err) {
console.error(err.stack)
}
}
device.on('error', function (err) {
console.log('error', err)
const code = err.code
// Access token errors
if (code >= 20101 && code <= 20160) {
updateToken()
}
})
device.on('tokenWillExpire', () => {
updateToken()
})
device.on('registered', () => {
console.log('registered!')
})
device.register()
}
async function main() {
const token = await getToken()
setupTwilio(token)
}
main() I have tested the above code by:
The above sequence will produce AccessTokenInvalid errors even though all tokens we generate are valid for 4 hours. |
@mhuynh5757 Any insights here? |
Hey everyone, apologies for the late response. Can you please provide all the logs you see from the browser console, along with all the websocket messages (similar to what @ostap0207 posted, but all)? |
Hi @charliesantos I tried to include everything you asked for in "example" in the zip-file, but I just took screenshots of the websocket-traffic since I didn't find any easy way to save it in my current browser (Firefox). |
We are facing the exact same problem! |
Apologies for the delay. We are looking at it and still haven't found the root cause. Please bear with us in the meantime. |
I'm observing the same issue. When my PC goes in a suspended mode (i have 10 minutes timeout) and wakes up, there is a bunch of errors including AccessTokenInvalid in the log. |
Based on my logs to me this looked like a race condition between |
Hey everyone, sorry for the late response. We're able to reproduce the issue and found the root cause. However, the fix is not pretty straightforward and might require some more thoughts on how we design the ideal solution. Basically, as you guys have observed, this is a race condition between listen and register signaling messages. As a workaround in the meantime, can you please try either of the following?
OR
Please let me know your thoughts |
I encountered this error specifically when handling incoming calls. Based on my experience, it was related to the identity parameter used while generating the access token. For example, consider a scenario where we request a token with the identity set as public static function get_access_token($identity)
{
self::__initiate();
$accessToken = new AccessToken(
static::$sid,
static::$apiKey,
static::$apiSecret,
3600,
$identity
);
$voiceGrant = new VoiceGrant();
$voiceGrant->setOutgoingApplicationSid(static::$twimlSid);
$voiceGrant->setIncomingAllow(true);
$accessToken->addGrant($voiceGrant);
$token = $accessToken->toJWT();
return ['token' => $token, 'identity' => $identity];
}
// issue token
self::get_access_token('Banana') If an incoming call is made to the client, and the identity in the request callback does not match one of the issued identities public static function get_voice_response($contact, $identity = null)
{
self::__initiate();
$response = new VoiceResponse();
if ($contact == self::$callerId) {
// If identity does not match 'Banana', the token will be invalid
$dial = $response->dial('');
$dial->client($identity);
} else {
if (strlen($contact) < 10) {
return $response->say('Invalid phone number');
}
$dial = $response->dial('', ['callerId' => static::$callerId]);
if (preg_match("/^[\d\+\-\(\) ]+$/", $contact)) {
$dial->number($contact);
} else {
$dial->client($contact);
}
}
return $response;
} |
or sensitive account information (API keys, credentials, etc.) when reporting this issue.
I have a problem with some clients getting AccessTokenInvalid (20101) for perfectly valid tokens. The only thing I have found is that sometimes the clients have drifting clocks. E.g. a client clock is set to 2022-08-30T09:51:41.000Z and tries to use the following token (most fields redacted):
According to the client clock, the access token is not yet valid. Our servers sent the token to the client approximately 2022-08-30T09:53:57.995Z
A long shot, but is there any kind of limit on the number of AccessTokens for a specific client? This client had flaky internet and I created several new tokens for it.
Software versions:
The text was updated successfully, but these errors were encountered: