Skip to content

Instantly share code, notes, and snippets.

@RobertApikyan
Created March 25, 2024 09:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobertApikyan/3df57d361f9f7cca879bfdce832ff717 to your computer and use it in GitHub Desktop.
Save RobertApikyan/3df57d361f9f7cca879bfdce832ff717 to your computer and use it in GitHub Desktop.
import 'dart:async';
import 'dart:io';
import 'package:raiser/api/ApiHeaders.dart';
import 'package:raiser/api/ApiRequestTracker.dart';
import 'package:raiser/repositories/OauthRepo.dart';
import 'package:raiser/repositories/RepoProvider.dart';
import 'package:raiser/rest/RestAbstract.dart';
class AuthorizationRequestMiddleware extends Middleware<RowRequest?> {
OauthRepo _oauth = Repositories.get().getOauthRepo();
static const unauthorizedCode = 401;
@override
Future<RowRequest?> onNext(RowRequest? row, Middleware nextMiddleware) async {
final hasAuthorizationHeader = row != null &&
(row.request.headers?.containsKey(HttpHeaders.authorizationHeader) ??
false);
if (!hasAuthorizationHeader) {
/// No need to check for refresh token, because not an authorized endpoint.
return await super.onNext(row, nextMiddleware);
}
bool isExpired = await _oauth.isAccessTokenExpires();
/// Wait here, because other endpoint was already expired and refresh token is
/// in process.
if (_oauth.isRefreshTokenLocked()) {
return await _waitForRefreshAndContinue(row, nextMiddleware);
} else if (isExpired) {
return await _refreshAndContinue(row, nextMiddleware);
}
return await super.onNext(row, nextMiddleware);
}
Future<RowRequest?> _refreshAndContinue(
RowRequest row, Middleware<dynamic> nextMiddleware) async {
final isSuccess = await _oauth.refreshTokenWithLock();
if (isSuccess) {
/// Adding updated accessToken to headers.
row.request.headers
?..removeWhere(
(key, value) => ApiHeaders.privateRequestHeaders.containsKey(key),
)
..addAll(ApiHeaders.privateRequestHeaders);
return await super.onNext(row, nextMiddleware);
} else {
throw AppRequestTrackerException(unauthorizedCode);
}
}
Future<RowRequest?> _waitForRefreshAndContinue(
RowRequest row, Middleware nextMiddleware) async {
final isSuccess = await _oauth.joinRefreshTokenLock();
await Future.delayed(const Duration(seconds: 1));
if (isSuccess) {
/// Adding updated accessToken to headers.
row.request.headers
?..removeWhere(
(key, value) => ApiHeaders.privateRequestHeaders.containsKey(key),
)
..addAll(ApiHeaders.privateRequestHeaders);
return await super.onNext(row, nextMiddleware);
} else {
throw AppRequestTrackerException(unauthorizedCode);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment