From 2ff7bfc053c94cbeebb387d9e78bf6242ef24795 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Fri, 2 May 2025 16:50:39 +0530 Subject: [PATCH 1/6] Implement InitializeAuth changes for BYO-CIAM Firebase Auth --- common/api-review/auth.api.md | 7 ++++ docs-devsite/_toc.yaml | 2 ++ docs-devsite/auth.dependencies.md | 11 ++++++ docs-devsite/auth.md | 1 + docs-devsite/auth.tenantconfig.md | 46 ++++++++++++++++++++++++ packages/auth/src/core/auth/auth_impl.ts | 3 +- packages/auth/src/core/auth/register.ts | 5 ++- packages/auth/src/model/public_types.ts | 22 ++++++++++++ 8 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 docs-devsite/auth.tenantconfig.md diff --git a/common/api-review/auth.api.md b/common/api-review/auth.api.md index 0c9625a90e9..a376cc62838 100644 --- a/common/api-review/auth.api.md +++ b/common/api-review/auth.api.md @@ -316,6 +316,7 @@ export interface Dependencies { errorMap?: AuthErrorMap; persistence?: Persistence | Persistence[]; popupRedirectResolver?: PopupRedirectResolver; + tenantConfig?: TenantConfig; } // @public @@ -795,6 +796,12 @@ 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 TotpMultiFactorAssertion extends MultiFactorAssertion { } diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 665222edb9d..f2197ede482 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -155,6 +155,8 @@ toc: path: /docs/reference/js/auth.recaptchaverifier.md - title: SAMLAuthProvider path: /docs/reference/js/auth.samlauthprovider.md + - title: TenantConfig + path: /docs/reference/js/auth.tenantconfig.md - title: TotpMultiFactorAssertion path: /docs/reference/js/auth.totpmultifactorassertion.md - title: TotpMultiFactorGenerator diff --git a/docs-devsite/auth.dependencies.md b/docs-devsite/auth.dependencies.md index 8d212b7aa1d..b8720d7c6d9 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 field is optional and required if Regional Auth Instance needs to be configured. The Auth instance depends on the endpoint. | ## 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 field is optional and required if Regional Auth Instance needs to be configured. The Auth instance depends on the endpoint. + +Signature: + +```typescript +tenantConfig?: TenantConfig; +``` diff --git a/docs-devsite/auth.md b/docs-devsite/auth.md index 1b3938ef4eb..6e87e5c1110 100644 --- a/docs-devsite/auth.md +++ b/docs-devsite/auth.md @@ -137,6 +137,7 @@ 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. | +| [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) | The tenant config that can be used to initialize a Regional [Auth](./auth.auth.md#auth_interface) instance. | | [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. | diff --git a/docs-devsite/auth.tenantconfig.md b/docs-devsite/auth.tenantconfig.md new file mode 100644 index 00000000000..933c6d815ca --- /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/packages/auth/src/core/auth/auth_impl.ts b/packages/auth/src/core/auth/auth_impl.ts index 4a718702110..14c23ae28f3 100644 --- a/packages/auth/src/core/auth/auth_impl.ts +++ b/packages/auth/src/core/auth/auth_impl.ts @@ -91,7 +91,8 @@ interface AsyncAction { export const enum DefaultConfig { TOKEN_API_HOST = 'securetoken.googleapis.com', API_HOST = 'identitytoolkit.googleapis.com', - API_SCHEME = 'https' + API_SCHEME = 'https', + REGIONAL_API_HOST = 'identityplatform.googleapis.com' } export class AuthImpl implements AuthInternal, _FirebaseService { diff --git a/packages/auth/src/core/auth/register.ts b/packages/auth/src/core/auth/register.ts index 9d0d6b4559d..52493945abc 100644 --- a/packages/auth/src/core/auth/register.ts +++ b/packages/auth/src/core/auth/register.ts @@ -68,6 +68,7 @@ export function registerAuth(clientPlatform: ClientPlatform): void { const appCheckServiceProvider = container.getProvider<'app-check-internal'>('app-check-internal'); const { apiKey, authDomain } = app.options; + const tenantConfig = deps?.tenantConfig; _assert( apiKey && !apiKey.includes(':'), @@ -79,7 +80,9 @@ export function registerAuth(clientPlatform: ClientPlatform): void { apiKey, authDomain, clientPlatform, - apiHost: DefaultConfig.API_HOST, + apiHost: tenantConfig?.location + ? DefaultConfig.REGIONAL_API_HOST + : DefaultConfig.API_HOST, tokenApiHost: DefaultConfig.TOKEN_API_HOST, apiScheme: DefaultConfig.API_SCHEME, sdkClientVersion: _getClientVersion(clientPlatform) diff --git a/packages/auth/src/model/public_types.ts b/packages/auth/src/model/public_types.ts index 43942b93d92..dbaa05bf1e9 100644 --- a/packages/auth/src/model/public_types.ts +++ b/packages/auth/src/model/public_types.ts @@ -1260,6 +1260,28 @@ export interface Dependencies { * Which {@link AuthErrorMap} to use. */ errorMap?: AuthErrorMap; + /** + * The {@link TenantConfig} to use. This field is optional and required + * if Regional Auth Instance needs to be configured. The Auth instance depends + * on the {@link DefaultConfig.REGIONAL_API_HOST} endpoint. + */ + tenantConfig?: TenantConfig; +} + +/** + * The tenant config that can be used to initialize a Regional {@link Auth} instance. + * + * @public + */ +export interface TenantConfig { + /** + * Which location to use. + */ + location?: string; + /** + * The tenant Id being used. + */ + tenantId?: string; } /** From e2d7605ec4e78c0f7fb8b0d93b6735822ae3d628 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Mon, 5 May 2025 11:37:07 +0530 Subject: [PATCH 2/6] Removing white space --- packages/auth/src/model/public_types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth/src/model/public_types.ts b/packages/auth/src/model/public_types.ts index dbaa05bf1e9..05d0ef75e5c 100644 --- a/packages/auth/src/model/public_types.ts +++ b/packages/auth/src/model/public_types.ts @@ -1270,7 +1270,7 @@ export interface Dependencies { /** * The tenant config that can be used to initialize a Regional {@link Auth} instance. - * + * * @public */ export interface TenantConfig { From 2d776b9ca06754d110df330d78f368d3df906087 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Tue, 6 May 2025 11:02:37 +0530 Subject: [PATCH 3/6] Addressing review comments --- docs-devsite/auth.dependencies.md | 4 ++-- docs-devsite/auth.tenantconfig.md | 4 ++-- packages/auth/src/model/public_types.ts | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs-devsite/auth.dependencies.md b/docs-devsite/auth.dependencies.md index b8720d7c6d9..b80bd24af20 100644 --- a/docs-devsite/auth.dependencies.md +++ b/docs-devsite/auth.dependencies.md @@ -29,7 +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 field is optional and required if Regional Auth Instance needs to be configured. The Auth instance depends on the endpoint. | +| [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 endpoint. It should not be set otherwise. | ## Dependencies.errorMap @@ -65,7 +65,7 @@ popupRedirectResolver?: PopupRedirectResolver; ## Dependencies.tenantConfig -The [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) to use. This field is optional and required if Regional Auth Instance needs to be configured. The Auth instance depends on the endpoint. +The [TenantConfig](./auth.tenantconfig.md#tenantconfig_interface) to use. This dependency is only required if you want to use regional auth which works with endpoint. It should not be set otherwise. Signature: diff --git a/docs-devsite/auth.tenantconfig.md b/docs-devsite/auth.tenantconfig.md index 933c6d815ca..8ac9d0c7c51 100644 --- a/docs-devsite/auth.tenantconfig.md +++ b/docs-devsite/auth.tenantconfig.md @@ -32,7 +32,7 @@ Which location to use. Signature: ```typescript -location?: string; +location: string; ``` ## TenantConfig.tenantId @@ -42,5 +42,5 @@ The tenant Id being used. Signature: ```typescript -tenantId?: string; +tenantId: string; ``` diff --git a/packages/auth/src/model/public_types.ts b/packages/auth/src/model/public_types.ts index 05d0ef75e5c..ea997c7855f 100644 --- a/packages/auth/src/model/public_types.ts +++ b/packages/auth/src/model/public_types.ts @@ -1261,9 +1261,9 @@ export interface Dependencies { */ errorMap?: AuthErrorMap; /** - * The {@link TenantConfig} to use. This field is optional and required - * if Regional Auth Instance needs to be configured. The Auth instance depends - * on the {@link DefaultConfig.REGIONAL_API_HOST} endpoint. + * The {@link TenantConfig} to use. This dependency is only required + * if you want to use regional auth which works with + * {@link DefaultConfig.REGIONAL_API_HOST} endpoint. It should not be set otherwise. */ tenantConfig?: TenantConfig; } @@ -1277,11 +1277,11 @@ export interface TenantConfig { /** * Which location to use. */ - location?: string; + location: string; /** * The tenant Id being used. */ - tenantId?: string; + tenantId: string; } /** From 02b8e3e73132ba9cc72028ce43a324aeb2d57d1a Mon Sep 17 00:00:00 2001 From: mansisampat Date: Tue, 6 May 2025 11:24:02 +0530 Subject: [PATCH 4/6] Adding Unit test for initializeAuth with TenantConfig dependency --- .../auth/src/core/auth/initialize.test.ts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/auth/src/core/auth/initialize.test.ts b/packages/auth/src/core/auth/initialize.test.ts index f2d4d24c887..f15bacdfaba 100644 --- a/packages/auth/src/core/auth/initialize.test.ts +++ b/packages/auth/src/core/auth/initialize.test.ts @@ -26,6 +26,7 @@ import { AuthProvider, Persistence as PersistencePublic, PopupRedirectResolver, + TenantConfig, UserCredential } from '../../model/public_types'; import { isNode } from '@firebase/util'; @@ -51,6 +52,7 @@ import { ClientPlatform, _getClientVersion } from '../util/version'; import { initializeAuth } from './initialize'; import { registerAuth } from './register'; import { debugErrorMap, prodErrorMap } from '../errors'; +import { DefaultConfig } from './auth_impl'; describe('core/auth/initialize', () => { let fakeApp: FirebaseApp; @@ -132,6 +134,8 @@ describe('core/auth/initialize', () => { const fakePopupRedirectResolver: PopupRedirectResolver = FakePopupRedirectResolver; + const fakeTenantConfig: TenantConfig = {'location': "us", 'tenantId': "tenant-1"}; + before(() => { registerAuth(ClientPlatform.BROWSER); }); @@ -202,6 +206,15 @@ describe('core/auth/initialize', () => { ); }); + it('should set TenantConfig', async() => { + const auth = initializeAuth(fakeApp, { + tenantConfig: fakeTenantConfig + }) as AuthInternal; + await auth._initializationPromise; + + expect(auth.config.apiHost).equal(DefaultConfig.REGIONAL_API_HOST); + }); + it('should abort initialization if deleted synchronously', async () => { const auth = initializeAuth(fakeApp, { popupRedirectResolver: fakePopupRedirectResolver @@ -221,13 +234,15 @@ describe('core/auth/initialize', () => { const auth = initializeAuth(fakeApp, { errorMap: prodErrorMap, persistence: fakeSessionPersistence, - popupRedirectResolver: fakePopupRedirectResolver + popupRedirectResolver: fakePopupRedirectResolver, + tenantConfig: fakeTenantConfig }); expect( initializeAuth(fakeApp, { errorMap: prodErrorMap, persistence: fakeSessionPersistence, - popupRedirectResolver: fakePopupRedirectResolver + popupRedirectResolver: fakePopupRedirectResolver, + tenantConfig: fakeTenantConfig }) ).to.equal(auth); }); @@ -264,5 +279,16 @@ describe('core/auth/initialize', () => { }) ).to.throw(); }); + + it('should throw if called again with different params (TenantConfig)', () => { + initializeAuth(fakeApp, { + tenantConfig: fakeTenantConfig + }); + expect(() => + initializeAuth(fakeApp, { + tenantConfig: undefined + }) + ).to.throw(); + }); }); }); From 0321a140610824703d5ca8476323f2d094cec5dd Mon Sep 17 00:00:00 2001 From: mansisampat Date: Tue, 6 May 2025 12:07:05 +0530 Subject: [PATCH 5/6] Running yarn run demo --- packages/auth/src/core/auth/initialize.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/auth/src/core/auth/initialize.test.ts b/packages/auth/src/core/auth/initialize.test.ts index f15bacdfaba..a09efd8f46c 100644 --- a/packages/auth/src/core/auth/initialize.test.ts +++ b/packages/auth/src/core/auth/initialize.test.ts @@ -134,7 +134,10 @@ describe('core/auth/initialize', () => { const fakePopupRedirectResolver: PopupRedirectResolver = FakePopupRedirectResolver; - const fakeTenantConfig: TenantConfig = {'location': "us", 'tenantId': "tenant-1"}; + const fakeTenantConfig: TenantConfig = { + 'location': 'us', + 'tenantId': 'tenant-1' + }; before(() => { registerAuth(ClientPlatform.BROWSER); @@ -206,7 +209,7 @@ describe('core/auth/initialize', () => { ); }); - it('should set TenantConfig', async() => { + it('should set TenantConfig', async () => { const auth = initializeAuth(fakeApp, { tenantConfig: fakeTenantConfig }) as AuthInternal; From e53dceae86887a8a97e7b9326b4a5ac392ade094 Mon Sep 17 00:00:00 2001 From: mansisampat Date: Tue, 6 May 2025 12:13:05 +0530 Subject: [PATCH 6/6] Update doc --- common/api-review/auth.api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/api-review/auth.api.md b/common/api-review/auth.api.md index a376cc62838..aed0fb619da 100644 --- a/common/api-review/auth.api.md +++ b/common/api-review/auth.api.md @@ -798,8 +798,8 @@ export function signOut(auth: Auth): Promise; // @public export interface TenantConfig { - location?: string; - tenantId?: string; + location: string; + tenantId: string; } // @public