-
Notifications
You must be signed in to change notification settings - Fork 112
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
Returning empty token when the refresh method is called #128
Comments
Hi @Mubaola23, For example, you don't need to call Furthermore I don't understand why you are calling I'll try to review and comment your code below, let me know if I misunderstood anything... class MyOAuth2Client extends OAuth2Client {
MyOAuth2Client({required String redirectUri, required String customUriScheme})
: super(
authorizeUrl:
'https://$baseurl/connect/authorize', //Your service's authorization url
tokenUrl:
'https://$baseurl/connect/token', //Your service access token url
redirectUri: redirectUri,
revokeUrl: "https://$baseurl/connect/revocation",
customUriScheme: customUriScheme);
}
class MyHelper {
OAuth2Client getClient() {
var client;
client = MyOAuth2Client(
redirectUri: REDIRECT_URL,
customUriScheme: CUSTOM_SCHEME,
);
return client;
}
FlutterSecureStorage _storage = FlutterSecureStorage();
Future authorize() async {
try {
var client = getClient();
await _storage.deleteAll();
if (client != null) {
// ###No harm here, but you already have the client instantiated, you should pass it to the helper...###
//var hlp = toPerformRequest(getClient());
var hlp = toPerformRequest(client);
// ### No need to disconnect and retrieving the token.... ###
/*
await hlp.disconnect();
var result = await hlp.getToken().catchError((onError) async {
await hlp.disconnect();
print("error $onError");
});
*/
Response user = await hlp.get(USER_INFO);
UserInfo userinfo = UserInfo.fromJson(jsonDecode(user.body));
await _storage.write(key: "email", value: userinfo.email);
await _storage.write(key: "userID", value: userinfo.userID);
await _storage.write(key: "id", value: userinfo.sub);
await _storage.write(key: "name", value: userinfo.givenName);
await _storage.write(key: "tenantId", value: userinfo.tenantId);
}
} catch (ex) {
throw (ex.toString());
}
}
OAuth2Helper toPerformRequest(OAuth2Client client) {
String clientId = CLIENT_ID;
String clientSecret = CLIENT_SECRET;
var hlp = OAuth2Helper(client,
clientId: clientId,
clientSecret: clientSecret,
scopes: ['openid', 'profile', 'offline_access']);
return hlp;
}
logout() async {
/*
String clientId = CLIENT_ID;
String clientSecret = CLIENT_SECRET;
var hlp = OAuth2Helper(getClient(),
clientId: clientId,
clientSecret: clientSecret,
scopes: ['openid', 'profile', 'offline_access']);
*/
var hlp = toPerformRequest(getClient());
await hlp.disconnect();
// ### Why are you removing all tokens in the storage? ###
//await hlp.removeAllTokens();
await _storage.deleteAll();
}
get(
String url, {
Map<String, String>? data,
}) async {
try {
var hlp = toPerformRequest(getClient());
// ### Again, no need to retrieve the token... ###
//await hlp.getToken();
// ### Does the token expire on its own or due to the calls to the disconnect method? ###
var token = await hlp.getTokenFromStorage();
//the token gets printed here until it expires an no longer able to get another token form storage
print(token?.accessToken.toString());
var response = await hlp.get("$baseurl$url", headers: data);
return jsonDecode(response.body);
} on SocketException {
throw Failure('No Internet connection expressionless');
} on HttpException {
throw Failure("Couldn't find the post scream");
} on FormatException {
throw Failure("Bad response format -1");
} on TimeoutException {
throw Failure('Connection Timeout: Check your internet connection');
} on Failure catch (e) {
throw Failure(e.message);
}
}
post(
String url,
dynamic data,
) async {
try {
var hlp = toPerformRequest(getClient());
// ### Again, no need to retrieve the token... ###
//await hlp.getToken();
var decodeBody = jsonEncode(data);
var response = await hlp.post(
"$baseurl$url",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: decodeBody,
);
return jsonDecode(response.body);
} on SocketException {
throw Failure('No Internet connection 😑');
} on HttpException {
throw Failure("Couldn't find the post 😱");
} on FormatException {
throw Failure("Bad response format 👎");
} on TimeoutException {
throw Failure('Connection Timeout: Check your internet connection');
} on Failure catch (e) {
throw Failure(e.message);
}
}
} |
I'm using the disconnect in the authorize method in order to empty the storage if at all there's token stored already before it authorizes the user. I will effect these corrections and see if it solves the issue. |
I made the corrections you suggested and here is what i have. When the token expires, it prints the previous token unlike before but redirects back to the login page( whereby it's suppose to refresh the token )I/flutter ( 9737): eyJhbGciOiJSUzI1NiIsImtpZCI6IjgyODUxRDU4Mzc2ODE3RUEzOTMyM0VGRTBEQzlENDZGQUJERENENDVSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6ImdvVWRXRGRvRi1vNU1qNy1EY25VYjZ2ZHpVVSJ9.eyJuYmYiOjE2NTA1MzU0MDgsImV4cCI6MTY1MDUzNzIwOCwiaXNzIjoiaHR0cHM6Ly9pZGVudGl0eS5vbmRnby5uZyIsImNsaWVudF9pZCI6Im9uRGdvQXBwQ2xpZW50Iiwic3ViIjoiNjI0MmUyZGZlNzUyNmNhbCIsImdpdmVuX25hbWUiOiJkYXlvIiwiZmFtaWx5X25hbWUiOiJvbmRnbyIsInJvbGUiOiJvbkRnb1VzZXIiLCJlbWFpbCI6ImRheW8zQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjoidHJ1ZSIsImFkZHJlc3MiOiIgIiwib25EZ29JZCI6ImRlbW8tb25EZ28tMTAwMDA0MCIsInRlbmIiwidGVuYW50TmFtZSI6Ik9OREdPIExpbWl0ZWQiLCJzaWQiOiIwQzA4RjBBRTEwN0ZGNTcxQ0M0QjFENEVDMURDRkY0RCIsImlhdCI6MTY1MDUzNTQwOCwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.DHrGOp9ZOFCqCW97tpNNuB5ze3IAXAP6tbuDW-yZewxdm_11PctqkhTVYtA0iay2mg8nkWP2yPCYZBcnf7ZrYrgbKCRhl4A54G5OjXDZQMtrcdLtmDu6Uct3RQWkQcENJuwQY3MEsivbZhzpa8Lfp5GDXkWgexwgTgAvHVraZNdkenQkLAsCHj when i tried it the second time here is the responseI/flutter ( 9737): null |
@Mubaola23, are you sure the server provides a refresh endpoint? If so, can it be that the refresh endpoint url is different than the access token url? Usually they are the same, but they can differ. For example: class MyOAuth2Client extends OAuth2Client {
MyOAuth2Client({required String redirectUri, required String customUriScheme})
: super(
authorizeUrl:
'https://$baseurl/connect/authorize', //Your service's authorization url
tokenUrl:
'https://$baseurl/connect/token', //Your service access token url
refreshUrl: 'https://$baseurl/connect/refresh', //***Just a made up url, you should check the server docs...
redirectUri: redirectUri,
revokeUrl: "https://$baseurl/connect/revocation",
customUriScheme: customUriScheme);
} But first of all, can you verify if actually a refresh token exists before the access token expires? get(
String url, {
Map<String, String>? data,
}) async {
try {
var hlp = toPerformRequest(getClient());
var token = await hlp.getTokenFromStorage();
print(token?.accessToken.toString());
print(token?.refreshToken.toString());
...
} |
Yes , I was able to print the refresh token along with the access token Access Token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjgyODUxRDU4Mzc2ODE3RUEzOTMyM0VGRTBEQzlENDZGQUJERENENDVSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6ImY1MDYxOTkxMiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJwd2QiXX0.Vqz21ZUuyvHhoE9sBRuZAr8FJxH8VJX0s__h9wRfPS8xl3B9Zlew73B2_eGgHigCtBd4fzZ_0M6X7ymmT5OW-oosfZ866RYhC1CXti1Hk0vZ2l0W78tginYdrxd5Z66_VuYVSVf_Nader7RMRrseKudKUGFtcIvV6_PmXYjG I/flutter ( 3440): Refresh Token :2A245D099FD4C628571264BBDDE5C673F90A689483541B I |
Hi @Mubaola23, I managed to replicate your issue, now I need to understand what's going on and how to solve it... |
Hi @okrad , thank you for taking time to look into this issue, i'll look forward to a reply from you. |
Hi @Mubaola23, can you try out the new version? |
Hi @okrad , I Added the updated version already and here is what changed: |
That's quite strange... If you are presented the login page this could mean one of two things:
In all of these cases, the client is forced to fetch a new token by means of the appropriate oauth flow. One thing you could try is to clear the token storage by calling the |
When the token expires, it tries to refresh the token in the secure storage but replaces it with an empty variable causing it to redirect to the login page. I’ve been on this issue for a while and seek possible solutions including checking the GitHub issues but still unable to get a better solution.
Here is where i defined my helper class
class MyOAuth2Client extends OAuth2Client {
MyOAuth2Client({required String redirectUri, required String customUriScheme})
: super(
authorizeUrl:
'https://$baseurl/connect/authorize', //Your service's authorization url
tokenUrl:
'https://$baseurl/connect/token', //Your service access token url
redirectUri: redirectUri,
revokeUrl: "https://$baseurl/connect/revocation",
customUriScheme: customUriScheme);
}
class MyHelper {
OAuth2Client getClient() {
var client;
client = MyOAuth2Client(
redirectUri: REDIRECT_URL,
customUriScheme: CUSTOM_SCHEME,
);
return client;
}
FlutterSecureStorage _storage = FlutterSecureStorage();
Future authorize() async {
try {
var client = getClient();
await _storage.deleteAll();
}
OAuth2Helper toPerformRequest(OAuth2Client client) {
String clientId = CLIENT_ID;
String clientSecret = CLIENT_SECRET;
}
logout() async {
String clientId = CLIENT_ID;
String clientSecret = CLIENT_SECRET;
var hlp = OAuth2Helper(getClient(),
clientId: clientId,
clientSecret: clientSecret,
scopes: [ 'openid', 'profile', 'offline_access']);
}
get(
String url, {
Map<String, String>? data,
}) async {
try {
var hlp = toPerformRequest(getClient());
//the token gets printed here until it expires an no longer able to get another token form storage
print(token?.accessToken.toString());
var response =
await hlp.get("$baseurl$url", headers: data);
return jsonDecode(response.body);
} on SocketException {
throw Failure('No Internet connection 😑');
} on HttpException {
throw Failure("Couldn't find the post 😱");
} on FormatException {
throw Failure("Bad response format 👎");
} on TimeoutException {
throw Failure('Connection Timeout: Check your internet connection');
} on Failure catch (e) {
throw Failure(e.message);
}
}
post(
String url,
dynamic data,
) async {
try {
var hlp = toPerformRequest(getClient());
await hlp.getToken();
}
}
This is from the helper class, At this point when the token expires , its suppose to refresh, but instead its calling the fetchToken() method which means it has previously try to refresh the token and it replaced it with an empty token
/// Returns a previously required token, if any, or requires a new one.
///
/// If a token already exists but is expired, a new token is generated through the refresh_token grant.
Future<AccessTokenResponse?> getToken() async {
_validateAuthorizationParams();
// [At this point when the token expires , its suppose to refresh, but instead its calling the fetchToken() method which means it has previously try to refresh the token and it replaced it with an empty token ]
if (tknResp != null) {
if (tknResp.refreshNeeded()) {
//The access token is expired
if (tknResp.refreshToken != null) {
tknResp = await refreshToken(tknResp.refreshToken!);
} else {
//No refresh token, fetch a new token
tknResp = await fetchToken();
}
}
} else {
tknResp = await fetchToken();
}
}
The text was updated successfully, but these errors were encountered: