Add ActionCodeSettings.linkDomain and deprecate ActionCodeSettings.dynamicLinkDomain (#8738)

* Add linkDomain field to ActionCodeSettings (#8428)

* Add linkDomain field to ActionCodeSettings

* Update API reports

* Update error message for ERROR_INVALID_HOSTING_LINK_DOMAIN to include that default hosting domains cannot be used.

* Use constants for test values

---------

Co-authored-by: NhienLam <[email protected]>

* FDL Deprecation & Hosting link Integration Test (#8603)

* Implement Integration test for passwordless email sign-in via firebase-hosting links.

* Add license to new test file created' did not match any files

* Remove unwanted _

* Add support for setting custom hosting link domain in test app (#8614)

* Add afterEach method and apply formatting to the hosting links integration test (#8615)

* Mark ActionCodeSettings.dynamicLinkDomain as deprecated

* Add changeset

* Update API reports

* Address review comments

* Fix changeset

* Update refdocs and address review comments

* Update deprecated comment

* Add FDL deprecation FAQ link

* Fix linkDomain link in refdocs

---------

Co-authored-by: NhienLam <[email protected]>
Co-authored-by: mansisampat <[email protected]>
This commit is contained in:
Nhien (Ricky) Lam
2025-02-04 14:18:02 -08:00
committed by GitHub
co-authored by NhienLam mansisampat
parent 7bec6a1f4b
commit 0e520b0401
18 changed files with 232 additions and 37 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'firebase': minor
'@firebase/auth-types': minor
'@firebase/auth': minor
---
Added `ActionCodeSettings.linkDomain` to customize the Firebase Hosting link domain that is used in mobile out-of-band email action flows. Also, deprecated `ActionCodeSettings.dynamicLinkDomain`.
+3
View File
@@ -40,11 +40,13 @@ export interface ActionCodeSettings {
minimumVersion?: string;
packageName: string;
};
// @deprecated
dynamicLinkDomain?: string;
handleCodeInApp?: boolean;
iOS?: {
bundleId: string;
};
linkDomain?: string;
url: string;
}
@@ -236,6 +238,7 @@ export const AuthErrorCodes: {
readonly MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version";
readonly INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version";
readonly INVALID_REQ_TYPE: "auth/invalid-req-type";
readonly INVALID_HOSTING_LINK_DOMAIN: "auth/invalid-hosting-link-domain";
};
// @public
+18 -4
View File
@@ -26,13 +26,14 @@ export interface ActionCodeSettings
| [dynamicLinkDomain](./auth.actioncodesettings.md#actioncodesettingsdynamiclinkdomain) | string | When multiple custom dynamic link domains are defined for a project, specify which one to use when the link is to be opened via a specified mobile app (for example, <code>example.page.link</code>). |
| [handleCodeInApp](./auth.actioncodesettings.md#actioncodesettingshandlecodeinapp) | boolean | When set to true, the action code link will be be sent as a Universal Link or Android App Link and will be opened by the app if installed. |
| [iOS](./auth.actioncodesettings.md#actioncodesettingsios) | { bundleId: string; } | Sets the iOS bundle ID. |
| [linkDomain](./auth.actioncodesettings.md#actioncodesettingslinkdomain) | string | The optional custom Firebase Hosting domain to use when the link is to be opened via a specified mobile app. The domain must be configured in Firebase Hosting and owned by the project. This cannot be a default Hosting domain (<code>web.app</code> or <code>firebaseapp.com</code>). |
| [url](./auth.actioncodesettings.md#actioncodesettingsurl) | string | Sets the link continue/state URL. |
## ActionCodeSettings.android
Sets the Android package name.
This will try to open the link in an android app if it is installed. If `installApp` is passed, it specifies whether to install the Android app if the device supports it and the app is not already installed. If this field is provided without a `packageName`<!-- -->, an error is thrown explaining that the `packageName` must be provided in conjunction with this field. If `minimumVersion` is specified, and an older version of the app is installed, the user is taken to the Play Store to upgrade the app.
This will try to open the link in an Android app if it is installed.
<b>Signature:</b>
@@ -46,6 +47,11 @@ android?: {
## ActionCodeSettings.dynamicLinkDomain
> Warning: This API is now obsolete.
>
> Firebase Dynamic Links is deprecated and will be shut down as early as August 2025. Instead, use [ActionCodeSettings.linkDomain](./auth.actioncodesettings.md#actioncodesettingslinkdomain) to set a custom domain for mobile links. Learn more in the [Dynamic Links deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq)<!-- -->.
>
When multiple custom dynamic link domains are defined for a project, specify which one to use when the link is to be opened via a specified mobile app (for example, `example.page.link`<!-- -->).
<b>Signature:</b>
@@ -72,8 +78,6 @@ Sets the iOS bundle ID.
This will try to open the link in an iOS app if it is installed.
App installation is not supported for iOS.
<b>Signature:</b>
```typescript
@@ -82,11 +86,21 @@ iOS?: {
};
```
## ActionCodeSettings.linkDomain
The optional custom Firebase Hosting domain to use when the link is to be opened via a specified mobile app. The domain must be configured in Firebase Hosting and owned by the project. This cannot be a default Hosting domain (`web.app` or `firebaseapp.com`<!-- -->).
<b>Signature:</b>
```typescript
linkDomain?: string;
```
## ActionCodeSettings.url
Sets the link continue/state URL.
This has different meanings in different contexts: - When the link is handled in the web action widgets, this is the deep link in the `continueUrl` query parameter. - When the link is handled in the app directly, this is the `continueUrl` query parameter in the deep link of the Dynamic Link.
This has different meanings in different contexts: - When the link is handled in the web action widgets, this is the deep link in the `continueUrl` query parameter. - When the link is handled in the app directly, this is the `continueUrl` query parameter in the deep link of the Dynamic Link or Hosting link.
<b>Signature:</b>
+1
View File
@@ -1956,6 +1956,7 @@ AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY: {
readonly MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version";
readonly INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version";
readonly INVALID_REQ_TYPE: "auth/invalid-req-type";
readonly INVALID_HOSTING_LINK_DOMAIN: "auth/invalid-hosting-link-domain";
}
```
+1
View File
@@ -130,6 +130,7 @@ export type ActionCodeSettings = {
iOS?: { bundleId: string };
url: string;
dynamicLinkDomain?: string;
linkDomain?: string;
};
export type AdditionalUserInfo = {
+5
View File
@@ -823,6 +823,11 @@
<input type="text" class="form-control" id="ibi" placeholder="iOS Bundle ID"/>
</div>
</form>
<div class="group">Mobile link</div>
<div class="form-group">
<input type="text" class="form-control" id="hostingLinkDomain"
placeholder="Custom Hosting Link Domain"/>
</div>
<form class="form form-bordered no-submit">
<div class="btn-group radio-block" id="handle-in-app-selection"
data-toggle="buttons">
+6 -1
View File
@@ -49,8 +49,8 @@ import {
signInWithCredential,
signInWithCustomToken,
signInWithEmailAndPassword,
signInWithEmailLink,
TotpMultiFactorGenerator,
TotpSecret,
unlink,
updateEmail,
updatePassword,
@@ -995,6 +995,7 @@ function getActionCodeSettings() {
const installApp = $('input[name=install-app]:checked').val() === 'Yes';
const handleCodeInApp =
$('input[name=handle-in-app]:checked').val() === 'Yes';
const hostingLinkDomain = $('#hostingLinkDomain').val();
if (url || apn || ibi) {
actionCodeSettings['url'] = url;
if (apn) {
@@ -1010,6 +1011,9 @@ function getActionCodeSettings() {
};
}
actionCodeSettings['handleCodeInApp'] = handleCodeInApp;
if (hostingLinkDomain) {
actionCodeSettings['linkDomain'] = hostingLinkDomain;
}
}
return actionCodeSettings;
}
@@ -1020,6 +1024,7 @@ function onActionCodeSettingsReset() {
$('#apn').val('');
$('#amv').val('');
$('#ibi').val('');
$('#hostingLinkDomain').val('');
}
/**
+2 -1
View File
@@ -41,7 +41,8 @@ function getTestFiles(argv) {
return [
'test/integration/flows/totp.test.ts',
'test/integration/flows/password_policy.test.ts',
'test/integration/flows/recaptcha_enterprise.test.ts'
'test/integration/flows/recaptcha_enterprise.test.ts',
'test/integration/flows/hosting_link.test.ts'
];
}
return argv.local
@@ -70,6 +70,7 @@ export interface GetOobCodeRequest {
dynamicLinkDomain?: string;
tenantId?: string;
targetProjectid?: string;
linkDomain?: string;
}
export interface VerifyEmailRequest extends GetOobCodeRequest {
+2 -1
View File
@@ -100,7 +100,8 @@ export const enum ServerError {
MISSING_RECAPTCHA_VERSION = 'MISSING_RECAPTCHA_VERSION',
INVALID_RECAPTCHA_VERSION = 'INVALID_RECAPTCHA_VERSION',
INVALID_REQ_TYPE = 'INVALID_REQ_TYPE',
PASSWORD_DOES_NOT_MEET_REQUIREMENTS = 'PASSWORD_DOES_NOT_MEET_REQUIREMENTS'
PASSWORD_DOES_NOT_MEET_REQUIREMENTS = 'PASSWORD_DOES_NOT_MEET_REQUIREMENTS',
INVALID_HOSTING_LINK_DOMAIN = 'INVALID_HOSTING_LINK_DOMAIN'
}
/**
+8 -3
View File
@@ -134,7 +134,8 @@ export const enum AuthErrorCode {
INVALID_RECAPTCHA_VERSION = 'invalid-recaptcha-version',
INVALID_REQ_TYPE = 'invalid-req-type',
UNSUPPORTED_PASSWORD_POLICY_SCHEMA_VERSION = 'unsupported-password-policy-schema-version',
PASSWORD_DOES_NOT_MEET_REQUIREMENTS = 'password-does-not-meet-requirements'
PASSWORD_DOES_NOT_MEET_REQUIREMENTS = 'password-does-not-meet-requirements',
INVALID_HOSTING_LINK_DOMAIN = 'invalid-hosting-link-domain'
}
function _debugErrorMap(): ErrorMap<AuthErrorCode> {
@@ -387,7 +388,10 @@ function _debugErrorMap(): ErrorMap<AuthErrorCode> {
[AuthErrorCode.UNSUPPORTED_PASSWORD_POLICY_SCHEMA_VERSION]:
'The password policy received from the backend uses a schema version that is not supported by this version of the Firebase SDK.',
[AuthErrorCode.PASSWORD_DOES_NOT_MEET_REQUIREMENTS]:
'The password does not meet the requirements.'
'The password does not meet the requirements.',
[AuthErrorCode.INVALID_HOSTING_LINK_DOMAIN]:
'The provided Hosting link domain is not configured in Firebase Hosting or is not owned by ' +
'the current project. This cannot be a default Hosting domain (`web.app` or `firebaseapp.com`).'
};
}
@@ -598,5 +602,6 @@ export const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = {
MISSING_CLIENT_TYPE: 'auth/missing-client-type',
MISSING_RECAPTCHA_VERSION: 'auth/missing-recaptcha-version',
INVALID_RECAPTCHA_VERSION: 'auth/invalid-recaptcha-version',
INVALID_REQ_TYPE: 'auth/invalid-req-type'
INVALID_REQ_TYPE: 'auth/invalid-req-type',
INVALID_HOSTING_LINK_DOMAIN: 'auth/invalid-hosting-link-domain'
} as const;
@@ -26,6 +26,10 @@ describe('core/strategies/action_code_settings', () => {
let auth: TestAuth;
const request: GetOobCodeRequest = {};
const TEST_BUNDLE_ID = 'my-bundle';
const TEST_FDL_DOMAIN = 'fdl-domain';
const TEST_URL = 'my-url';
beforeEach(async () => {
auth = await testAuth();
});
@@ -35,10 +39,10 @@ describe('core/strategies/action_code_settings', () => {
_setActionCodeSettingsOnRequest(auth, request, {
handleCodeInApp: true,
iOS: {
bundleId: 'my-bundle'
bundleId: TEST_BUNDLE_ID
},
url: '',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: TEST_FDL_DOMAIN
})
).to.throw(FirebaseError, '(auth/invalid-continue-uri)');
});
@@ -48,9 +52,9 @@ describe('core/strategies/action_code_settings', () => {
_setActionCodeSettingsOnRequest(auth, request, {
handleCodeInApp: true,
iOS: {
bundleId: 'my-´bundle'
bundleId: TEST_BUNDLE_ID
},
url: 'my-url'
url: TEST_URL
})
).to.not.throw();
});
@@ -60,14 +64,27 @@ describe('core/strategies/action_code_settings', () => {
_setActionCodeSettingsOnRequest(auth, request, {
handleCodeInApp: true,
iOS: {
bundleId: 'my-´bundle'
bundleId: TEST_BUNDLE_ID
},
url: 'my-url',
url: TEST_URL,
dynamicLinkDomain: ''
})
).to.throw(FirebaseError, '(auth/invalid-dynamic-link-domain)');
});
it('should require a non empty Hosting link URL', () => {
expect(() =>
_setActionCodeSettingsOnRequest(auth, request, {
handleCodeInApp: true,
iOS: {
bundleId: TEST_BUNDLE_ID
},
url: TEST_URL,
linkDomain: ''
})
).to.throw(FirebaseError, '(auth/invalid-hosting-link-domain)');
});
it('should require a non-empty bundle ID', () => {
expect(() =>
_setActionCodeSettingsOnRequest(auth, request, {
@@ -75,8 +92,8 @@ describe('core/strategies/action_code_settings', () => {
iOS: {
bundleId: ''
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
url: TEST_URL,
dynamicLinkDomain: TEST_FDL_DOMAIN
})
).to.throw(FirebaseError, '(auth/missing-ios-bundle-id)');
});
@@ -88,8 +105,8 @@ describe('core/strategies/action_code_settings', () => {
android: {
packageName: ''
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
url: TEST_URL,
dynamicLinkDomain: TEST_FDL_DOMAIN
})
).to.throw(FirebaseError, '(auth/missing-android-pkg-name)');
});
@@ -37,9 +37,16 @@ export function _setActionCodeSettingsOnRequest(
auth,
AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN
);
_assert(
typeof actionCodeSettings.linkDomain === 'undefined' ||
actionCodeSettings.linkDomain.length > 0,
auth,
AuthErrorCode.INVALID_HOSTING_LINK_DOMAIN
);
request.continueUrl = actionCodeSettings.url;
request.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
request.linkDomain = actionCodeSettings.linkDomain;
request.canHandleCodeInApp = actionCodeSettings.handleCodeInApp;
if (actionCodeSettings.iOS) {
@@ -162,7 +162,8 @@ describe('core/strategies/sendEmailVerification', () => {
bundleId: 'my-bundle'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
@@ -170,6 +171,7 @@ describe('core/strategies/sendEmailVerification', () => {
idToken,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
iOSBundleId: 'my-bundle'
});
@@ -190,13 +192,15 @@ describe('core/strategies/sendEmailVerification', () => {
packageName: 'my-package'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
requestType: ActionCodeOperation.VERIFY_EMAIL,
idToken,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
androidInstallApp: false,
androidMinimumVersionCode: 'my-version',
@@ -270,7 +274,8 @@ describe('core/strategies/verifyBeforeUpdateEmail', () => {
bundleId: 'my-bundle'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
@@ -279,6 +284,7 @@ describe('core/strategies/verifyBeforeUpdateEmail', () => {
newEmail,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
iOSBundleId: 'my-bundle'
});
@@ -299,7 +305,8 @@ describe('core/strategies/verifyBeforeUpdateEmail', () => {
packageName: 'my-package'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
requestType: ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL,
@@ -307,6 +314,7 @@ describe('core/strategies/verifyBeforeUpdateEmail', () => {
newEmail,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
androidInstallApp: false,
androidMinimumVersionCode: 'my-version',
@@ -121,7 +121,8 @@ describe('core/strategies/sendPasswordResetEmail', () => {
bundleId: 'my-bundle'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
@@ -129,6 +130,7 @@ describe('core/strategies/sendPasswordResetEmail', () => {
email,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
iOSBundleId: 'my-bundle',
clientType: 'CLIENT_TYPE_WEB'
@@ -149,13 +151,15 @@ describe('core/strategies/sendPasswordResetEmail', () => {
packageName: 'my-package'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
requestType: ActionCodeOperation.PASSWORD_RESET,
email,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
androidInstallApp: false,
androidMinimumVersionCode: 'my-version',
@@ -124,7 +124,8 @@ describe('core/strategies/sendSignInLinkToEmail', () => {
bundleId: 'my-bundle'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
@@ -132,6 +133,7 @@ describe('core/strategies/sendSignInLinkToEmail', () => {
email,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
iOSBundleId: 'my-bundle',
clientType: 'CLIENT_TYPE_WEB'
@@ -152,13 +154,15 @@ describe('core/strategies/sendSignInLinkToEmail', () => {
packageName: 'my-package'
},
url: 'my-url',
dynamicLinkDomain: 'fdl-domain'
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain'
});
expect(mock.calls[0].request).to.eql({
requestType: ActionCodeOperation.EMAIL_SIGNIN,
email,
continueUrl: 'my-url',
dynamicLinkDomain: 'fdl-domain',
linkDomain: 'hosting-link-domain',
canHandleCodeInApp: true,
androidInstallApp: false,
androidMinimumVersionCode: 'my-version',
+14 -9
View File
@@ -462,12 +462,7 @@ export interface ActionCodeSettings {
* Sets the Android package name.
*
* @remarks
* This will try to open the link in an android app if it is
* installed. If `installApp` is passed, it specifies whether to install the Android app if the
* device supports it and the app is not already installed. If this field is provided without
* a `packageName`, an error is thrown explaining that the `packageName` must be provided in
* conjunction with this field. If `minimumVersion` is specified, and an older version of the
* app is installed, the user is taken to the Play Store to upgrade the app.
* This will try to open the link in an Android app if it is installed.
*/
android?: {
installApp?: boolean;
@@ -490,8 +485,6 @@ export interface ActionCodeSettings {
*
* @remarks
* This will try to open the link in an iOS app if it is installed.
*
* App installation is not supported for iOS.
*/
iOS?: {
bundleId: string;
@@ -504,7 +497,7 @@ export interface ActionCodeSettings {
* - When the link is handled in the web action widgets, this is the deep link in the
* `continueUrl` query parameter.
* - When the link is handled in the app directly, this is the `continueUrl` query parameter in
* the deep link of the Dynamic Link.
* the deep link of the Dynamic Link or Hosting link.
*/
url: string;
/**
@@ -513,8 +506,20 @@ export interface ActionCodeSettings {
*
*
* @defaultValue The first domain is automatically selected.
*
* @deprecated Firebase Dynamic Links is deprecated and will be shut down as early as August
* 2025. Instead, use {@link ActionCodeSettings.linkDomain} to set a custom domain for mobile
* links. Learn more in the {@link https://firebase.google.com/support/dynamic-links-faq | Dynamic Links deprecation FAQ}.
*/
dynamicLinkDomain?: string;
/**
* The optional custom Firebase Hosting domain to use when the link is to be opened via
* a specified mobile app. The domain must be configured in Firebase Hosting and owned
* by the project. This cannot be a default Hosting domain (`web.app` or `firebaseapp.com`).
*
* @defaultValue The default Hosting domain will be used (for example, `example.firebaseapp.com`).
*/
linkDomain?: string;
}
/**
@@ -0,0 +1,106 @@
/**
* @license
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// eslint-disable-next-line import/no-extraneous-dependencies
import {
ActionCodeSettings,
Auth,
sendSignInLinkToEmail
} from '@firebase/auth';
import { expect, use } from 'chai';
import {
cleanUpTestInstance,
getTestInstance,
randomEmail
} from '../../helpers/integration/helpers';
import { getEmulatorUrl } from '../../helpers/integration/settings';
import chaiAsPromised from 'chai-as-promised';
import { FirebaseError } from '@firebase/util';
use(chaiAsPromised);
// Assumes mobileLinksConfig.domain is set as "HOSTING_DOMAIN" in the test GCP-project.
describe('Integration test: hosting link validation', () => {
let auth: Auth;
let email: string;
const AUTHORIZED_CUSTOM_DOMAIN = 'localhost/action_code_return';
const ANDROID_PACKAGE_NAME = 'com.google.firebase.test.thin';
const BASE_SETTINGS: ActionCodeSettings = {
url: 'http://' + AUTHORIZED_CUSTOM_DOMAIN,
handleCodeInApp: true,
android: { packageName: ANDROID_PACKAGE_NAME }
};
const VALID_LINK_DOMAIN = 'jscore-sandbox.testdomaindonotuse.com';
const INVALID_LINK_DOMAIN = 'invalid.testdomaindonotuse.com';
const INVALID_LINK_DOMAIN_ERROR = 'auth/invalid-hosting-link-domain';
const TEST_TENANT_ID = 'passpol-tenant-d7hha';
beforeEach(function () {
auth = getTestInstance();
email = randomEmail();
if (getEmulatorUrl()) {
this.skip();
}
});
afterEach(async () => {
await cleanUpTestInstance(auth);
});
it('allows user to sign in with default firebase hosting link', async () => {
// Sends email link to user using default hosting link.
await sendSignInLinkToEmail(auth, email, BASE_SETTINGS);
});
it('allows user to sign in to a tenant with default firebase hosting link', async () => {
auth.tenantId = TEST_TENANT_ID;
// Sends email link to user using default hosting link.
await sendSignInLinkToEmail(auth, email, BASE_SETTINGS);
});
it('allows user to sign in with custom firebase hosting link', async () => {
// Sends email link to user using custom hosting link.
await sendSignInLinkToEmail(auth, email, {
...BASE_SETTINGS,
linkDomain: VALID_LINK_DOMAIN
});
});
it('allows user to sign in to a tenant with custom firebase hosting link', async () => {
// Sends email link to user using custom hosting link.
auth.tenantId = TEST_TENANT_ID;
await sendSignInLinkToEmail(auth, email, {
...BASE_SETTINGS,
linkDomain: VALID_LINK_DOMAIN
});
});
it('sign in with invalid firebase hosting link throws exception', async () => {
// Throws an exception while sening email link to user using invalid hosting link.
await expect(
sendSignInLinkToEmail(auth, email, {
...BASE_SETTINGS,
linkDomain: INVALID_LINK_DOMAIN
})
).to.be.rejectedWith(
FirebaseError,
new RegExp('.*' + INVALID_LINK_DOMAIN_ERROR + '.*')
);
});
});