Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve types around login, registration, UIA and identity servers #3537

Merged
merged 14 commits into from
Jul 4, 2023
123 changes: 22 additions & 101 deletions src/@types/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ limitations under the License.

import { UnstableValue } from "../NamespacedValue";
import { IClientWellKnown } from "../client";
import { AuthDict } from "../interactive-auth";

// disable lint because these are wire responses
/* eslint-disable camelcase */
Expand Down Expand Up @@ -90,15 +89,20 @@ export enum SSOAction {
}

/**
* https://spec.matrix.org/v1.7/client-server-api/#matrix-user-id
* A client can identify a user using their Matrix ID.
* This can either be the fully qualified Matrix user ID, or just the localpart of the user ID.
* @see https://spec.matrix.org/v1.7/client-server-api/#matrix-user-id
Comment on lines +92 to +94
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is certainly helpful, but for bonus points it would be nice to say where this thing is used: if I look at https://pr3537--js-sdk-docs-previews.netlify.app/stable/types/_internal_.userloginidentifier it's just somewhat lacking in context.

Anyway no need to change this now but something I think we could be better at in future.

*/
type UserLoginIdentifier = {
type: "m.id.user";
user: string;
};

/**
* https://spec.matrix.org/v1.7/client-server-api/#third-party-id
* A client can identify a user using a 3PID associated with the user’s account on the homeserver,
* where the 3PID was previously associated using the /account/3pid API.
* See the 3PID Types Appendix for a list of Third-party ID media.
* @see https://spec.matrix.org/v1.7/client-server-api/#third-party-id
*/
type ThirdPartyLoginIdentifier = {
type: "m.id.thirdparty";
Expand All @@ -107,7 +111,15 @@ type ThirdPartyLoginIdentifier = {
};

/**
* https://spec.matrix.org/v1.7/client-server-api/#phone-number
* A client can identify a user using a phone number associated with the user’s account,
* where the phone number was previously associated using the /account/3pid API.
* The phone number can be passed in as entered by the user; the homeserver will be responsible for canonicalising it.
* If the client wishes to canonicalise the phone number,
* then it can use the m.id.thirdparty identifier type with a medium of msisdn instead.
*
* The country is the two-letter uppercase ISO-3166-1 alpha-2 country code that the number in phone should be parsed as if it were dialled from.
*
* @see https://spec.matrix.org/v1.7/client-server-api/#phone-number
*/
type PhoneLoginIdentifier = {
type: "m.id.phone";
Expand All @@ -117,13 +129,17 @@ type PhoneLoginIdentifier = {

type SpecUserIdentifier = UserLoginIdentifier | ThirdPartyLoginIdentifier | PhoneLoginIdentifier;

/**
* User Identifiers usable for login & user-interactive authentication
* Extensibly allows more than Matrix specified identifiers
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
*/
export type UserIdentifier =
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
| SpecUserIdentifier
| { type: Exclude<string, SpecUserIdentifier["type"]>; [key: string]: any };

/**
* Request body for POST /login request
* See https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3login
* @see https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3login
*/
export interface LoginRequest {
/**
Expand Down Expand Up @@ -183,7 +199,7 @@ export type ILoginParams = LoginRequest;

/**
* Response body for POST /login request
* See https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3login
* @see https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3login
*/
export interface LoginResponse {
/**
Expand Down Expand Up @@ -246,98 +262,3 @@ export interface LoginTokenPostResponse {
*/
expires_in_ms: number;
}

/**
*
*/
export interface RegisterRequest {
/**
* Additional authentication information for the user-interactive authentication API.
* Note that this information is not used to define how the registered user should be authenticated,
* but is instead used to authenticate the register call itself.
*/
auth?: AuthDict;
/**
* The basis for the localpart of the desired Matrix ID.
* If omitted, the homeserver MUST generate a Matrix ID local part.
*/
username?: string;
/**
* The desired password for the account.
*/
password?: string;
/**
* If true, the client supports refresh tokens.
*/
refresh_token?: boolean;
/**
* If true, an access_token and device_id should not be returned from this call, therefore preventing an automatic login.
* Defaults to false.
*/
inhibit_login?: boolean;
/**
* A display name to assign to the newly-created device.
* Ignored if device_id corresponds to a known device.
*/
initial_device_display_name?: string;
/**
* @deprecated missing in the spec
*/
guest_access_token?: string;
/**
* @deprecated missing in the spec
*/
x_show_msisdn?: boolean;
/**
* @deprecated missing in the spec
*/
bind_msisdn?: boolean;
/**
* @deprecated missing in the spec
*/
bind_email?: boolean;
}

/**
* The result of a successful call to POST https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3register
*/
export interface RegisterResponse {
/**
* The fully-qualified Matrix user ID (MXID) that has been registered.
*/
user_id: string;
/**
* An access token for the account.
* This access token can then be used to authorize other requests.
* Required if the inhibit_login option is false.
*/
access_token?: string;
/**
* ID of the registered device.
* Will be the same as the corresponding parameter in the request, if one was specified.
* Required if the inhibit_login option is false.
*/
device_id?: string;
/**
* The lifetime of the access token, in milliseconds.
* Once the access token has expired a new access token can be obtained by using the provided refresh token.
* If no refresh token is provided, the client will need to re-log in to obtain a new access token.
* If not given, the client can assume that the access token will not expire.
*
* Omitted if the inhibit_login option is true.
*/
expires_in_ms?: number;
/**
* A refresh token for the account.
* This token can be used to obtain a new access token when it expires by calling the /refresh endpoint.
*
* Omitted if the inhibit_login option is true.
*/
refresh_token?: string;
/**
* The server_name of the homeserver on which the account has been registered.
*
* @deprecated Clients should extract the server_name from user_id (by splitting at the first colon) if they require it.
*/
home_server?: string;
}
112 changes: 112 additions & 0 deletions src/@types/registration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
Copyright 2023 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.
*/

import { AuthDict } from "../interactive-auth";

/**
* The request body of a call to POST https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3register
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
*/
export interface RegisterRequest {
/**
* Additional authentication information for the user-interactive authentication API.
* Note that this information is not used to define how the registered user should be authenticated,
* but is instead used to authenticate the register call itself.
*/
auth?: AuthDict;
/**
* The basis for the localpart of the desired Matrix ID.
* If omitted, the homeserver MUST generate a Matrix ID local part.
*/
username?: string;
/**
* The desired password for the account.
*/
password?: string;
/**
* If true, the client supports refresh tokens.
*/
refresh_token?: boolean;
/**
* If true, an access_token and device_id should not be returned from this call, therefore preventing an automatic login.
* Defaults to false.
*/
inhibit_login?: boolean;
/**
* A display name to assign to the newly-created device.
* Ignored if device_id corresponds to a known device.
*/
initial_device_display_name?: string;
/**
* @deprecated missing in the spec
*/
guest_access_token?: string;
/**
* @deprecated missing in the spec
*/
x_show_msisdn?: boolean;
/**
* @deprecated missing in the spec
*/
bind_msisdn?: boolean;
/**
* @deprecated missing in the spec
*/
bind_email?: boolean;
}

/**
* The result of a successful call to POST https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3register
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
*/
export interface RegisterResponse {
/**
* The fully-qualified Matrix user ID (MXID) that has been registered.
*/
user_id: string;
/**
* An access token for the account.
* This access token can then be used to authorize other requests.
* Required if the inhibit_login option is false.
*/
access_token?: string;
/**
* ID of the registered device.
* Will be the same as the corresponding parameter in the request, if one was specified.
* Required if the inhibit_login option is false.
*/
device_id?: string;
/**
* The lifetime of the access token, in milliseconds.
* Once the access token has expired a new access token can be obtained by using the provided refresh token.
* If no refresh token is provided, the client will need to re-log in to obtain a new access token.
* If not given, the client can assume that the access token will not expire.
*
* Omitted if the inhibit_login option is true.
*/
expires_in_ms?: number;
/**
* A refresh token for the account.
* This token can be used to obtain a new access token when it expires by calling the /refresh endpoint.
*
* Omitted if the inhibit_login option is true.
*/
refresh_token?: string;
/**
* The server_name of the homeserver on which the account has been registered.
*
* @deprecated Clients should extract the server_name from user_id (by splitting at the first colon) if they require it.
*/
home_server?: string;
}
7 changes: 3 additions & 4 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,6 @@ import {
SSOAction,
LoginResponse,
LoginRequest,
RegisterRequest,
RegisterResponse,
} from "./@types/auth";
import { TypedEventEmitter } from "./models/typed-event-emitter";
import { MAIN_ROOM_TIMELINE, ReceiptType } from "./@types/read_receipts";
Expand Down Expand Up @@ -218,6 +216,7 @@ import {
ServerSideSecretStorage,
ServerSideSecretStorageImpl,
} from "./secret-storage";
import { RegisterRequest, RegisterResponse } from "./@types/registration";

export type Store = IStore;

Expand Down Expand Up @@ -7796,7 +7795,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* @returns Promise which resolves to a LoginResponse object
* @returns Rejects: with an error response.
*/
public login(loginType: string, data: Omit<LoginRequest, "type">): Promise<LoginResponse> {
public login(loginType: LoginRequest["type"], data: Omit<LoginRequest, "type">): Promise<LoginResponse> {
return this.http
.authedRequest<LoginResponse>(Method.Post, "/login", undefined, {
...data,
Expand Down Expand Up @@ -7826,7 +7825,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa

/**
* @param relayState - URL Callback after SAML2 Authentication
* @returns Promise which resolves to a LoginResponse object
* @returns Promise which resolves to a LoginResponse object
* @returns Rejects: with an error response.
* @deprecated this isn't in the Matrix spec anymore
*/
Expand Down
3 changes: 3 additions & 0 deletions src/interactive-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ interface IOpts<T> {
* submitAuthDict.
*
* @param opts - options object
* @typeParam T - the return type of the request when it is successful
*/
export class InteractiveAuth<T> {
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
private readonly matrixClient: MatrixClient;
Expand All @@ -262,6 +263,8 @@ export class InteractiveAuth<T> {
private readonly requestEmailTokenCallback: IOpts<T>["requestEmailToken"];
private readonly supportedStages?: Set<string>;

// The current latest data as part of the interactive auth
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
// MatrixError can occur if the error from server is not a 401 UIA error
private data: IAuthData | MatrixError;
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
private emailSid?: string;
private requestingEmailToken = false;
Expand Down