Skip to content

GCIP BYO-CIAM Initialize Auth Changes #8995

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions common/api-review/auth.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ export interface Dependencies {
errorMap?: AuthErrorMap;
persistence?: Persistence | Persistence[];
popupRedirectResolver?: PopupRedirectResolver;
tenantConfig?: TenantConfig;
}

// @public
Expand Down Expand Up @@ -795,6 +796,12 @@ export function signInWithRedirect(auth: Auth, provider: AuthProvider, resolver?
// @public
export function signOut(auth: Auth): Promise<void>;

// @public
export interface TenantConfig {
location: string;
tenantId: string;
}

// @public
export interface TotpMultiFactorAssertion extends MultiFactorAssertion {
}
Expand Down
2 changes: 2 additions & 0 deletions docs-devsite/_toc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions docs-devsite/auth.dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>Persistence</code> that the device supports is used. The SDK searches for an existing account in order and, if one is found in a secondary <code>Persistence</code>, the account is moved to the primary <code>Persistence</code>.<!-- -->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 endpoint. It should not be set otherwise. |

## Dependencies.errorMap

Expand Down Expand Up @@ -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 endpoint. It should not be set otherwise.

<b>Signature:</b>

```typescript
tenantConfig?: TenantConfig;
```
1 change: 1 addition & 0 deletions docs-devsite/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>AsyncStorage</code>. |
| [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 <code>sitekey</code>: Firebase Auth provisions a reCAPTCHA for each project and will configure the site key upon rendering.<!-- -->For an invisible reCAPTCHA, set the <code>size</code> key to <code>invisible</code>. |
| [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 <code>factorId</code> of this second factor is [FactorId](./auth.md#factorid)<!-- -->.TOTP. |
| [User](./auth.user.md#user_interface) | A user account. |
Expand Down
46 changes: 46 additions & 0 deletions docs-devsite/auth.tenantconfig.md
Original file line number Diff line number Diff line change
@@ -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.

<b>Signature:</b>

```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.

<b>Signature:</b>

```typescript
location: string;
```

## TenantConfig.tenantId

The tenant Id being used.

<b>Signature:</b>

```typescript
tenantId: string;
```
3 changes: 2 additions & 1 deletion packages/auth/src/core/auth/auth_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
33 changes: 31 additions & 2 deletions packages/auth/src/core/auth/initialize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
AuthProvider,
Persistence as PersistencePublic,
PopupRedirectResolver,
TenantConfig,
UserCredential
} from '../../model/public_types';
import { isNode } from '@firebase/util';
Expand All @@ -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;
Expand Down Expand Up @@ -132,6 +134,11 @@ describe('core/auth/initialize', () => {
const fakePopupRedirectResolver: PopupRedirectResolver =
FakePopupRedirectResolver;

const fakeTenantConfig: TenantConfig = {
'location': 'us',
'tenantId': 'tenant-1'
};

before(() => {
registerAuth(ClientPlatform.BROWSER);
});
Expand Down Expand Up @@ -202,6 +209,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
Expand All @@ -221,13 +237,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);
});
Expand Down Expand Up @@ -264,5 +282,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();
});
});
});
5 changes: 4 additions & 1 deletion packages/auth/src/core/auth/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(':'),
Expand All @@ -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)
Expand Down
22 changes: 22 additions & 0 deletions packages/auth/src/model/public_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,28 @@ export interface Dependencies {
* Which {@link AuthErrorMap} to use.
*/
errorMap?: AuthErrorMap;
/**
* 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;
}

/**
* 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;
}

/**
Expand Down
Loading