-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add refresh token handling http client
- implement a `MatrixRefreshTokenClient` to await token refresh before dispatching http requests - improve documentation about soft logout logic - fix dartdoc locations about soft logout Fixes: #2027 Signed-off-by: The one with the braid <[email protected]>
- Loading branch information
1 parent
352b3fa
commit 65e065c
Showing
3 changed files
with
90 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import 'package:http/http.dart' hide Client; | ||
|
||
import 'package:matrix/matrix.dart'; | ||
|
||
class MatrixRefreshTokenClient extends BaseClient { | ||
MatrixRefreshTokenClient({ | ||
required this.inner, | ||
required this.client, | ||
}); | ||
|
||
final Client client; | ||
final BaseClient inner; | ||
|
||
@override | ||
Future<StreamedResponse> send(BaseRequest request) async { | ||
Request? req; | ||
if ( // only refresh if | ||
// we are actually initialized | ||
client.onSync.value != null && | ||
// the request is to the homeserver rather than e.g. IDP | ||
request.url.host == client.homeserver?.host && | ||
// the request is authenticated | ||
request.headers | ||
.map((k, v) => MapEntry(k.toLowerCase(), v)) | ||
.containsKey('authorization') && | ||
// and last but not least we're logged in | ||
client.isLogged()) { | ||
try { | ||
await client.ensureNotSoftLoggedOut(); | ||
} catch (e) { | ||
Logs().w('Could not rotate token before dispatching HTTP request.', e); | ||
} | ||
// in every case ensure we run with the latest bearer token to avoid | ||
// race conditions | ||
finally { | ||
final headers = request.headers; | ||
// hours wasted : unknown :facepalm: | ||
headers.removeWhere((k, _) => k.toLowerCase() == 'authorization'); | ||
headers['Authorization'] = 'Bearer ${client.bearerToken!}'; | ||
req = Request(request.method, request.url); | ||
req.headers.addAll(headers); | ||
if (request is Request) { | ||
req.bodyBytes = request.bodyBytes; | ||
} | ||
} | ||
} | ||
return inner.send(req ?? request); | ||
} | ||
} |