matrix-js-sdk
Version:
Matrix Client-Server SDK for Javascript
341 lines • 12.6 kB
TypeScript
import { type MatrixClient } from "./client.ts";
import { type UserIdentifier } from "./@types/auth.ts";
export interface UIAFlow {
stages: Array<AuthType | string>;
}
export interface IInputs {
emailAddress?: string;
phoneCountry?: string;
phoneNumber?: string;
registrationToken?: string;
}
export interface IStageStatus {
emailSid?: string;
errcode?: string;
error?: string;
}
/**
* Data returned in the body of a 401 response from a UIA endpoint.
*
* @see https://spec.matrix.org/v1.6/client-server-api/#user-interactive-api-in-the-rest-api
*/
export interface IAuthData {
/**
* This is a session identifier that the client must pass back to the home server,
* if one is provided, in subsequent attempts to authenticate in the same API call.
*/
session?: string;
/**
* A list of the stages the client has completed successfully
*/
completed?: string[];
/**
* A list of the login flows supported by the server for this API.
*/
flows?: UIAFlow[];
/**
* Contains any information that the client will need to know in order to use a given type of authentication.
* For each login type presented, that type may be present as a key in this dictionary.
* For example, the public part of an OAuth client ID could be given here.
*/
params?: Record<string, Record<string, any>>;
}
export declare enum AuthType {
Password = "m.login.password",
Recaptcha = "m.login.recaptcha",
Terms = "m.login.terms",
Email = "m.login.email.identity",
Msisdn = "m.login.msisdn",
Sso = "m.login.sso",
SsoUnstable = "org.matrix.login.sso",
Dummy = "m.login.dummy",
RegistrationToken = "m.login.registration_token",
UnstableRegistrationToken = "org.matrix.msc3231.login.registration_token",
/**
* m.oauth stage introduced by MSC4312:
* https://spec.matrix.org/v1.17/client-server-api/#oauth-authentication
*/
OAuth = "m.oauth"
}
/**
* https://spec.matrix.org/v1.7/client-server-api/#password-based
*/
type PasswordDict = {
type: AuthType.Password;
identifier: UserIdentifier;
password: string;
session: string;
};
/**
* https://spec.matrix.org/v1.7/client-server-api/#google-recaptcha
*/
type RecaptchaDict = {
type: AuthType.Recaptcha;
response: string;
session: string;
};
interface ThreepidCreds {
sid: string;
client_secret: string;
id_server: string;
id_access_token: string;
}
/**
* https://spec.matrix.org/v1.7/client-server-api/#email-based-identity--homeserver
*/
type EmailIdentityDict = {
type: AuthType.Email;
threepid_creds: ThreepidCreds;
session: string;
};
/**
* The parameters which are submitted as the `auth` dict in a UIA request
*
* @see https://spec.matrix.org/v1.6/client-server-api/#authentication-types
*/
export type AuthDict = PasswordDict | RecaptchaDict | EmailIdentityDict | {
type: Exclude<string, AuthType>;
[key: string]: any;
} | {};
export declare class NoAuthFlowFoundError extends Error {
readonly required_stages: string[];
readonly flows: UIAFlow[];
name: string;
constructor(m: string, required_stages: string[], flows: UIAFlow[]);
}
/**
* The type of an application callback to perform the user-interactive bit of UIA.
*
* It is called with a single parameter, `makeRequest`, which is a function which takes the UIA parameters and
* makes the HTTP request. The `authData` parameter in `makeRequest` can be set to null to omit the `auth` field
* from the UIA request.
*
* The generic parameter `T` is the type of the response of the endpoint, once it is eventually successful.
*/
export type UIAuthCallback<T> = (makeRequest: (authData: AuthDict | null) => Promise<T>) => Promise<T>;
interface IOpts<T> {
/**
* A matrix client to use for the auth process
*/
matrixClient: MatrixClient;
/**
* Error response from the last request. If null, a request will be made with no auth before starting.
*/
authData?: IAuthData;
/**
* Inputs provided by the user and used by different stages of the auto process.
* The inputs provided will affect what flow is chosen.
*/
inputs?: IInputs;
/**
* If resuming an existing interactive auth session, the sessionId of that session.
*/
sessionId?: string;
/**
* If resuming an existing interactive auth session, the client secret for that session
*/
clientSecret?: string;
/**
* If returning from having completed m.login.email.identity auth, the sid for the email verification session.
*/
emailSid?: string;
/**
* If specified, will prefer flows which entirely consist of listed stages.
* These should normally be of type AuthTypes but can be string when supporting custom auth stages.
*
* This can be used to avoid needing the fallback mechanism.
*/
supportedStages?: Array<AuthType | string>;
/**
* Called with the new auth dict to submit the request.
* Also passes a second deprecated arg which is a flag set to true if this request is a background request.
* The busyChanged callback should be used instead of the background flag.
* Should return a promise which resolves to the successful response or rejects with a MatrixError.
*/
doRequest(auth: AuthDict | null, background: boolean): Promise<T>;
/**
* Called when the status of the UI auth changes,
* ie. when the state of an auth stage changes of when the auth flow moves to a new stage.
* The arguments are: the login type (eg m.login.password); and an object which is either an error or an
* informational object specific to the login type.
* If the 'errcode' key is defined, the object is an error, and has keys:
* errcode: string, the textual error code, eg. M_UNKNOWN
* error: string, human readable string describing the error
*
* The login type specific objects are as follows:
* m.login.email.identity:
* * emailSid: string, the sid of the active email auth session
*/
stateUpdated(nextStage: AuthType | string, status: IStageStatus): void;
/**
* A function that takes the email address (string), clientSecret (string), attempt number (int) and
* sessionId (string) and calls the relevant requestToken function and returns the promise returned by that
* function.
* If the resulting promise rejects, the rejection will propagate through to the attemptAuth promise.
*/
requestEmailToken(email: string, secret: string, attempt: number, session: string): Promise<{
sid: string;
}>;
/**
* Called whenever the interactive auth logic becomes busy submitting information provided by the user or finishes.
* After this has been called with true the UI should indicate that a request is in progress
* until it is called again with false.
*/
busyChanged?(busy: boolean): void;
startAuthStage?(nextStage: string): Promise<void>;
}
/**
* Abstracts the logic used to drive the interactive auth process.
*
* <p>Components implementing an interactive auth flow should instantiate one of
* these, passing in the necessary callbacks to the constructor. They should
* then call attemptAuth, which will return a promise which will resolve or
* reject when the interactive-auth process completes.
*
* <p>Meanwhile, calls will be made to the startAuthStage and doRequest
* callbacks, and information gathered from the user can be submitted with
* submitAuthDict.
*
* @param opts - options object
* @typeParam T - the return type of the request when it is successful
*/
export declare class InteractiveAuth<T> {
private readonly matrixClient;
private readonly inputs;
private readonly clientSecret;
private readonly requestCallback;
private readonly busyChangedCallback?;
private readonly stateUpdatedCallback;
private readonly requestEmailTokenCallback;
private readonly supportedStages?;
private data;
private emailSid?;
private requestingEmailToken;
private attemptAuthDeferred;
private chosenFlow;
private currentStage;
private emailAttempt;
private submitPromise;
constructor(opts: IOpts<T>);
/**
* begin the authentication process.
*
* @returns which resolves to the response on success,
* or rejects with the error on failure. Rejects with NoAuthFlowFoundError if
* no suitable authentication flow can be found
*/
attemptAuth(): Promise<T>;
/**
* Poll to check if the auth session or current stage has been
* completed out-of-band. If so, the attemptAuth promise will
* be resolved.
*/
poll(): Promise<void>;
/**
* get the auth session ID
*
* @returns session id
*/
getSessionId(): string | undefined;
/**
* get the client secret used for validation sessions
* with the identity server.
*
* @returns client secret
*/
getClientSecret(): string;
/**
* get the server params for a given stage
*
* @param loginType - login type for the stage
* @returns any parameters from the server for this stage
*/
getStageParams(loginType: string): Record<string, any> | undefined;
getChosenFlow(): UIAFlow | null;
/**
* submit a new auth dict and fire off the request. This will either
* make attemptAuth resolve/reject, or cause the startAuthStage callback
* to be called for a new stage.
*
* @param authData - new auth dict to send to the server. Should
* include a `type` property denoting the login type, as well as any
* other params for that stage.
* @param background - If true, this request failing will not result
* in the attemptAuth promise being rejected. This can be set to true
* for requests that just poll to see if auth has been completed elsewhere.
*/
submitAuthDict(authData: AuthDict, background?: boolean): Promise<void>;
/**
* Gets the sid for the email validation session
* Specific to m.login.email.identity
*
* @returns The sid of the email auth session
*/
getEmailSid(): string | undefined;
/**
* Sets the sid for the email validation session
* This must be set in order to successfully poll for completion
* of the email validation.
* Specific to m.login.email.identity
*
* @param sid - The sid for the email validation session
*/
setEmailSid(sid: string): void;
/**
* Requests a new email token and sets the email sid for the validation session
*/
requestEmailToken: () => Promise<void>;
/**
* Fire off a request, and either resolve the promise, or call
* startAuthStage.
*
* @internal
* @param auth - new auth dict, including session id
* @param background - If true, this request is a background poll, so it
* failing will not result in the attemptAuth promise being rejected.
* This can be set to true for requests that just poll to see if auth has
* been completed elsewhere.
*/
private doRequest;
/**
* Pick the next stage and call the callback
*
* @internal
* @throws {@link NoAuthFlowFoundError} If no suitable authentication flow can be found
*/
private startNextAuthStage;
/**
* Pick the next auth stage
*
* @internal
* @returns login type
* @throws {@link NoAuthFlowFoundError} If no suitable authentication flow can be found
*/
private chooseStage;
private scoreFlow;
/**
* Pick one of the flows from the returned list
* If a flow using all of the inputs is found, it will
* be returned, otherwise, null will be returned.
*
* Only flows using all given inputs are chosen because it
* is likely to be surprising if the user provides a
* credential and it is not used. For example, for registration,
* this could result in the email not being used which would leave
* the account with no means to reset a password.
*
* @internal
* @returns flow
* @throws {@link NoAuthFlowFoundError} If no suitable authentication flow can be found
*/
private chooseFlow;
/**
* Get the first uncompleted stage in the given flow
*
* @internal
* @returns login type
*/
private firstUncompletedStage;
}
export {};
//# sourceMappingURL=interactive-auth.d.ts.map