-
Notifications
You must be signed in to change notification settings - Fork 41
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
[Android] expiration date mismatch #286
Comments
Hi @o-artebiakin, thanks for raising this. @poovamraj could you please take a look? |
@o-artebiakin The Hope this answers your question. Please feel free to comment here and we can reopen this issue if you have more doubts. |
@poovamraj
Reproduction
|
PS: I noticed that the dates also differ slightly in iOS, but it's insignificant and doesn't cause any communication issues with the backend.
|
The ID Tokens are supposed to be much shorter lived than the access token. Can you show me how you are decoding the ID token in Android vs how you decode it in iOS? Also can you let us know the timezone in both the devices/emulators you are using? |
@poovamraj Example code where I compare results: class Auth0Service {
final Auth0 _auth0Client = Auth0(
'auth0Domain',
Platform.isIOS ? 'auth0ClientIdIOS' : 'auth0ClientIdAndroid',
);
Future<void> getCredentials() async {
try {
final credential = await _auth0Client.credentialsManager.credentials();
final decodedIdToken = JwtDecoder.decode(credential.idToken);
final decodedAccessToken = JwtDecoder.decode(credential.accessToken);
final credentialExpiration = credential.expiresAt.toUtc();
final idTokenExpiration = DateTime.fromMillisecondsSinceEpoch(
(decodedIdToken['exp'] as int) * 1000,
).toUtc();
final accessTokenExpiration = DateTime.fromMillisecondsSinceEpoch(
(decodedAccessToken['exp'] as int) * 1000,
).toUtc();
debugPrint('''
Credential Expiration: $credentialExpiration
Decoded Token Expiration(idToken): $idTokenExpiration
Decoded Token Expiration(accessToken): $accessTokenExpiration
''');
} catch (e) {
debugPrint(e.toString());
}
}
} Response(Android):
Response(iOS):
On the backend side, we use the standard Timezone:GMT+03.00 (EEST) If I change the timezone on an android emulator, for example, to: GMT-04.00(EDT)
Response(iOS):
|
@o-artebiakin From the code you shared looks like you are just getting a string value back from our SDK and parsing it using a seperate plugin. As you can see here
The string value is returned to you and how you parse it is left to you. The error you are mentioning looks like it happens in how the jwt_decoder plugin handles it. What I would suggest is to use the If parsing is still mandatory, the error is in how it is parsed, as the SDK just returns a string value and doesn't handle the parsing logic. If you print the exact value without parsing, it would work for you. |
Also, looks like you have different client id for Android and iOS. Which means your backend configuration could be different and this could lead expiration time being different. i would suggest you to check that out as well |
@poovamraj class Auth0Service {
final Auth0 _auth0Client = Auth0(
'auth0Domain',
// Remove iOS
'auth0ClientIdAndroid',
);
Future<void> getCredentials() async {
try {
final credential = await _auth0Client.credentialsManager.credentials();
final decodedIdToken = JwtDecoder.decode(credential.idToken);
final decodedAccessToken = JwtDecoder.decode(credential.accessToken);
final credentialExpiration = credential.expiresAt.toUtc();
final idTokenExpiration = DateTime.fromMillisecondsSinceEpoch(
(decodedIdToken['exp'] as int) * 1000,
).toUtc();
final accessTokenExpiration = DateTime.fromMillisecondsSinceEpoch(
(decodedAccessToken['exp'] as int) * 1000,
).toUtc();
debugPrint('''
Credential Expiration: $credentialExpiration
Decoded Token Expiration(idToken): $idTokenExpiration
Decoded Token Expiration(accessToken): $accessTokenExpiration
''');
} catch (e) {
debugPrint(e.toString());
}
}
} Response:
The application settings are standard. I believe that this method of verification is correct, because after 3 hours, when the CredentialsManager finally updates the token, the backend recognizes this key as valid. |
@o-artebiakin thanks for these details. Can you also share the snippet on how you are doing the verification on the backend. With this I can fully reproduce the end to end working. Also you response is that the |
Code snippet: /**
* Auth0 token validation middleware
*/
import { NextFunction, Request, Response } from 'express';
import { auth, JWTPayload } from 'express-oauth2-jwt-bearer';
import { logger } from 'firebase-functions';
import { UnauthorizedError } from '../../error-classes';
import { decodeTokenBody, getAuth0Config, getTokenFromHeader, isValidIssuer } from '../jwt-utils';
export function verifyAuth0Jwt(req: Request, res: Response, next: NextFunction): void {
const token = getTokenFromHeader(req.headers);
if (!token) {
return next(new UnauthorizedError('No token'));
}
let tokenBody: JWTPayload;
try {
tokenBody = decodeTokenBody(token);
} catch (e) {
logger.warn((e as Error).message);
return next(new UnauthorizedError('Bad token format'));
}
const auth0Config = getAuth0Config(tokenBody);
const issuer = tokenBody.iss!;
if (!isValidIssuer(auth0Config, issuer)) {
return next(new UnauthorizedError('Unknown issuer'));
}
const authHandler = auth({
audience: auth0Config.audience,
issuer,
jwksUri: `${issuer}.well-known/jwks.json`
});
return authHandler(req, res, next);
}
|
Hi @o-artebiakin as you can see the access token is not manipulated anywhere. We just send the value returned from the backend. It cannot be done in SDK as well as it is a jWT and you are just sending that value. Your backend code seems fine but I would suggest you check whether you are using the same client id for both iOS and Android and getting same result. You can post this code to our express-auth2-bearer where you can get more help on this. |
Hi @poovamraj and thanks for your support. |
@o-artebiakin The credential manager checks the |
@poovamraj If my method of checking the date through parsing the |
@o-artebiakin when you mention
You mean the access token? Refresh token is the only other information that is checked and looks like you have disabled it from the configuration you shared earlier. |
We will close this issue now. Let us know if you have more doubts and we can reopen it |
Hi. We are experiencing time differences in access token expiration dates given by
We are comparing |
@poovamraj any updates on that one ? On Android those methods are working incorrect |
@poovamraj could you please take a look? |
@aprzedecki @marcellplentific @o-artebiakin We were able to figure out this issue, thanks to @aprzedecki. As mentioned it is the use of UTC that caused this issue We have create a PR fixing this and explaining the issue - #315 Please have a look and let us know |
Yes, this looks good 👌 |
Edit: Didn't realize that the expiration was calculated when storing the token. The PR looks good then. The PR doesn't solve the problem for me, when referencing the branch in my project. |
@joymyr Can you check whether the issue you mention is in reference to the one mentioned here - auth0/Auth0.Android#695 |
@poovamraj based on my tests, setting the timezone to New York, or any timezone behind UTC should only result in refreshing the token too early. So this seems odd. |
The library compares: |
@poovamraj Yes. Just waiting for the fix to be published, but I have tested it directly from Git |
The fix is now out in v1.3.0. |
Checklist
Description
Credentials Manager for the Android app is returning an invalid expiration time. The credentialsManager.credentials() method is returning a Credentials object, but the expiresAt field does not match the expiration date provided in the idToken. This mismatch is causing the token to be invalidated on the server.
This issue does not occur on iOS, as it is working correctly.
Reproduction
Auth0().credentialsManager.credentials()
.expiresAt
field with the expiration date parsed from theidToken
.Additional context
No response
auth0_flutter version
1.2.1
Flutter version
3.10.4
Platform
Android
Platform version(s)
No response
The text was updated successfully, but these errors were encountered: