diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 02c3ab0326f..8a354b453ac 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -23,7 +23,7 @@ env: # the behavior to use the new URLs. CHROMEDRIVER_CDNURL: https://googlechromelabs.github.io/ CHROMEDRIVER_CDNBINARIESURL: https://storage.googleapis.com/chrome-for-testing-public - CHROME_VALIDATED_VERSION: linux-132.0.6834.110 + CHROME_VALIDATED_VERSION: linux-141.0.7390.78 CHROME_VERSION_MISMATCH_MESSAGE: "The Chrome version doesn't match the previously validated version. Consider updating CHROME_VALIDATED_VERSION in the GitHub workflow if tests pass, or rollback the installed Chrome version if tests fail." artifactRetentionDays: 14 # Bump Node memory limit diff --git a/.github/workflows/test-changed-auth.yml b/.github/workflows/test-changed-auth.yml index 2ae77916492..d1fbbe1c714 100644 --- a/.github/workflows/test-changed-auth.yml +++ b/.github/workflows/test-changed-auth.yml @@ -23,7 +23,7 @@ env: # the behavior to use the new URLs. CHROMEDRIVER_CDNURL: https://googlechromelabs.github.io/ CHROMEDRIVER_CDNBINARIESURL: https://storage.googleapis.com/chrome-for-testing-public - CHROME_VALIDATED_VERSION: linux-120.0.6099.71 + CHROME_VALIDATED_VERSION: linux-137.0.7151.119 # Bump Node memory limit NODE_OPTIONS: "--max_old_space_size=4096" @@ -119,4 +119,4 @@ jobs: - name: Run tests on changed packages run: yarn test:changed auth env: - BROWSERS: 'WebkitHeadless' \ No newline at end of file + BROWSERS: 'WebkitHeadless' diff --git a/common/api-review/auth.api.md b/common/api-review/auth.api.md index 0c9625a90e9..0976da5172d 100644 --- a/common/api-review/auth.api.md +++ b/common/api-review/auth.api.md @@ -94,7 +94,9 @@ export interface Auth { onIdTokenChanged(nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; setPersistence(persistence: Persistence): Promise; readonly settings: AuthSettings; + setTokenRefreshHandler(tokenRefreshHandler: TokenRefreshHandler): void; signOut(): Promise; + readonly tenantConfig?: TenantConfig; tenantId: string | null; updateCurrentUser(user: User | null): Promise; useDeviceLanguage(): void; @@ -316,6 +318,7 @@ export interface Dependencies { errorMap?: AuthErrorMap; persistence?: Persistence | Persistence[]; popupRedirectResolver?: PopupRedirectResolver; + tenantConfig?: TenantConfig; } // @public @@ -362,6 +365,9 @@ export interface EmulatorConfig { export { ErrorFn } +// @public +export function exchangeToken(auth: Auth, idpConfigId: string, customToken: string): Promise; + // Warning: (ae-forgotten-export) The symbol "BaseOAuthProvider" needs to be exported by the entry point index.d.ts // // @public @@ -729,6 +735,12 @@ export class RecaptchaVerifier implements ApplicationVerifierInternal { verify(): Promise; } +// @public +export interface RefreshIdpTokenResult { + idpConfigId: string; + idToken: string; +} + // @public export function reload(user: User): Promise; @@ -795,6 +807,17 @@ export function signInWithRedirect(auth: Auth, provider: AuthProvider, resolver? // @public export function signOut(auth: Auth): Promise; +// @public +export interface TenantConfig { + location: string; + tenantId: string; +} + +// @public +export interface TokenRefreshHandler { + refreshIdpToken(): Promise; +} + // @public export interface TotpMultiFactorAssertion extends MultiFactorAssertion { } diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 364d5b992c9..561cc3e217b 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -366,8 +366,14 @@ toc: path: /docs/reference/js/auth.recaptchaparameters.md - title: RecaptchaVerifier path: /docs/reference/js/auth.recaptchaverifier.md + - title: RefreshIdpTokenResult + path: /docs/reference/js/auth.refreshidptokenresult.md - title: SAMLAuthProvider path: /docs/reference/js/auth.samlauthprovider.md + - title: TenantConfig + path: /docs/reference/js/auth.tenantconfig.md + - title: TokenRefreshHandler + path: /docs/reference/js/auth.tokenrefreshhandler.md - title: TotpMultiFactorAssertion path: /docs/reference/js/auth.totpmultifactorassertion.md - title: TotpMultiFactorGenerator diff --git a/docs-devsite/auth.auth.md b/docs-devsite/auth.auth.md index cbbc7a9ceb0..1db61201040 100644 --- a/docs-devsite/auth.auth.md +++ b/docs-devsite/auth.auth.md @@ -31,6 +31,7 @@ export interface Auth | [languageCode](./auth.auth.md#authlanguagecode) | string \| null | The [Auth](./auth.auth.md#auth_interface) instance's language code. | | [name](./auth.auth.md#authname) | string | The name of the app associated with the Auth service instance. | | [settings](./auth.auth.md#authsettings) | [AuthSettings](./auth.authsettings.md#authsettings_interface) | The [Auth](./auth.auth.md#auth_interface) instance's settings. | +| [tenantConfig](./auth.auth.md#authtenantconfig) | [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) | The [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) used to initialize a Regional Auth. This is only present if regional auth is initialized and DefaultConfig.REGIONAL_API_HOST backend endpoint is used. | | [tenantId](./auth.auth.md#authtenantid) | string \| null | The [Auth](./auth.auth.md#auth_interface) instance's tenant ID. | ## Methods @@ -42,6 +43,7 @@ export interface Auth | [onAuthStateChanged(nextOrObserver, error, completed)](./auth.auth.md#authonauthstatechanged) | Adds an observer for changes to the user's sign-in state. | | [onIdTokenChanged(nextOrObserver, error, completed)](./auth.auth.md#authonidtokenchanged) | Adds an observer for changes to the signed-in user's ID token. | | [setPersistence(persistence)](./auth.auth.md#authsetpersistence) | Changes the type of persistence on the Auth instance. | +| [setTokenRefreshHandler(tokenRefreshHandler)](./auth.auth.md#authsettokenrefreshhandler) | Registers a handler for refreshing third-party identity provider (IDP) tokens.When the Firebase access token is expired, the SDK will automatically invoke the provided handler's refreshIdpToken() method to obtain a new IDP token. This new token will then be exchanged for a fresh Firebase token, streamlining the authentication process. | | [signOut()](./auth.auth.md#authsignout) | Signs out the current user. This does not automatically revoke the user's ID token. | | [updateCurrentUser(user)](./auth.auth.md#authupdatecurrentuser) | Asynchronously sets the provided user as [Auth.currentUser](./auth.auth.md#authcurrentuser) on the [Auth](./auth.auth.md#auth_interface) instance. | | [useDeviceLanguage()](./auth.auth.md#authusedevicelanguage) | Sets the current language to the default device/browser preference. | @@ -120,6 +122,16 @@ This is used to edit/read configuration related options such as app verification readonly settings: AuthSettings; ``` +## Auth.tenantConfig + +The [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) used to initialize a Regional Auth. This is only present if regional auth is initialized and `DefaultConfig.REGIONAL_API_HOST` backend endpoint is used. + +Signature: + +```typescript +readonly tenantConfig?: TenantConfig; +``` + ## Auth.tenantId The [Auth](./auth.auth.md#auth_interface) instance's tenant ID. @@ -261,6 +273,44 @@ auth.setPersistence(browserSessionPersistence); ``` +## Auth.setTokenRefreshHandler() + +Registers a handler for refreshing third-party identity provider (IDP) tokens. + +When the Firebase access token is expired, the SDK will automatically invoke the provided handler's `refreshIdpToken()` method to obtain a new IDP token. This new token will then be exchanged for a fresh Firebase token, streamlining the authentication process. + +Signature: + +```typescript +setTokenRefreshHandler(tokenRefreshHandler: TokenRefreshHandler): void; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| tokenRefreshHandler | [TokenRefreshHandler](./auth.tokenrefreshhandler.md#tokenrefreshhandler_interface) | An object that implements the TokenRefreshHandler interface, providing the logic to refresh the IDP token. | + +Returns: + +void + +### Example + + +```javascript +class TokenRefreshHandlerImpl { + refreshIdpToken() { + // Logic to fetch a new token from your custom IDP. + // Returns a Promise that resolves with a RefreshIdpTokenResult. + } +} + +const tokenRefreshHandler = new TokenRefreshHandlerImpl(); +auth.setTokenRefreshHandler(tokenRefreshHandler); + +``` + ## Auth.signOut() Signs out the current user. This does not automatically revoke the user's ID token. diff --git a/docs-devsite/auth.dependencies.md b/docs-devsite/auth.dependencies.md index 8d212b7aa1d..d5b098cbedd 100644 --- a/docs-devsite/auth.dependencies.md +++ b/docs-devsite/auth.dependencies.md @@ -29,6 +29,7 @@ export interface Dependencies | [errorMap](./auth.dependencies.md#dependencieserrormap) | [AuthErrorMap](./auth.autherrormap.md#autherrormap_interface) | Which [AuthErrorMap](./auth.autherrormap.md#autherrormap_interface) to use. | | [persistence](./auth.dependencies.md#dependenciespersistence) | [Persistence](./auth.persistence.md#persistence_interface) \| [Persistence](./auth.persistence.md#persistence_interface)\[\] | Which [Persistence](./auth.persistence.md#persistence_interface) to use. If this is an array, the first Persistence that the device supports is used. The SDK searches for an existing account in order and, if one is found in a secondary Persistence, the account is moved to the primary Persistence.If no persistence is provided, the SDK falls back on [inMemoryPersistence](./auth.md#inmemorypersistence). | | [popupRedirectResolver](./auth.dependencies.md#dependenciespopupredirectresolver) | [PopupRedirectResolver](./auth.popupredirectresolver.md#popupredirectresolver_interface) | The [PopupRedirectResolver](./auth.popupredirectresolver.md#popupredirectresolver_interface) to use. This value depends on the platform. Options are [browserPopupRedirectResolver](./auth.md#browserpopupredirectresolver) and [cordovaPopupRedirectResolver](./auth.md#cordovapopupredirectresolver). This field is optional if neither [signInWithPopup()](./auth.md#signinwithpopup_770f816) or [signInWithRedirect()](./auth.md#signinwithredirect_770f816) are being used. | +| [tenantConfig](./auth.dependencies.md#dependenciestenantconfig) | [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) | The [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) to use. This dependency is only required if you want to use regional auth which works with DefaultConfig.REGIONAL_API_HOST endpoint. It should not be set otherwise. | ## Dependencies.errorMap @@ -61,3 +62,13 @@ The [PopupRedirectResolver](./auth.popupredirectresolver.md#popupredirectresolve ```typescript popupRedirectResolver?: PopupRedirectResolver; ``` + +## Dependencies.tenantConfig + +The [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) to use. This dependency is only required if you want to use regional auth which works with `DefaultConfig.REGIONAL_API_HOST` endpoint. It should not be set otherwise. + +Signature: + +```typescript +tenantConfig?: TenantConfig; +``` diff --git a/docs-devsite/auth.md b/docs-devsite/auth.md index 1b3938ef4eb..36446a9a0fe 100644 --- a/docs-devsite/auth.md +++ b/docs-devsite/auth.md @@ -28,6 +28,7 @@ Firebase Authentication | [confirmPasswordReset(auth, oobCode, newPassword)](./auth.md#confirmpasswordreset_749dad8) | Completes the password reset process, given a confirmation code and new password. | | [connectAuthEmulator(auth, url, options)](./auth.md#connectauthemulator_657c7e5) | Changes the [Auth](./auth.auth.md#auth_interface) instance to communicate with the Firebase Auth Emulator, instead of production Firebase Auth services. | | [createUserWithEmailAndPassword(auth, email, password)](./auth.md#createuserwithemailandpassword_21ad33b) | Creates a new user account associated with the specified email address and password. | +| [exchangeToken(auth, idpConfigId, customToken)](./auth.md#exchangetoken_b6b1871) | Asynchronously exchanges an OIDC provider's Authorization code or Id Token for a Firebase Token. | | [fetchSignInMethodsForEmail(auth, email)](./auth.md#fetchsigninmethodsforemail_efb3887) | Gets the list of possible sign in methods for the given email address. This method returns an empty list when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of authentication methods available for the given email. | | [getMultiFactorResolver(auth, error)](./auth.md#getmultifactorresolver_201ba61) | Provides a [MultiFactorResolver](./auth.multifactorresolver.md#multifactorresolver_interface) suitable for completion of a multi-factor flow. | | [getRedirectResult(auth, resolver)](./auth.md#getredirectresult_c35dc1f) | Returns a [UserCredential](./auth.usercredential.md#usercredential_interface) from the redirect-based sign-in flow. | @@ -137,6 +138,9 @@ Firebase Authentication | [PopupRedirectResolver](./auth.popupredirectresolver.md#popupredirectresolver_interface) | A resolver used for handling DOM specific operations like [signInWithPopup()](./auth.md#signinwithpopup_770f816) or [signInWithRedirect()](./auth.md#signinwithredirect_770f816). | | [ReactNativeAsyncStorage](./auth.reactnativeasyncstorage.md#reactnativeasyncstorage_interface) | Interface for a supplied AsyncStorage. | | [RecaptchaParameters](./auth.recaptchaparameters.md#recaptchaparameters_interface) | Interface representing reCAPTCHA parameters.See the [reCAPTCHA docs](https://developers.google.com/recaptcha/docs/display#render_param) for the list of accepted parameters. All parameters are accepted except for sitekey: Firebase Auth provisions a reCAPTCHA for each project and will configure the site key upon rendering.For an invisible reCAPTCHA, set the size key to invisible. | +| [RefreshIdpTokenResult](./auth.refreshidptokenresult.md#refreshidptokenresult_interface) | The result of a third-party IDP token refresh operation.This object contains the new IDP token and the Idp Config ID of the provider that issued it. | +| [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) | The tenant config that can be used to initialize a Regional [Auth](./auth.auth.md#auth_interface) instance. | +| [TokenRefreshHandler](./auth.tokenrefreshhandler.md#tokenrefreshhandler_interface) | An interface for handling the refresh of Firebase tokens. | | [TotpMultiFactorAssertion](./auth.totpmultifactorassertion.md#totpmultifactorassertion_interface) | The class for asserting ownership of a TOTP second factor. Provided by [TotpMultiFactorGenerator.assertionForEnrollment()](./auth.totpmultifactorgenerator.md#totpmultifactorgeneratorassertionforenrollment) and [TotpMultiFactorGenerator.assertionForSignIn()](./auth.totpmultifactorgenerator.md#totpmultifactorgeneratorassertionforsignin). | | [TotpMultiFactorInfo](./auth.totpmultifactorinfo.md#totpmultifactorinfo_interface) | The subclass of the [MultiFactorInfo](./auth.multifactorinfo.md#multifactorinfo_interface) interface for TOTP second factors. The factorId of this second factor is [FactorId](./auth.md#factorid).TOTP. | | [User](./auth.user.md#user_interface) | A user account. | @@ -404,6 +408,34 @@ export declare function createUserWithEmailAndPassword(auth: Auth, email: string Promise<[UserCredential](./auth.usercredential.md#usercredential_interface)> +### exchangeToken(auth, idpConfigId, customToken) {:#exchangetoken_b6b1871} + +Asynchronously exchanges an OIDC provider's Authorization code or Id Token for a Firebase Token. + +This method is implemented only for `DefaultConfig.REGIONAL_API_HOST` and requires [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) to be configured in the [Auth](./auth.auth.md#auth_interface) instance used. + +Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service. + +Signature: + +```typescript +export declare function exchangeToken(auth: Auth, idpConfigId: string, customToken: string): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| auth | [Auth](./auth.auth.md#auth_interface) | The [Auth](./auth.auth.md#auth_interface) instance. | +| idpConfigId | string | The ExternalUserDirectoryId corresponding to the OIDC custom Token. | +| customToken | string | The OIDC provider's Authorization code or Id Token to exchange. | + +Returns: + +Promise<string> + +The firebase access token (JWT signed by Firebase Auth). + ### fetchSignInMethodsForEmail(auth, email) {:#fetchsigninmethodsforemail_efb3887} Gets the list of possible sign in methods for the given email address. This method returns an empty list when [Email Enumeration Protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) is enabled, irrespective of the number of authentication methods available for the given email. diff --git a/docs-devsite/auth.refreshidptokenresult.md b/docs-devsite/auth.refreshidptokenresult.md new file mode 100644 index 00000000000..6b57b573d42 --- /dev/null +++ b/docs-devsite/auth.refreshidptokenresult.md @@ -0,0 +1,48 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# RefreshIdpTokenResult interface +The result of a third-party IDP token refresh operation. + +This object contains the new IDP token and the Idp Config ID of the provider that issued it. + +Signature: + +```typescript +export interface RefreshIdpTokenResult +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [idpConfigId](./auth.refreshidptokenresult.md#refreshidptokenresultidpconfigid) | string | The configuration ID of the third-party identity provider. | +| [idToken](./auth.refreshidptokenresult.md#refreshidptokenresultidtoken) | string | The new Id Token from the 3rd party Identity Provider. | + +## RefreshIdpTokenResult.idpConfigId + +The configuration ID of the third-party identity provider. + +Signature: + +```typescript +idpConfigId: string; +``` + +## RefreshIdpTokenResult.idToken + +The new Id Token from the 3rd party Identity Provider. + +Signature: + +```typescript +idToken: string; +``` diff --git a/docs-devsite/auth.tenantconfig.md b/docs-devsite/auth.tenantconfig.md new file mode 100644 index 00000000000..8ac9d0c7c51 --- /dev/null +++ b/docs-devsite/auth.tenantconfig.md @@ -0,0 +1,46 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TenantConfig interface +The tenant config that can be used to initialize a Regional [Auth](./auth.auth.md#auth_interface) instance. + +Signature: + +```typescript +export interface TenantConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [location](./auth.tenantconfig.md#tenantconfiglocation) | string | Which location to use. | +| [tenantId](./auth.tenantconfig.md#tenantconfigtenantid) | string | The tenant Id being used. | + +## TenantConfig.location + +Which location to use. + +Signature: + +```typescript +location: string; +``` + +## TenantConfig.tenantId + +The tenant Id being used. + +Signature: + +```typescript +tenantId: string; +``` diff --git a/docs-devsite/auth.tokenrefreshhandler.md b/docs-devsite/auth.tokenrefreshhandler.md new file mode 100644 index 00000000000..ad7bddfefb0 --- /dev/null +++ b/docs-devsite/auth.tokenrefreshhandler.md @@ -0,0 +1,43 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# TokenRefreshHandler interface +An interface for handling the refresh of Firebase tokens. + +Signature: + +```typescript +export interface TokenRefreshHandler +``` + +## Methods + +| Method | Description | +| --- | --- | +| [refreshIdpToken()](./auth.tokenrefreshhandler.md#tokenrefreshhandlerrefreshidptoken) | Refreshes the third-party IDP token.This method should contain the logic to obtain a new, valid IDP token from your identity provider. | + +## TokenRefreshHandler.refreshIdpToken() + +Refreshes the third-party IDP token. + +This method should contain the logic to obtain a new, valid IDP token from your identity provider. + +Signature: + +```typescript +refreshIdpToken(): Promise; +``` +Returns: + +Promise<[RefreshIdpTokenResult](./auth.refreshidptokenresult.md#refreshidptokenresult_interface)> + +A promise that resolves with a `RefreshIdpTokenResult` object containing the new IDP token and its corresponding Idp Config ID. + diff --git a/packages/auth/demo/public/index.html b/packages/auth/demo/public/index.html index 78b14b8dd92..9581513551a 100644 --- a/packages/auth/demo/public/index.html +++ b/packages/auth/demo/public/index.html @@ -170,6 +170,13 @@ Action Code Settings +
  • + + BYO-CIAM methods + +