Support refresh tokens (#7802)
MSC: https://github.com/matrix-org/matrix-doc/pull/2918 Fixes https://github.com/vector-im/element-web/issues/18698 Fixes https://github.com/vector-im/element-web/issues/20648 **Requires https://github.com/matrix-org/matrix-js-sdk/pull/2178** **Note**: There's a lot of logging in this PR. That is intentional to ensure that if/when something goes wrong we can chase the exact code path. It does not log any tokens - just where the code is going. Overall, it should be fairly low volume spam (and can be relaxed at a later date). ---- This approach uses indexeddb (through a mutex library) to manage which tab actually triggers the refresh, preventing issues where multiple tabs try to update the token. If multiple tabs update the token then the server might consider the account hacked and hard logout all the tokens. If for some reason the timer code gets it wrong, or the user has been offline for too long and the token can't be refreshed, they should be sent to a soft logout screen by the server. This will retain the user's encryption state - they simply need to reauthenticate to get an active access token again. This additionally contains a change to fix soft logout not working, per the issue links above. Of interest may be the IPC approach which was ultimately declined in favour of this change instead: https://github.com/matrix-org/matrix-react-sdk/pull/7803
This commit is contained in:
parent
a958cd20f1
commit
839593412c
9 changed files with 504 additions and 25 deletions
|
@ -44,6 +44,8 @@ export interface IMatrixClientCreds {
|
|||
userId: string;
|
||||
deviceId?: string;
|
||||
accessToken: string;
|
||||
accessTokenExpiryTs?: number; // set if access token expires
|
||||
accessTokenRefreshToken?: string; // set if access token can be renewed
|
||||
guest?: boolean;
|
||||
pickleKey?: string;
|
||||
freshLogin?: boolean;
|
||||
|
@ -99,6 +101,14 @@ export interface IMatrixClientPeg {
|
|||
* @param {IMatrixClientCreds} creds The new credentials to use.
|
||||
*/
|
||||
replaceUsingCreds(creds: IMatrixClientCreds): void;
|
||||
|
||||
/**
|
||||
* Similar to replaceUsingCreds(), but without the replacement operation.
|
||||
* Credentials that can be updated in-place will be updated. All others
|
||||
* will be ignored.
|
||||
* @param {IMatrixClientCreds} creds The new credentials to use.
|
||||
*/
|
||||
updateUsingCreds(creds: IMatrixClientCreds): void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -164,6 +174,15 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
this.createClient(creds);
|
||||
}
|
||||
|
||||
public updateUsingCreds(creds: IMatrixClientCreds): void {
|
||||
if (creds?.accessToken) {
|
||||
this.currentClientCreds = creds;
|
||||
this.matrixClient.setAccessToken(creds.accessToken);
|
||||
} else {
|
||||
// ignore, per signature
|
||||
}
|
||||
}
|
||||
|
||||
public async assign(): Promise<any> {
|
||||
for (const dbType of ['indexeddb', 'memory']) {
|
||||
try {
|
||||
|
@ -233,7 +252,15 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
|||
}
|
||||
|
||||
public getCredentials(): IMatrixClientCreds {
|
||||
let copiedCredentials = this.currentClientCreds;
|
||||
if (this.currentClientCreds?.userId !== this.matrixClient?.credentials?.userId) {
|
||||
// cached credentials belong to a different user - don't use them
|
||||
copiedCredentials = null;
|
||||
}
|
||||
return {
|
||||
// Copy the cached credentials before overriding what we can.
|
||||
...(copiedCredentials ?? {}),
|
||||
|
||||
homeserverUrl: this.matrixClient.baseUrl,
|
||||
identityServerUrl: this.matrixClient.idBaseUrl,
|
||||
userId: this.matrixClient.credentials.userId,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue