diff --git a/dist/b2b/client.js b/dist/b2b/client.js index 2416dbb4..f119cec0 100644 --- a/dist/b2b/client.js +++ b/dist/b2b/client.js @@ -23,6 +23,8 @@ var _passwords = require("./passwords"); var _oauth = require("./oauth"); +var _otps = require("./otps"); + function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } @@ -49,6 +51,7 @@ class B2BClient extends _client.BaseClient { this.discovery = new _discovery.Discovery(this.fetchConfig); this.passwords = new _passwords.Passwords(this.fetchConfig); this.oauth = new _oauth.OAuth(this.fetchConfig); + this.otps = new _otps.OTPs(this.fetchConfig); } } diff --git a/dist/b2b/members.js b/dist/b2b/members.js index 2a8ce435..cf40de8d 100644 --- a/dist/b2b/members.js +++ b/dist/b2b/members.js @@ -53,6 +53,13 @@ class Members { }); } + deletePhoneNumber(data) { + return (0, _shared.request)(this.fetchConfig, { + method: "DELETE", + url: `${this.base_path}/${data.organization_id}/members/phone_numbers/${data.member_phone_id}` + }); + } + } exports.Members = Members; \ No newline at end of file diff --git a/dist/b2b/mfa.js b/dist/b2b/mfa.js new file mode 100644 index 00000000..430afc16 --- /dev/null +++ b/dist/b2b/mfa.js @@ -0,0 +1,5 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); \ No newline at end of file diff --git a/dist/b2b/otps.js b/dist/b2b/otps.js new file mode 100644 index 00000000..e5164ba3 --- /dev/null +++ b/dist/b2b/otps.js @@ -0,0 +1,49 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.OTPs = void 0; + +var _shared = require("../shared"); + +class SMS { + delivery = "sms"; + + constructor(fetchConfig, base_path) { + this.fetchConfig = fetchConfig; + this.base_path = base_path; + } + + endpoint(path) { + return `${this.base_path}/${this.delivery}/${path}`; + } + + send(data) { + return (0, _shared.request)(this.fetchConfig, { + method: "POST", + url: this.endpoint("send"), + data + }); + } + + authenticate(data) { + return (0, _shared.request)(this.fetchConfig, { + method: "POST", + url: this.endpoint("authenticate"), + data + }); + } + +} + +class OTPs { + base_path = "otps"; + + constructor(fetchConfig) { + this.sms = new SMS(fetchConfig, this.base_path); + } + +} + +exports.OTPs = OTPs; \ No newline at end of file diff --git a/lib/b2b/client.ts b/lib/b2b/client.ts index 87a8c40d..6a5f1a32 100644 --- a/lib/b2b/client.ts +++ b/lib/b2b/client.ts @@ -8,6 +8,7 @@ import { JwtConfig } from "../shared/sessions"; import { Discovery } from "./discovery"; import { Passwords } from "./passwords"; import { OAuth } from "./oauth"; +import { OTPs } from "./otps"; export class B2BClient extends BaseClient { protected jwtConfig: JwtConfig; @@ -18,6 +19,7 @@ export class B2BClient extends BaseClient { sso: SSO; discovery: Discovery; passwords: Passwords; + otps: OTPs; constructor(config: ClientConfig) { super(config); @@ -43,5 +45,6 @@ export class B2BClient extends BaseClient { this.discovery = new Discovery(this.fetchConfig); this.passwords = new Passwords(this.fetchConfig); this.oauth = new OAuth(this.fetchConfig); + this.otps = new OTPs(this.fetchConfig); } } diff --git a/lib/b2b/discovery.ts b/lib/b2b/discovery.ts index e8e3d106..c6f7216c 100644 --- a/lib/b2b/discovery.ts +++ b/lib/b2b/discovery.ts @@ -1,6 +1,7 @@ import { MemberSession, ResponseWithMember } from "./shared_b2b"; import { BaseResponse, request, fetchConfig } from "../shared"; import { DiscoveredOrganization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BDiscoveryOrganizationsRequest { intermediate_session_token?: string; @@ -11,6 +12,7 @@ export interface B2BDiscoveryOrganizationsRequest { export interface B2BDiscoveryOrganizationsResponse extends BaseResponse { email_address: string; discovered_organizations: DiscoveredOrganization[]; + organization_id_hint: string | null; } export interface B2BDiscoveryOrganizationCreateRequest { @@ -27,13 +29,17 @@ export interface B2BDiscoveryOrganizationCreateRequest { email_invites?: "ALL_ALLOWED" | "RESTRICTED" | "NOT_ALLOWED"; auth_methods?: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods?: string[]; + mfa_policy?: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface B2BDiscoveryOrganizationCreateResponse extends ResponseWithMember { - member_session: MemberSession; + member_session: MemberSession | null; session_token: string; session_jwt: string; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BDiscoveryIntermediateSessionExchangeRequest { @@ -41,13 +47,17 @@ export interface B2BDiscoveryIntermediateSessionExchangeRequest { organization_id: string; session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any + locale?: "en" | "es" | "pt-br"; } export interface B2BDiscoveryIntermediateSessionExchangeResponse extends ResponseWithMember { - member_session: MemberSession; + member_session: MemberSession | null; session_token: string; session_jwt: string; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } class Organizations { diff --git a/lib/b2b/index.ts b/lib/b2b/index.ts index 1a1fedaf..db1fb6ae 100644 --- a/lib/b2b/index.ts +++ b/lib/b2b/index.ts @@ -119,3 +119,10 @@ export type { SAMLConnection, OIDCConnection, } from "./sso"; + +export type { + B2BOTPsSMSSendRequest, + B2BOTPsSMSSendResponse, + B2BOTPsSMSAuthenticateRequest, + B2BOTPsSMSAuthenticateResponse, +} from "./otps"; diff --git a/lib/b2b/magic_links.ts b/lib/b2b/magic_links.ts index c3473e17..474b217c 100644 --- a/lib/b2b/magic_links.ts +++ b/lib/b2b/magic_links.ts @@ -1,6 +1,7 @@ import { MemberSession, ResponseWithMember } from "./shared_b2b"; import { BaseResponse, fetchConfig, request } from "../shared"; import { DiscoveredOrganization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BMagicLinksLoginOrSignupByEmailRequest { organization_id: string; @@ -39,15 +40,19 @@ export interface B2BMagicLinksAuthenticateRequest { session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any pkce_code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BMagicLinksAuthenticateResponse extends ResponseWithMember { organization_id: string; method_id: string; - member_session?: MemberSession; + member_session: MemberSession | null; session_token?: string; session_jwt?: string; reset_sessions: boolean; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BMagicLinksDiscoveryByEmailRequest { diff --git a/lib/b2b/members.ts b/lib/b2b/members.ts index 8f35b423..62f861e8 100644 --- a/lib/b2b/members.ts +++ b/lib/b2b/members.ts @@ -15,6 +15,8 @@ export interface B2BMemberCreateRequest { untrusted_metadata?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any create_member_as_pending?: boolean; is_breakglass?: boolean; + phone_number?: string; + mfa_enrolled?: boolean; } export type B2BMemberCreateResponse = ResponseWithMember; @@ -34,6 +36,8 @@ export interface B2BMemberUpdateRequest { trusted_metadata?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any untrusted_metadata?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any is_breakglass?: boolean; + phone_number?: string; + mfa_enrolled?: boolean; } export type B2BMemberUpdateResponse = ResponseWithMember; @@ -58,6 +62,14 @@ export type MemberSearchOperand = | { filter_name: "statuses"; filter_value: string[]; + } + | { + filter_name: "member_phone_numbers"; + filter_value: string[]; + } + | { + filter_name: "member_phone_number_fuzzy"; + filter_value: string; }; export interface B2BMemberSearchRequest { @@ -85,6 +97,13 @@ export interface B2BMemberDeleteResponse extends BaseResponse { member_id: string; } +export interface B2BMemberDeletePhoneNumberRequest { + organization_id: string; + member_phone_id: string; +} + +export type B2BMemberDeletePhoneNumberResponse = ResponseWithMember; + export class Members { private base_path: string; private fetchConfig: fetchConfig; @@ -132,4 +151,13 @@ export class Members { data, }); } + + deletePhoneNumber( + data: B2BMemberDeletePhoneNumberRequest + ): Promise { + return request(this.fetchConfig, { + method: "DELETE", + url: `${this.base_path}/${data.organization_id}/members/phone_numbers/${data.member_phone_id}`, + }); + } } diff --git a/lib/b2b/mfa.ts b/lib/b2b/mfa.ts new file mode 100644 index 00000000..05610cf8 --- /dev/null +++ b/lib/b2b/mfa.ts @@ -0,0 +1,8 @@ +export interface MemberOptions { + phone_number: string; +} + +export interface MfaRequired { + member_options: MemberOptions; + secondary_auth_initiated: "sms_otp" | null; +} diff --git a/lib/b2b/oauth.ts b/lib/b2b/oauth.ts index 374361f9..664cf61e 100644 --- a/lib/b2b/oauth.ts +++ b/lib/b2b/oauth.ts @@ -1,6 +1,7 @@ import { MemberSession, Member } from "./shared_b2b"; import { request, BaseResponse, fetchConfig } from "../shared"; import { DiscoveredOrganization, Organization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BOAuthAuthenticateRequest { oauth_token: string; @@ -9,6 +10,7 @@ export interface B2BOAuthAuthenticateRequest { session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any pkce_code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BDiscoveryOAuthAuthenticateRequest { @@ -29,8 +31,11 @@ export interface B2BOAuthAuthenticateResponse extends BaseResponse { organization: Organization; session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; provider_values: ProvidersValues; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface ProvidersValues { diff --git a/lib/b2b/organizations.ts b/lib/b2b/organizations.ts index a34282d1..d9ae3198 100644 --- a/lib/b2b/organizations.ts +++ b/lib/b2b/organizations.ts @@ -1,6 +1,7 @@ import { SearchOperator, ResultsMetadata, Member } from "./shared_b2b"; import { BaseResponse, request, fetchConfig } from "../shared"; import { Members } from "./members"; +import { MfaRequired } from "./mfa"; export type OrganizationSearchOperand = | { @@ -57,6 +58,8 @@ export interface Organization { auth_methods: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods: string[]; + + mfa_policy: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface DiscoveredOrganization { @@ -73,6 +76,10 @@ export interface DiscoveredOrganization { member: Member; }; member_authenticated: boolean; + primary_required: { + allowed_auth_methods: string[]; + }; + mfa_required: MfaRequired; } export interface B2BOrganizationCreateRequest { @@ -86,6 +93,7 @@ export interface B2BOrganizationCreateRequest { email_invites?: "ALL_ALLOWED" | "RESTRICTED" | "NOT_ALLOWED"; auth_methods?: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods?: string[]; + mfa_policy?: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface B2BOrganizationCreateResponse extends BaseResponse { @@ -139,6 +147,8 @@ export interface B2BOrganizationUpdateRequest { auth_methods?: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods?: string[]; + + mfa_policy?: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface B2BOrganizationUpdateResponse extends BaseResponse { diff --git a/lib/b2b/otps.ts b/lib/b2b/otps.ts new file mode 100644 index 00000000..a2541935 --- /dev/null +++ b/lib/b2b/otps.ts @@ -0,0 +1,72 @@ +import { MemberSession, ResponseWithMember } from "./shared_b2b"; +import { fetchConfig, request } from "../shared"; + +export interface B2BOTPsSMSSendRequest { + organization_id: string; + member_id: string; + phone_number?: string; + locale?: "en" | "es" | "pt-br"; +} + +export type B2BOTPsSMSSendResponse = ResponseWithMember; + +export interface B2BOTPsSMSAuthenticateRequest { + organization_id: string; + member_id: string; + code: string; + intermediate_session_token?: string; + session_token?: string; + session_jwt?: string; + session_duration_minutes?: number; + session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any + set_mfa_enrollment?: "enroll" | "unenroll"; +} + +export interface B2BOTPsSMSAuthenticateResponse extends ResponseWithMember { + session_token: string; + session_jwt: string; + member_session: MemberSession; +} + +class SMS { + base_path: string; + delivery = "sms"; + + private fetchConfig: fetchConfig; + + constructor(fetchConfig: fetchConfig, base_path: string) { + this.fetchConfig = fetchConfig; + this.base_path = base_path; + } + + private endpoint(path: string): string { + return `${this.base_path}/${this.delivery}/${path}`; + } + + send(data: B2BOTPsSMSSendRequest): Promise { + return request(this.fetchConfig, { + method: "POST", + url: this.endpoint("send"), + data, + }); + } + + authenticate( + data: B2BOTPsSMSAuthenticateRequest + ): Promise { + return request(this.fetchConfig, { + method: "POST", + url: this.endpoint("authenticate"), + data, + }); + } +} + +export class OTPs { + base_path = "otps"; + sms: SMS; + + constructor(fetchConfig: fetchConfig) { + this.sms = new SMS(fetchConfig, this.base_path); + } +} diff --git a/lib/b2b/passwords.ts b/lib/b2b/passwords.ts index a9a32594..45cb7f6c 100644 --- a/lib/b2b/passwords.ts +++ b/lib/b2b/passwords.ts @@ -1,6 +1,7 @@ import { request, BaseResponse, fetchConfig } from "../shared"; import { MemberSession, ResponseWithMember } from "./shared_b2b"; import * as shared from "../shared/passwords"; +import { MfaRequired } from "./mfa"; export interface B2BPasswordsAuthenticateRequest { organization_id: string; @@ -10,13 +11,17 @@ export interface B2BPasswordsAuthenticateRequest { session_jwt?: string; session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any + locale?: "en" | "es" | "pt-br"; } export interface B2BPasswordsAuthenticateResponse extends ResponseWithMember { organization_id: string; session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BPasswordsEmailResetStartRequest { @@ -43,6 +48,7 @@ export interface B2BPasswordsEmailResetRequest { session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BPasswordsEmailResetResponse extends ResponseWithMember { @@ -50,7 +56,10 @@ export interface B2BPasswordsEmailResetResponse extends ResponseWithMember { organization_id: string; session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BPasswordsExistingPasswordResetRequest { @@ -62,13 +71,17 @@ export interface B2BPasswordsExistingPasswordResetRequest { session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any organization_id: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BPasswordsExistingPasswordResetResponse extends ResponseWithMember { session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BPasswordsSessionResetRequest { diff --git a/lib/b2b/sessions.ts b/lib/b2b/sessions.ts index 99db9034..d27a7f10 100644 --- a/lib/b2b/sessions.ts +++ b/lib/b2b/sessions.ts @@ -3,6 +3,7 @@ import { B2BAuthenticationFactor, Member, MemberSession } from "./shared_b2b"; import * as jose from "jose"; import { authenticateJwtLocal, JwtConfig } from "../shared/sessions"; import { Organization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BSessionsGetRequest { organization_id: string; @@ -59,15 +60,19 @@ export interface B2BSessionsExchangeRequest { session_jwt?: string; session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any + locale?: "en" | "es" | "pt-br"; } export interface B2BSessionsExchangeResponse extends BaseResponse { member_id: string; - member_session: MemberSession; + member_session: MemberSession | null; session_token: string; session_jwt: string; member: Member; organization: Organization; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } const organizationClaim = "https://stytch.com/organization"; diff --git a/lib/b2b/shared_b2b.ts b/lib/b2b/shared_b2b.ts index 8a8fa6c8..ddc03bc0 100644 --- a/lib/b2b/shared_b2b.ts +++ b/lib/b2b/shared_b2b.ts @@ -1,4 +1,3 @@ -import { GoogleOAuthFactor, MicrosoftOAuthFactor } from "../b2c/shared_b2c"; import { BaseResponse } from "../shared"; import { Organization } from "./organizations"; @@ -10,11 +9,49 @@ export interface EmailFactor { email_id: string; email_address: string; }; + sequence_order: "PRIMARY" | "SECONDARY"; } + +export interface PhoneNumberFactor { + delivery_method: "sms" | "whatsapp"; + type: string; + last_authenticated_at: string; + phone_number_factor: { + phone_id: string; + phone_number: string; + }; + sequence_order: "PRIMARY" | "SECONDARY"; +} + +export interface GoogleOAuthFactor { + delivery_method: "oauth_google"; + type: string; + last_authenticated_at: string; + google_oauth_factor: { + id: string; + email_id: string; + provider_subject: string; + }; + sequence_order: "PRIMARY" | "SECONDARY"; +} + +export interface MicrosoftOAuthFactor { + delivery_method: "oauth_microsoft"; + type: string; + last_authenticated_at: string; + microsoft_oauth_factor: { + id: string; + email_id: string; + provider_subject: string; + }; + sequence_order: "PRIMARY" | "SECONDARY"; +} + export type B2BAuthenticationFactor = | EmailFactor | GoogleOAuthFactor - | MicrosoftOAuthFactor; + | MicrosoftOAuthFactor + | PhoneNumberFactor; export interface MemberSession { member_session_id: string; member_id: string; @@ -38,6 +75,8 @@ export interface Member { untrusted_metadata: Record; // eslint-disable-line @typescript-eslint/no-explicit-any is_breakglass: boolean; member_password_id: string; + mfa_enrolled: boolean; + mfa_phone_number: string; } export interface SSORegistration { diff --git a/lib/b2b/sso.ts b/lib/b2b/sso.ts index a58aec53..64578759 100644 --- a/lib/b2b/sso.ts +++ b/lib/b2b/sso.ts @@ -3,6 +3,7 @@ import { Member, MemberSession } from "./shared_b2b"; import { SAML } from "./saml"; import { Organization } from "./organizations"; import { OIDC } from "./oidc"; +import { MfaRequired } from "./mfa"; export interface X509Certificate { certificate_id: string; @@ -66,6 +67,7 @@ export interface B2BSSOAuthenticateRequest { session_duration_minutes?: number; session_custom_claims?: Record; // eslint-disable-line @typescript-eslint/no-explicit-any pkce_code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BSSOAuthenticateResponse extends BaseResponse { @@ -75,9 +77,12 @@ export interface B2BSSOAuthenticateResponse extends BaseResponse { method_id: string; session_token?: string; session_jwt?: string; - session?: MemberSession; + session: MemberSession | null; reset_session: boolean; organization: Organization; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export class SSO { diff --git a/package-lock.json b/package-lock.json index 39519a05..54c64e37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "stytch", - "version": "7.2.0", + "version": "7.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "stytch", - "version": "7.2.0", + "version": "7.3.0", "license": "MIT", "dependencies": { "isomorphic-unfetch": "^3.1.0", diff --git a/package.json b/package.json index d712e84b..072c52bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stytch", - "version": "7.2.0", + "version": "7.3.0", "description": "A wrapper for the Stytch API", "types": "./types/lib/index.d.ts", "main": "./dist/index.js", diff --git a/test/b2b/discovery.test.ts b/test/b2b/discovery.test.ts index a0ffa0f5..a41bd207 100644 --- a/test/b2b/discovery.test.ts +++ b/test/b2b/discovery.test.ts @@ -52,6 +52,7 @@ describe("discovery.organizations.create", () => { email_invites: "ALL_ALLOWED", auth_methods: "RESTRICTED", allowed_auth_methods: ["sso"], + mfa_policy: "REQUIRED_FOR_ALL", }) ).resolves.toMatchObject({ method: "POST", @@ -69,6 +70,7 @@ describe("discovery.organizations.create", () => { email_invites: "ALL_ALLOWED", auth_methods: "RESTRICTED", allowed_auth_methods: ["sso"], + mfa_policy: "REQUIRED_FOR_ALL", }, }); }); @@ -81,6 +83,7 @@ describe("discovery.intermediateSessions.exchange", () => { intermediate_session_token: "DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94=", organization_id: "organization-id-1234", + locale: "pt-br", }) ).resolves.toMatchObject({ method: "POST", @@ -89,6 +92,7 @@ describe("discovery.intermediateSessions.exchange", () => { intermediate_session_token: "DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94=", organization_id: "organization-id-1234", + locale: "pt-br", }, }); }); diff --git a/test/b2b/magic_links.test.ts b/test/b2b/magic_links.test.ts index f46700e3..c2d02e7e 100644 --- a/test/b2b/magic_links.test.ts +++ b/test/b2b/magic_links.test.ts @@ -25,6 +25,7 @@ describe("magicLinks.authenticate", () => { magic_links_token: "DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94=", session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", session_duration_minutes: 60, + locale: "es", }) ).resolves.toMatchObject({ method: "POST", @@ -33,6 +34,7 @@ describe("magicLinks.authenticate", () => { magic_links_token: "DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94=", session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", session_duration_minutes: 60, + locale: "es", }, }); }); diff --git a/test/b2b/members.test.ts b/test/b2b/members.test.ts index cb4bd194..8b976428 100644 --- a/test/b2b/members.test.ts +++ b/test/b2b/members.test.ts @@ -17,6 +17,7 @@ describe("members.create", () => { email_address: "test@stytch.com", create_member_as_pending: true, is_breakglass: false, + mfa_enrolled: true, }, }); @@ -34,6 +35,7 @@ describe("members.create", () => { email_address: "test@stytch.com", create_member_as_pending: true, is_breakglass: false, + mfa_enrolled: true, }) ).resolves.toMatchObject({ request_id: "request-id-test-55555555-5555-4555-8555-555555555555", @@ -87,6 +89,7 @@ describe("members.update", () => { organization_id: "organization-id-1234", name: "new name", is_breakglass: true, + mfa_enrolled: true, }, }); @@ -104,6 +107,7 @@ describe("members.update", () => { organization_id: "organization-id-1234", name: "new name", is_breakglass: true, + mfa_enrolled: true, }) ).resolves.toMatchObject({ request_id: "request-id-test-55555555-5555-4555-8555-555555555555", @@ -204,3 +208,32 @@ describe("members.delete", () => { }); }); }); + +describe("members.deletePhoneNumber", () => { + test("success", () => { + mockRequest((req) => { + expect(req).toEqual({ + method: "DELETE", + path: "organizations/organization-id-1234/members/phone_numbers/member-phone-id-1234", + }); + + const data = { + request_id: "request-id-test-55555555-5555-4555-8555-555555555555", + member_id: "member-id-1234", + status_code: 200, + }; + return { status: 200, data }; + }); + + return expect( + members.deletePhoneNumber({ + organization_id: "organization-id-1234", + member_phone_id: "member-phone-id-1234", + }) + ).resolves.toMatchObject({ + request_id: "request-id-test-55555555-5555-4555-8555-555555555555", + member_id: "member-id-1234", + status_code: 200, + }); + }); +}); diff --git a/test/b2b/organizations.test.ts b/test/b2b/organizations.test.ts index edcb004d..4ad947c0 100644 --- a/test/b2b/organizations.test.ts +++ b/test/b2b/organizations.test.ts @@ -33,6 +33,7 @@ describe("organizations.create", () => { email_invites: "ALL_ALLOWED", auth_methods: "RESTRICTED", allowed_auth_methods: ["sso"], + mfa_policy: "OPTIONAL", }) ).resolves.toMatchObject({ method: "POST", @@ -48,6 +49,7 @@ describe("organizations.create", () => { email_invites: "ALL_ALLOWED", auth_methods: "RESTRICTED", allowed_auth_methods: ["sso"], + mfa_policy: "OPTIONAL", }, }); }); @@ -148,6 +150,7 @@ describe("organizations.update", () => { email_invites: "ALL_ALLOWED", auth_methods: "RESTRICTED", allowed_auth_methods: ["sso"], + mfa_policy: "REQUIRED_FOR_ALL", }) ).resolves.toMatchObject({ method: "PUT", @@ -165,6 +168,7 @@ describe("organizations.update", () => { email_invites: "ALL_ALLOWED", auth_methods: "RESTRICTED", allowed_auth_methods: ["sso"], + mfa_policy: "REQUIRED_FOR_ALL", }, }); }); diff --git a/test/b2b/otps.test.ts b/test/b2b/otps.test.ts new file mode 100644 index 00000000..0881eac9 --- /dev/null +++ b/test/b2b/otps.test.ts @@ -0,0 +1,90 @@ +import { OTPs } from "../../lib/b2b/otps"; +import { MOCK_FETCH_CONFIG } from "../helpers"; +import { request } from "../../lib/shared"; + +jest.mock("../../lib/shared"); + +beforeEach(() => { + (request as jest.Mock).mockReset(); + (request as jest.Mock).mockImplementation((_, config) => { + return Promise.resolve({ + method: config.method, + path: config.url, + data: config.data, + params: config.params, + }); + }); +}); + +const otps = new OTPs(MOCK_FETCH_CONFIG); + +describe("otps.sms.send", () => { + test("success", () => { + return expect( + otps.sms.send({ + organization_id: "organization-id-1234", + member_id: "member-id-1234", + phone_number: "555-555-5555", + locale: "es", + }) + ).resolves.toMatchObject({ + method: "POST", + path: "otps/sms/send", + data: { + organization_id: "organization-id-1234", + member_id: "member-id-1234", + phone_number: "555-555-5555", + locale: "es", + }, + }); + }); +}); + +describe("otps.sms.authenticate", () => { + test("intermediate session token", () => { + return expect( + otps.sms.authenticate({ + organization_id: "organization-id-1234", + member_id: "member-id-1234", + code: "1234", + intermediate_session_token: "intermediate-session-token-1234", + session_duration_minutes: 60, + set_mfa_enrollment: "enroll", + }) + ).resolves.toMatchObject({ + method: "POST", + path: "otps/sms/authenticate", + data: { + organization_id: "organization-id-1234", + member_id: "member-id-1234", + code: "1234", + intermediate_session_token: "intermediate-session-token-1234", + session_duration_minutes: 60, + set_mfa_enrollment: "enroll", + }, + }); + }); + test("session", () => { + return expect( + otps.sms.authenticate({ + organization_id: "organization-id-1234", + member_id: "member-id-1234", + code: "1234", + session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", + session_duration_minutes: 60, + set_mfa_enrollment: "unenroll", + }) + ).resolves.toMatchObject({ + method: "POST", + path: "otps/sms/authenticate", + data: { + organization_id: "organization-id-1234", + member_id: "member-id-1234", + code: "1234", + session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", + session_duration_minutes: 60, + set_mfa_enrollment: "unenroll", + }, + }); + }); +}); diff --git a/test/b2b/passwords.test.ts b/test/b2b/passwords.test.ts index 63f068fb..f68c81b6 100644 --- a/test/b2b/passwords.test.ts +++ b/test/b2b/passwords.test.ts @@ -28,6 +28,7 @@ describe("passwords.authenticate", () => { password: "not-a-real-password", session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", session_duration_minutes: 60, + locale: "pt-br", }) ).resolves.toEqual({ method: "POST", @@ -38,6 +39,7 @@ describe("passwords.authenticate", () => { email_address: "Ada_Lovelace@example.com", session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", session_duration_minutes: 60, + locale: "pt-br", }, params: undefined, }); diff --git a/test/b2b/sso.test.ts b/test/b2b/sso.test.ts index bad8e731..4a68d95e 100644 --- a/test/b2b/sso.test.ts +++ b/test/b2b/sso.test.ts @@ -36,6 +36,7 @@ describe("sso.authenticate", () => { sso_token: "DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94=", session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", session_duration_minutes: 60, + locale: "en", }) ).resolves.toMatchObject({ method: "POST", @@ -44,6 +45,7 @@ describe("sso.authenticate", () => { sso_token: "DOYoip3rvIMMW5lgItikFK-Ak1CfMsgjuiCyI7uuU94=", session_token: "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q", session_duration_minutes: 60, + locale: "en", }, }); }); diff --git a/types/lib/b2b/client.d.ts b/types/lib/b2b/client.d.ts index 90f4eae1..339255af 100644 --- a/types/lib/b2b/client.d.ts +++ b/types/lib/b2b/client.d.ts @@ -7,6 +7,7 @@ import { JwtConfig } from "../shared/sessions"; import { Discovery } from "./discovery"; import { Passwords } from "./passwords"; import { OAuth } from "./oauth"; +import { OTPs } from "./otps"; export declare class B2BClient extends BaseClient { protected jwtConfig: JwtConfig; magicLinks: MagicLinks; @@ -16,5 +17,6 @@ export declare class B2BClient extends BaseClient { sso: SSO; discovery: Discovery; passwords: Passwords; + otps: OTPs; constructor(config: ClientConfig); } diff --git a/types/lib/b2b/discovery.d.ts b/types/lib/b2b/discovery.d.ts index 759dc32a..8adbad5a 100644 --- a/types/lib/b2b/discovery.d.ts +++ b/types/lib/b2b/discovery.d.ts @@ -1,6 +1,7 @@ import { MemberSession, ResponseWithMember } from "./shared_b2b"; import { BaseResponse, fetchConfig } from "../shared"; import { DiscoveredOrganization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BDiscoveryOrganizationsRequest { intermediate_session_token?: string; session_token?: string; @@ -9,6 +10,7 @@ export interface B2BDiscoveryOrganizationsRequest { export interface B2BDiscoveryOrganizationsResponse extends BaseResponse { email_address: string; discovered_organizations: DiscoveredOrganization[]; + organization_id_hint: string | null; } export interface B2BDiscoveryOrganizationCreateRequest { intermediate_session_token: string; @@ -24,22 +26,30 @@ export interface B2BDiscoveryOrganizationCreateRequest { email_invites?: "ALL_ALLOWED" | "RESTRICTED" | "NOT_ALLOWED"; auth_methods?: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods?: string[]; + mfa_policy?: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface B2BDiscoveryOrganizationCreateResponse extends ResponseWithMember { - member_session: MemberSession; + member_session: MemberSession | null; session_token: string; session_jwt: string; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BDiscoveryIntermediateSessionExchangeRequest { intermediate_session_token: string; organization_id: string; session_duration_minutes?: number; session_custom_claims?: Record; + locale?: "en" | "es" | "pt-br"; } export interface B2BDiscoveryIntermediateSessionExchangeResponse extends ResponseWithMember { - member_session: MemberSession; + member_session: MemberSession | null; session_token: string; session_jwt: string; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } declare class Organizations { private fetchConfig; diff --git a/types/lib/b2b/index.d.ts b/types/lib/b2b/index.d.ts index a722fbf8..c54469e3 100644 --- a/types/lib/b2b/index.d.ts +++ b/types/lib/b2b/index.d.ts @@ -9,3 +9,4 @@ export type { B2BPasswordsAuthenticateRequest, B2BPasswordsAuthenticateResponse, export type { B2BSAMLCreateConnectionRequest, B2BSAMLCreateConnectionResponse, B2BSAMLUpdateConnectionRequest, B2BSAMLUpdateConnectionResponse, B2BSAMLDeleteVerificationCertificateRequest, B2BSAMLDeleteVerificationCertificateResponse, } from "./saml"; export type { B2BSessionsAuthenticateRequest, B2BSessionsAuthenticateResponse, B2BSessionsGetRequest, B2BSessionsGetResponse, B2BSessionsExchangeRequest, B2BSessionsExchangeResponse, B2BSessionsRevokeRequest, B2BSessionsRevokeResponse, B2BSessionsJwksResponse, } from "./sessions"; export type { B2BSSOAuthenticateRequest, B2BSSOAuthenticateResponse, B2BSSOGetConnectionsRequest, B2BSSOGetConnectionsResponse, B2BSSODeleteConnectionRequest, B2BSSODeleteConnectionResponse, X509Certificate, SAMLConnection, OIDCConnection, } from "./sso"; +export type { B2BOTPsSMSSendRequest, B2BOTPsSMSSendResponse, B2BOTPsSMSAuthenticateRequest, B2BOTPsSMSAuthenticateResponse, } from "./otps"; diff --git a/types/lib/b2b/magic_links.d.ts b/types/lib/b2b/magic_links.d.ts index 8dbed6f0..b82b8ec5 100644 --- a/types/lib/b2b/magic_links.d.ts +++ b/types/lib/b2b/magic_links.d.ts @@ -1,6 +1,7 @@ import { MemberSession, ResponseWithMember } from "./shared_b2b"; import { BaseResponse, fetchConfig } from "../shared"; import { DiscoveredOrganization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BMagicLinksLoginOrSignupByEmailRequest { organization_id: string; email_address: string; @@ -33,14 +34,18 @@ export interface B2BMagicLinksAuthenticateRequest { session_duration_minutes?: number; session_custom_claims?: Record; pkce_code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BMagicLinksAuthenticateResponse extends ResponseWithMember { organization_id: string; method_id: string; - member_session?: MemberSession; + member_session: MemberSession | null; session_token?: string; session_jwt?: string; reset_sessions: boolean; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BMagicLinksDiscoveryByEmailRequest { email_address: string; diff --git a/types/lib/b2b/members.d.ts b/types/lib/b2b/members.d.ts index 624a17f3..e1cd2b73 100644 --- a/types/lib/b2b/members.d.ts +++ b/types/lib/b2b/members.d.ts @@ -9,6 +9,8 @@ export interface B2BMemberCreateRequest { untrusted_metadata?: Record; create_member_as_pending?: boolean; is_breakglass?: boolean; + phone_number?: string; + mfa_enrolled?: boolean; } export declare type B2BMemberCreateResponse = ResponseWithMember; export interface B2BMemberGetRequest { @@ -24,6 +26,8 @@ export interface B2BMemberUpdateRequest { trusted_metadata?: Record; untrusted_metadata?: Record; is_breakglass?: boolean; + phone_number?: string; + mfa_enrolled?: boolean; } export declare type B2BMemberUpdateResponse = ResponseWithMember; export declare type MemberSearchOperand = { @@ -41,6 +45,12 @@ export declare type MemberSearchOperand = { } | { filter_name: "statuses"; filter_value: string[]; +} | { + filter_name: "member_phone_numbers"; + filter_value: string[]; +} | { + filter_name: "member_phone_number_fuzzy"; + filter_value: string; }; export interface B2BMemberSearchRequest { organization_ids: string[]; @@ -63,6 +73,11 @@ export interface B2BMemberDeleteRequest { export interface B2BMemberDeleteResponse extends BaseResponse { member_id: string; } +export interface B2BMemberDeletePhoneNumberRequest { + organization_id: string; + member_phone_id: string; +} +export declare type B2BMemberDeletePhoneNumberResponse = ResponseWithMember; export declare class Members { private base_path; private fetchConfig; @@ -72,4 +87,5 @@ export declare class Members { update(data: B2BMemberUpdateRequest): Promise; delete(data: B2BMemberDeleteRequest): Promise; search(data: B2BMemberSearchRequest): Promise; + deletePhoneNumber(data: B2BMemberDeletePhoneNumberRequest): Promise; } diff --git a/types/lib/b2b/mfa.d.ts b/types/lib/b2b/mfa.d.ts new file mode 100644 index 00000000..d6e44b91 --- /dev/null +++ b/types/lib/b2b/mfa.d.ts @@ -0,0 +1,7 @@ +export interface MemberOptions { + phone_number: string; +} +export interface MfaRequired { + member_options: MemberOptions; + secondary_auth_initiated: "sms_otp" | null; +} diff --git a/types/lib/b2b/oauth.d.ts b/types/lib/b2b/oauth.d.ts index 36e0ece9..37adf08f 100644 --- a/types/lib/b2b/oauth.d.ts +++ b/types/lib/b2b/oauth.d.ts @@ -1,6 +1,7 @@ import { MemberSession, Member } from "./shared_b2b"; import { BaseResponse, fetchConfig } from "../shared"; import { DiscoveredOrganization, Organization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BOAuthAuthenticateRequest { oauth_token: string; session_token?: string; @@ -8,6 +9,7 @@ export interface B2BOAuthAuthenticateRequest { session_duration_minutes?: number; session_custom_claims?: Record; pkce_code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BDiscoveryOAuthAuthenticateRequest { discovery_oauth_token: string; @@ -25,8 +27,11 @@ export interface B2BOAuthAuthenticateResponse extends BaseResponse { organization: Organization; session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; provider_values: ProvidersValues; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface ProvidersValues { access_token?: string; diff --git a/types/lib/b2b/organizations.d.ts b/types/lib/b2b/organizations.d.ts index 20f7552f..73935da6 100644 --- a/types/lib/b2b/organizations.d.ts +++ b/types/lib/b2b/organizations.d.ts @@ -1,6 +1,7 @@ import { SearchOperator, ResultsMetadata, Member } from "./shared_b2b"; import { BaseResponse, fetchConfig } from "../shared"; import { Members } from "./members"; +import { MfaRequired } from "./mfa"; export declare type OrganizationSearchOperand = { filter_name: "organization_ids"; filter_value: string[]; @@ -44,6 +45,7 @@ export interface Organization { email_invites: "ALL_ALLOWED" | "RESTRICTED" | "NOT_ALLOWED"; auth_methods: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods: string[]; + mfa_policy: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface DiscoveredOrganization { organization: Organization; @@ -59,6 +61,10 @@ export interface DiscoveredOrganization { member: Member; }; member_authenticated: boolean; + primary_required: { + allowed_auth_methods: string[]; + }; + mfa_required: MfaRequired; } export interface B2BOrganizationCreateRequest { organization_name: string; @@ -71,6 +77,7 @@ export interface B2BOrganizationCreateRequest { email_invites?: "ALL_ALLOWED" | "RESTRICTED" | "NOT_ALLOWED"; auth_methods?: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods?: string[]; + mfa_policy?: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface B2BOrganizationCreateResponse extends BaseResponse { organization: Organization; @@ -113,6 +120,7 @@ export interface B2BOrganizationUpdateRequest { email_invites?: "ALL_ALLOWED" | "RESTRICTED" | "NOT_ALLOWED"; auth_methods?: "ALL_ALLOWED" | "RESTRICTED"; allowed_auth_methods?: string[]; + mfa_policy?: "OPTIONAL" | "REQUIRED_FOR_ALL"; } export interface B2BOrganizationUpdateResponse extends BaseResponse { organization: Organization; diff --git a/types/lib/b2b/otps.d.ts b/types/lib/b2b/otps.d.ts new file mode 100644 index 00000000..3915b790 --- /dev/null +++ b/types/lib/b2b/otps.d.ts @@ -0,0 +1,40 @@ +import { MemberSession, ResponseWithMember } from "./shared_b2b"; +import { fetchConfig } from "../shared"; +export interface B2BOTPsSMSSendRequest { + organization_id: string; + member_id: string; + phone_number?: string; + locale?: "en" | "es" | "pt-br"; +} +export declare type B2BOTPsSMSSendResponse = ResponseWithMember; +export interface B2BOTPsSMSAuthenticateRequest { + organization_id: string; + member_id: string; + code: string; + intermediate_session_token?: string; + session_token?: string; + session_jwt?: string; + session_duration_minutes?: number; + session_custom_claims?: Record; + set_mfa_enrollment?: "enroll" | "unenroll"; +} +export interface B2BOTPsSMSAuthenticateResponse extends ResponseWithMember { + session_token: string; + session_jwt: string; + member_session: MemberSession; +} +declare class SMS { + base_path: string; + delivery: string; + private fetchConfig; + constructor(fetchConfig: fetchConfig, base_path: string); + private endpoint; + send(data: B2BOTPsSMSSendRequest): Promise; + authenticate(data: B2BOTPsSMSAuthenticateRequest): Promise; +} +export declare class OTPs { + base_path: string; + sms: SMS; + constructor(fetchConfig: fetchConfig); +} +export {}; diff --git a/types/lib/b2b/passwords.d.ts b/types/lib/b2b/passwords.d.ts index 643ae018..74b45b3a 100644 --- a/types/lib/b2b/passwords.d.ts +++ b/types/lib/b2b/passwords.d.ts @@ -1,6 +1,7 @@ import { BaseResponse, fetchConfig } from "../shared"; import { MemberSession, ResponseWithMember } from "./shared_b2b"; import * as shared from "../shared/passwords"; +import { MfaRequired } from "./mfa"; export interface B2BPasswordsAuthenticateRequest { organization_id: string; email_address: string; @@ -9,12 +10,16 @@ export interface B2BPasswordsAuthenticateRequest { session_jwt?: string; session_duration_minutes?: number; session_custom_claims?: Record; + locale?: "en" | "es" | "pt-br"; } export interface B2BPasswordsAuthenticateResponse extends ResponseWithMember { organization_id: string; session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BPasswordsEmailResetStartRequest { organization_id: string; @@ -38,13 +43,17 @@ export interface B2BPasswordsEmailResetRequest { session_duration_minutes?: number; session_custom_claims?: Record; code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BPasswordsEmailResetResponse extends ResponseWithMember { member_email_id: string; organization_id: string; session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BPasswordsExistingPasswordResetRequest { email_address: string; @@ -55,11 +64,15 @@ export interface B2BPasswordsExistingPasswordResetRequest { session_duration_minutes?: number; session_custom_claims?: Record; organization_id: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BPasswordsExistingPasswordResetResponse extends ResponseWithMember { session_token?: string; session_jwt?: string; - member_session?: MemberSession; + member_session: MemberSession | null; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export interface B2BPasswordsSessionResetRequest { password: string; diff --git a/types/lib/b2b/sessions.d.ts b/types/lib/b2b/sessions.d.ts index 0be5e6f5..0c54f999 100644 --- a/types/lib/b2b/sessions.d.ts +++ b/types/lib/b2b/sessions.d.ts @@ -2,6 +2,7 @@ import { BaseResponse, fetchConfig } from "../shared"; import { Member, MemberSession } from "./shared_b2b"; import { JwtConfig } from "../shared/sessions"; import { Organization } from "./organizations"; +import { MfaRequired } from "./mfa"; export interface B2BSessionsGetRequest { organization_id: string; member_id: string; @@ -52,14 +53,18 @@ export interface B2BSessionsExchangeRequest { session_jwt?: string; session_duration_minutes?: number; session_custom_claims?: Record; + locale?: "en" | "es" | "pt-br"; } export interface B2BSessionsExchangeResponse extends BaseResponse { member_id: string; - member_session: MemberSession; + member_session: MemberSession | null; session_token: string; session_jwt: string; member: Member; organization: Organization; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export declare class Sessions { private base_path; diff --git a/types/lib/b2b/shared_b2b.d.ts b/types/lib/b2b/shared_b2b.d.ts index f9549426..6eaaa802 100644 --- a/types/lib/b2b/shared_b2b.d.ts +++ b/types/lib/b2b/shared_b2b.d.ts @@ -1,4 +1,3 @@ -import { GoogleOAuthFactor, MicrosoftOAuthFactor } from "../b2c/shared_b2c"; import { BaseResponse } from "../shared"; import { Organization } from "./organizations"; export interface EmailFactor { @@ -9,8 +8,41 @@ export interface EmailFactor { email_id: string; email_address: string; }; + sequence_order: "PRIMARY" | "SECONDARY"; } -export declare type B2BAuthenticationFactor = EmailFactor | GoogleOAuthFactor | MicrosoftOAuthFactor; +export interface PhoneNumberFactor { + delivery_method: "sms" | "whatsapp"; + type: string; + last_authenticated_at: string; + phone_number_factor: { + phone_id: string; + phone_number: string; + }; + sequence_order: "PRIMARY" | "SECONDARY"; +} +export interface GoogleOAuthFactor { + delivery_method: "oauth_google"; + type: string; + last_authenticated_at: string; + google_oauth_factor: { + id: string; + email_id: string; + provider_subject: string; + }; + sequence_order: "PRIMARY" | "SECONDARY"; +} +export interface MicrosoftOAuthFactor { + delivery_method: "oauth_microsoft"; + type: string; + last_authenticated_at: string; + microsoft_oauth_factor: { + id: string; + email_id: string; + provider_subject: string; + }; + sequence_order: "PRIMARY" | "SECONDARY"; +} +export declare type B2BAuthenticationFactor = EmailFactor | GoogleOAuthFactor | MicrosoftOAuthFactor | PhoneNumberFactor; export interface MemberSession { member_session_id: string; member_id: string; @@ -33,6 +65,8 @@ export interface Member { untrusted_metadata: Record; is_breakglass: boolean; member_password_id: string; + mfa_enrolled: boolean; + mfa_phone_number: string; } export interface SSORegistration { connection_id: string; diff --git a/types/lib/b2b/sso.d.ts b/types/lib/b2b/sso.d.ts index 644d63cc..c0685bcd 100644 --- a/types/lib/b2b/sso.d.ts +++ b/types/lib/b2b/sso.d.ts @@ -3,6 +3,7 @@ import { Member, MemberSession } from "./shared_b2b"; import { SAML } from "./saml"; import { Organization } from "./organizations"; import { OIDC } from "./oidc"; +import { MfaRequired } from "./mfa"; export interface X509Certificate { certificate_id: string; certificate: string; @@ -58,6 +59,7 @@ export interface B2BSSOAuthenticateRequest { session_duration_minutes?: number; session_custom_claims?: Record; pkce_code_verifier?: string; + locale?: "en" | "es" | "pt-br"; } export interface B2BSSOAuthenticateResponse extends BaseResponse { member_id: string; @@ -66,9 +68,12 @@ export interface B2BSSOAuthenticateResponse extends BaseResponse { method_id: string; session_token?: string; session_jwt?: string; - session?: MemberSession; + session: MemberSession | null; reset_session: boolean; organization: Organization; + member_authenticated: boolean; + intermediate_session_token: string; + mfa_required: MfaRequired | null; } export declare class SSO { private readonly fetchConfig;