You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-28 05:03:59 +03:00
Add functions to support refresh tokens (#2178)
* Add functions for refreshing access tokens * Add function to change the client's access token in flight * Appease the linter * Use sensible code style
This commit is contained in:
29
src/@types/auth.ts
Normal file
29
src/@types/auth.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// disable lint because these are wire responses
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a response to the CSAPI `/refresh` endpoint.
|
||||||
|
*/
|
||||||
|
export interface IRefreshTokenResponse {
|
||||||
|
access_token: string;
|
||||||
|
expires_in_ms: number;
|
||||||
|
refresh_token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-enable camelcase */
|
||||||
@@ -20,7 +20,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import { EmoteEvent, MessageEvent, NoticeEvent, IPartialEvent } from "matrix-events-sdk";
|
import { EmoteEvent, IPartialEvent, MessageEvent, NoticeEvent } from "matrix-events-sdk";
|
||||||
|
|
||||||
import { ISyncStateData, SyncApi, SyncState } from "./sync";
|
import { ISyncStateData, SyncApi, SyncState } from "./sync";
|
||||||
import { EventStatus, IContent, IDecryptOptions, IEvent, MatrixEvent } from "./models/event";
|
import { EventStatus, IContent, IDecryptOptions, IEvent, MatrixEvent } from "./models/event";
|
||||||
@@ -52,6 +52,7 @@ import {
|
|||||||
PREFIX_MEDIA_R0,
|
PREFIX_MEDIA_R0,
|
||||||
PREFIX_R0,
|
PREFIX_R0,
|
||||||
PREFIX_UNSTABLE,
|
PREFIX_UNSTABLE,
|
||||||
|
PREFIX_V1,
|
||||||
retryNetworkOperation,
|
retryNetworkOperation,
|
||||||
UploadContentResponseType,
|
UploadContentResponseType,
|
||||||
} from "./http-api";
|
} from "./http-api";
|
||||||
@@ -87,14 +88,7 @@ import {
|
|||||||
} from "./crypto/keybackup";
|
} from "./crypto/keybackup";
|
||||||
import { IIdentityServerProvider } from "./@types/IIdentityServerProvider";
|
import { IIdentityServerProvider } from "./@types/IIdentityServerProvider";
|
||||||
import { MatrixScheduler } from "./scheduler";
|
import { MatrixScheduler } from "./scheduler";
|
||||||
import {
|
import { IAuthData, ICryptoCallbacks, IMinimalEvent, IRoomEvent, IStateEvent, NotificationCountType } from "./matrix";
|
||||||
IAuthData,
|
|
||||||
ICryptoCallbacks,
|
|
||||||
IMinimalEvent,
|
|
||||||
IRoomEvent,
|
|
||||||
IStateEvent,
|
|
||||||
NotificationCountType,
|
|
||||||
} from "./matrix";
|
|
||||||
import {
|
import {
|
||||||
CrossSigningKey,
|
CrossSigningKey,
|
||||||
IAddSecretStorageKeyOpts,
|
IAddSecretStorageKeyOpts,
|
||||||
@@ -160,6 +154,7 @@ import { IPusher, IPusherRequest, IPushRules, PushRuleAction, PushRuleKind, Rule
|
|||||||
import { IThreepid } from "./@types/threepids";
|
import { IThreepid } from "./@types/threepids";
|
||||||
import { CryptoStore } from "./crypto/store/base";
|
import { CryptoStore } from "./crypto/store/base";
|
||||||
import { MediaHandler } from "./webrtc/mediaHandler";
|
import { MediaHandler } from "./webrtc/mediaHandler";
|
||||||
|
import { IRefreshTokenResponse } from "./@types/auth";
|
||||||
|
|
||||||
export type Store = IStore;
|
export type Store = IStore;
|
||||||
export type SessionStore = WebStorageSessionStore;
|
export type SessionStore = WebStorageSessionStore;
|
||||||
@@ -6619,6 +6614,14 @@ export class MatrixClient extends EventEmitter {
|
|||||||
return this.http.opts.accessToken || null;
|
return this.http.opts.accessToken || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the access token associated with this account.
|
||||||
|
* @param {string} token The new access token.
|
||||||
|
*/
|
||||||
|
public setAccessToken(token: string) {
|
||||||
|
this.http.opts.accessToken = token;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {boolean} true if there is a valid access_token for this client.
|
* @return {boolean} true if there is a valid access_token for this client.
|
||||||
*/
|
*/
|
||||||
@@ -6695,6 +6698,7 @@ export class MatrixClient extends EventEmitter {
|
|||||||
|
|
||||||
const params: any = {
|
const params: any = {
|
||||||
auth: auth,
|
auth: auth,
|
||||||
|
refresh_token: true, // always ask for a refresh token - does nothing if unsupported
|
||||||
};
|
};
|
||||||
if (username !== undefined && username !== null) {
|
if (username !== undefined && username !== null) {
|
||||||
params.username = username;
|
params.username = username;
|
||||||
@@ -6772,6 +6776,31 @@ export class MatrixClient extends EventEmitter {
|
|||||||
return this.http.request(callback, Method.Post, "/register", params, data);
|
return this.http.request(callback, Method.Post, "/register", params, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes an access token using a provided refresh token. The refresh token
|
||||||
|
* must be valid for the current access token known to the client instance.
|
||||||
|
*
|
||||||
|
* Note that this function will not cause a logout if the token is deemed
|
||||||
|
* unknown by the server - the caller is responsible for managing logout
|
||||||
|
* actions on error.
|
||||||
|
* @param {string} refreshToken The refresh token.
|
||||||
|
* @return {Promise<IRefreshTokenResponse>} Resolves to the new token.
|
||||||
|
* @return {module:http-api.MatrixError} Rejects with an error response.
|
||||||
|
*/
|
||||||
|
public refreshToken(refreshToken: string): Promise<IRefreshTokenResponse> {
|
||||||
|
return this.http.authedRequest(
|
||||||
|
undefined,
|
||||||
|
Method.Post,
|
||||||
|
"/refresh",
|
||||||
|
undefined,
|
||||||
|
{ refresh_token: refreshToken },
|
||||||
|
{
|
||||||
|
prefix: PREFIX_V1,
|
||||||
|
inhibitLogoutEmit: true, // we don't want to cause logout loops
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {module:client.callback} callback Optional.
|
* @param {module:client.callback} callback Optional.
|
||||||
* @return {Promise} Resolves: TODO
|
* @return {Promise} Resolves: TODO
|
||||||
|
|||||||
@@ -111,6 +111,12 @@ interface IRequestOpts<T> {
|
|||||||
json?: boolean; // defaults to true
|
json?: boolean; // defaults to true
|
||||||
qsStringifyOptions?: CoreOptions["qsStringifyOptions"];
|
qsStringifyOptions?: CoreOptions["qsStringifyOptions"];
|
||||||
bodyParser?(body: string): T;
|
bodyParser?(body: string): T;
|
||||||
|
|
||||||
|
// Set to true to prevent the request function from emitting
|
||||||
|
// a Session.logged_out event. This is intended for use on
|
||||||
|
// endpoints where M_UNKNOWN_TOKEN is a valid/notable error
|
||||||
|
// response, such as with token refreshes.
|
||||||
|
inhibitLogoutEmit?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUpload {
|
export interface IUpload {
|
||||||
@@ -596,7 +602,7 @@ export class MatrixHttpApi {
|
|||||||
const requestPromise = this.request<T, O>(callback, method, path, queryParams, data, requestOpts);
|
const requestPromise = this.request<T, O>(callback, method, path, queryParams, data, requestOpts);
|
||||||
|
|
||||||
requestPromise.catch((err: MatrixError) => {
|
requestPromise.catch((err: MatrixError) => {
|
||||||
if (err.errcode == 'M_UNKNOWN_TOKEN') {
|
if (err.errcode == 'M_UNKNOWN_TOKEN' && !requestOpts?.inhibitLogoutEmit) {
|
||||||
this.eventEmitter.emit("Session.logged_out", err);
|
this.eventEmitter.emit("Session.logged_out", err);
|
||||||
} else if (err.errcode == 'M_CONSENT_NOT_GIVEN') {
|
} else if (err.errcode == 'M_CONSENT_NOT_GIVEN') {
|
||||||
this.eventEmitter.emit(
|
this.eventEmitter.emit(
|
||||||
|
|||||||
Reference in New Issue
Block a user