UNPKG

@openpass/openpass-js-sdk

Version:
254 lines 16.5 kB
import { OpenPassApiClient } from "./api/openPassApiClient"; import { SignInStateRepository, StorageSessionProvider } from "./signInState"; import InlineSignInForm from "./inlineSignInForm"; import QuickAuth from "./quickAuth"; import RedirectAuth from "./redirect"; import PopupAuth from "./popup"; import SignInButton from "./signInButton"; import DeviceAuthGrant from "./deviceAuthGrant"; import { sendSdkTelemetryInfoEvent } from "./utils/sdkTelemetry"; import SilentAuth from "./silentAuth"; import { addAnalyticsDimension } from "./utils/userAnalytics"; /** * The OpenPassClient, which you can use to authenticate a user with OpenPass. */ export default class OpenPassClient { /** * Creates a new instance of the OpenPassClient. * * @param {OpenPassOptions} options The options to initialize the client. * @param {string} options.clientId The client ID of the application. * @param {string} [options.baseUrl=OpenPass Api Production Url] Optionally set the base URL of the OpenPass API. * @constructor * @returns {OpenPassClient} */ constructor(options) { /** * Displays the quick-auth dialog instantly. * * Important: You will need to have called the renderQuickAuth method before calling this method. */ this.showQuickAuthSignIn = () => this.quickAuth.showInstantly(); /** * Hides the quick-auth dialog instantly. * * Important: You will need to have called the renderQuickAuth method before calling this method. */ this.hideQuickAuthSignIn = () => this.quickAuth.hideInstantly(); this.openPassOptions = options; this.openPassApiClient = new OpenPassApiClient(this.openPassOptions); this.redirect = new RedirectAuth(this.openPassOptions, new SignInStateRepository(new StorageSessionProvider()), this.openPassApiClient); this.popup = new PopupAuth(this.openPassOptions, this.redirect, this.openPassApiClient); this.silentAuth = new SilentAuth(this.openPassOptions, this.openPassApiClient, this.popup); this.inlineSigninform = new InlineSignInForm(this.openPassOptions, this.redirect, this.popup, this.openPassApiClient, this.silentAuth); this.signInButton = new SignInButton(this.redirect, this.popup, this.openPassApiClient); this.quickAuth = new QuickAuth(this.openPassOptions, this.redirect, this.popup, this.openPassApiClient, this.silentAuth); this.deviceAuthGrant = new DeviceAuthGrant(this.openPassOptions, this.openPassApiClient); if ("wasDiscarded" in document && document.wasDiscarded) { sendSdkTelemetryInfoEvent("OpenPassClient.constructor", "SDK initialized from a page that was previously discarded", this.openPassApiClient); } addAnalyticsDimension("op_application_client_id", this.openPassOptions.clientId); } /** * Initiates a full-page redirect OpenPass sign-in. This method first redirects the user to the OpenPass authorization server and then, when authorization is complete, redirects back to the specified redirect URI. * * @param {RedirectSignInOptions} options Sign-in options. * @param {string} options.redirectUrl A valid redirect URI that processes a callback from the OpenPass authorization server. The URL must exactly match a redirect URI you have configured with OpenPass. * @param {SignInClientState} [options.clientState] - The client state that was stored when initiating the authentication flow. Note: This is useful for the redirect authentication flow, to be able to store optional client state and retrieve it when the sign-in completes. * @param {string} [options.loginHint] An optional hint for the login email address identifier the user might log in with. * @param {string} [options.disableLoginHintEditing] If a login hint is provided, this can be set to true to prevent the user from changing the sign-in email address. * @param {Array<CustomQueryParameter>} [options.customQueryParameteres] An optional list of query parameters to send to the authorize endpoint * @returns {Promise<void>} */ async signInWithRedirect(options) { return this.redirect.signIn({ ...options, source: "Custom", }); } /** * Returns `true` if the current page was redirected to by the OpenPass authentication process after a successful or unsuccessful user sign-in. * * @returns {boolean} */ isAuthenticationRedirect() { return this.redirect.isAuthenticationRedirect(); } /** * Call this method to complete the OpenPass authentication flow in response to receiving a callback to a redirect URI from OpenPass. * * @example * * if (openpassClient.isAuthenticationRedirect()) { * try { * // Attempt to complete the sign-in process. * const authResponse = await openpassClient.handleAuthenticationRedirect(); * console.log(authResponse.idToken); * console.log(authResponse.clientState); * } catch (e) { * console.log(e); * } * } * * @returns {Promise<SignInResponse>} */ async handleAuthenticationRedirect() { return this.redirect.handleAuthenticationRedirect(); } /** * Initiates an OpenPass sign-in in a popup window. If the popup windows fails to open, and redirectUrl is supplied as a fallback, then a full-page redirect sign-in will be initiated instead. * * A fallback to a full-page redirect happens in these scenarios: * - If a fallback redirectUrl is supplied. * - If the device width or height is too small. * - If a popup cannot be opened (for example, if blocked). * * Note: In order to use the redirect fallback, you need to configure the redirectUrl as a valid redirectUrl in your application configuration. See the redirect mode documentation for more information. * * ``` * try { * const signInResponse = await openpassClient.signInWithPopup({ * redirectUrl: "[Your_Redirect_URL]", * clientState: "[Your_Client_State]" * }); * console.log(signInResponse.idToken); * console.log(signInResponse.clientState); * } catch (e) { * console.log(e); * } * ``` * @param {PopupSignInOptions} options Sign-in options * @param {string} [options.redirectUrl] An optional valid redirect URI, to use as a fallback if the popup window fails to open, that processes a callback from the OpenPass authorization server. The URL must exactly match a redirect URI you have configured with OpenPass. * @param {SignInClientState} [options.clientState] - The client state that was stored when initiating the authentication flow. Note: This is useful for the redirect authentication flow, to be able to store optional client state and retrieve it when the sign-in completes. * @param {string} [options.loginHint] An optional hint for the login email address identifier the user might log in with. * @param {string} [options.disableLoginHintEditing] If a login hint is provided, this can be set to true to prevent the user from changing the sign-in email address. * @returns {Promise<SignInResponse>} */ async signInWithPopup(options) { return this.popup.signInWithPopup({ ...options, source: "Custom", }); } /** * Attaches the OpenPass inline sign-in form with the specified options. You must supply a valid HTML Div element to attach this form to. * The form contains an email entry input, and a submit button. Once submitted, the form will redirect the user to the OpenPass sign-in form, or display * the OpenPass sign in form popup (depending on the authentication mode option), to finalise the authentication. * @param {InlineSignInOptions} options - The inline sign-in form options. * @param {string} options.parentContainerElementId The ID of the HTML element where the sign-in form is inserted. This is usually a div element large enough to wrap around the sign-in form. * @param {AuthenticationModeType} options.authenticationMode This determines how the sign-in process is handled, either by redirecting the user to a new page or opening a popup window. * @param {string} options.redirectUrl - Specifies the URL to which the user will be redirected when the authentication mode is set to redirect, or optional if set to popup to enable fallback mode to the redirect flow if the popup window fails to open. * @param {SignInClientState} [options.clientState] - The client state that was stored when initiating the authentication flow. Note: This is useful for the redirect authentication flow, to be able to store optional client state and retrieve it when the sign-in completes. * @param {InlineSignInButtonTextOption} [options.signinButtonTextOption] Specifies the text that appears on the sign-in button. * @param {PopupSuccessCallback} [options.popupSuccessCallback] Applies only to the popup option. This function is called when sign-in is successful. It receives a SignInResponse object as a parameter. * @param {PopupFailedCallback} [options.popupFailureCallback] Applies only to the popup option. This function is called when sign-in fails. It receives an SdkError object as a parameter, which contains the error. * @param {PopupSignInInitiatedCallback} [options.popupSignInInitiatedCallback] Applies only to the popup option. This function is called when a sign-in is initiated. * @param {number} [options.widthInPixels] Sets the width of the inline sign-in form iFrame. Defaults to 100% if not specified. * @param {number} [options.heightInPixels] Sets the height of the inline sign-in form iFrame. Defaults to 100% if not specified. * @param {boolean} [options.darkModeEnabled] Enables dark mode for the inline sign-in form. Defaults to false if not specified. * @throws {SdkError} If the required options are missing. */ renderInlineSignInForm(options) { this.inlineSigninform.renderInlineSignInForm(options); } /** * Initializes the quick-auth dialog with the specified options. * * The quick-auth dialog is displayed with a delay (if specified) and can be hidden or displayed on initialization (if specified). * * The form contains an email entry input, and a submit button. Once submitted, the form will redirect the user to the OpenPass sign-in form, or display * the OpenPass sign in form popup (depending on the authentication mode option), to finalize the authentication. * * Note: You must supply a valid HTML Div element to attach this form to. * @param options - The quick-auth dialog options. * @throws {SdkError} If the required options are missing. */ renderQuickAuth(options) { this.quickAuth.render(options); } /** * Renders the Sign-In With OpenPass button in the provided parent container ID. * @param {SignInButtonOptions} options - The sign-in button options. * @param {string} options.parentContainerElementId - Specifies the ID of the HTML element where the sign-in button is inserted. This is usually a div element large enough to wrap around the sign-in button. * @param {AuthenticationModeType} options.authenticationMode This determines how the sign-in process is handled, either by redirecting the user to a new page or opening a popup window. * @param {string} [options.redirectUrl] - Specifies the URL to which the user will be redirected when the authentication mode is set to redirect, or optional if set to popup to enable fallback mode to the redirect flow if the popup window fails to open. * @param {string} [options.loginHint] - An optional hint for the login email address identifier the user might log in with. * @param {SignInClientState} [options.clientState] - The client state that was stored when initiating the authentication flow. Note: This is useful for the redirect authentication flow, to be able to store optional client state and retrieve it when the sign-in completes. * @param {PopupSuccessCallback} [options.popupSuccessCallback] Applies only to the popup option. This function is called when sign-in is successful. It receives a SignInResponse object as a parameter. * @param {PopupFailedCallback} [options.popupFailureCallback] Applies only to the popup option. This function is called when sign-in fails. It receives an SdkError object as a parameter, which contains the error. * @param {SignInButtonShape} [options.shape] Specifies the shape of the button. Defaults to 'standard'. * @param {SignInButtonShapeVariant} [options.shapeVariant] The shape variant of the button. Defaults to 'pill'. * @param {SignInButtonSize} [options.size] The size of the button. Defaults to 'large'. * @param {SignInButtonText} [options.text] The text that appears on the button. Defaults to 'signin_with'. * @param {SignInButtonTheme} [options.theme] The theme of the button. Defaults to 'openpass'. * @param {number} [options.additionalWidth] Additional width to apply to the button. * @throws {SdkError} If the required options are missing. */ renderSignInButton(options) { this.signInButton.renderSignInButton(options); } /** * Initiates the OpenPass device authorization grant. This should be called on the device that wishes to authenticate (e.g. TV). * * Once initiated, prompt the user to finish the authentication on another device by using the user code or verification URI * provided in the result of this method call. * * ``` * try { * const authorizeDeviceData = await openpassClient.authorizeDevice({}); * * // Display this link (via QR code or other means) to the user to complete the authentication on another device. * console.log(authorizeDeviceData.verificationUriComplete); * * } catch (e) { * console.log(e); * } * ``` * @param {AuthorizeDeviceOptions} authorizeDeviceOptions Authorize device options, including specifying the login hint * @returns {Promise<AuthorizeDeviceData>} */ async authorizeDevice(authorizeDeviceOptions) { return await this.deviceAuthGrant.authorizeDevice(authorizeDeviceOptions); } /** * Check the status of the device token request. This should be called on the device that initiated the device authorization grant. * * Once the user has authenticated on another device, this method will return an `ok` status and the OpenPass tokens (ID token, access token). * * If the authentication is stil pending, the status will be `authorization_pending` or `slow_down`. * Poll the endpoint again after the interval provided in the result of the authorizeDevice method.. * * ``` * try { * // Get the device code from the result of the authorizeDevice method. * const authorizeDeviceData = await openpassClient.authorizeDevice({}); * * // wait `authorizeDeviceData.interval` seconds * * // Check the status of the device token request. * const deviceTokenWithStatus = await openpassClient.deviceToken({ deviceCode: authorizeDeviceData.deviceCode }); * * if (deviceTokenWithStatus.status === "ok") { * console.log("User authenticated on another device. Id token: " + deviceTokenWithStatus.tokens.idToken); * * } else if (deviceTokenWithStatus.status === "authorization_pending") { * console.log("Authorization pending..."); * // wait `authorizeDeviceData.interval` seconds before next poll * * } else if (deviceTokenWithStatus.status === "slow_down") { * console.log("Authorization pending, slow down polling..."); * // wait (`authorizeDeviceData.interval` x multiplier) seconds before next poll * } * * } catch (e) { * console.log(e); * } * ``` * @param {DeviceTokenOptions} deviceTokenOptions Device token options, to specify the device code * @returns {Promise<DeviceTokenWithStatus>} */ async deviceToken(deviceTokenOptions) { return await this.deviceAuthGrant.deviceToken(deviceTokenOptions.deviceCode); } } //# sourceMappingURL=openPassClient.js.map