Skip to content

Commit 7ce12f5

Browse files
authored
Release3.5.0 (#532)
* Added support for email link sign-in. * update dependency
1 parent eb969f8 commit 7ce12f5

File tree

130 files changed

+14186
-4295
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+14186
-4295
lines changed

README.md

Lines changed: 227 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,17 @@ Localized versions of the widget are available through the CDN. To use a localiz
6868
localized JS library instead of the default library:
6969

7070
```html
71-
<script src="https://www.gstatic.com/firebasejs/ui/3.4.1/firebase-ui-auth__{LANGUAGE_CODE}.js"></script>
72-
<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/3.4.1/firebase-ui-auth.css" />
71+
<script src="https://www.gstatic.com/firebasejs/ui/3.5.0/firebase-ui-auth__{LANGUAGE_CODE}.js"></script>
72+
<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/3.5.0/firebase-ui-auth.css" />
7373
```
7474

7575
where `{LANGUAGE_CODE}` is replaced by the code of the language you want. For example, the French
7676
version of the library is available at
77-
`https://www.gstatic.com/firebasejs/ui/3.4.1/firebase-ui-auth__fr.js`. The list of available
77+
`https://www.gstatic.com/firebasejs/ui/3.5.0/firebase-ui-auth__fr.js`. The list of available
7878
languages and their respective language codes can be found at [LANGUAGES.md](LANGUAGES.md).
7979

8080
Right-to-left languages also require the right-to-left version of the stylesheet, available at
81-
`https://www.gstatic.com/firebasejs/ui/3.4.1/firebase-ui-auth-rtl.css`, instead of the default
81+
`https://www.gstatic.com/firebasejs/ui/3.5.0/firebase-ui-auth-rtl.css`, instead of the default
8282
stylesheet. The supported right-to-left languages are Arabic (ar), Farsi (fa), and Hebrew (iw).
8383

8484
### Option 2: npm Module
@@ -128,7 +128,7 @@ FirebaseUI includes the following flows:
128128

129129
1. Interaction with Identity Providers such as Google and Facebook
130130
2. Phone number based authentication
131-
3. Sign-up and sign-in with email accounts
131+
3. Sign-up and sign-in with email accounts (email/password and email link)
132132
4. Password reset
133133
5. Prevention of account duplication (activated when
134134
*"One account per email address"* setting is enabled in the
@@ -154,6 +154,7 @@ provider you want to use in their own developer app settings. Please read the
154154
- [Twitter](https://firebase.google.com/docs/auth/web/twitter-login#before_you_begin)
155155
- [Github](https://firebase.google.com/docs/auth/web/github-auth#before_you_begin)
156156
- [Anonymous](https://firebase.google.com/docs/auth/web/anonymous-auth#before_you_begin)
157+
- [Email link](https://firebase.google.com/docs/auth/web/email-link-auth#before_you_begin)
157158

158159
### Starting the sign-in flow
159160

@@ -224,8 +225,9 @@ for a more in-depth example, showcasing a Single Page Application mode.
224225

225226
**This is only relevant for single page apps or apps where the sign-in UI is rendered conditionally (e.g. button click)**
226227

227-
When redirecting back from accountchooser.com or Identity Providers like Google
228-
and Facebook, `start()` method needs to be called to finish the sign-in flow.
228+
When redirecting back from accountchooser.com, Identity Providers like Google
229+
and Facebook or email link sign-in, `start()` method needs to be called to
230+
finish the sign-in flow.
229231
If it requires a user interaction to start the initial sign-in process, you need to
230232
check if there is a pending redirect operation going on on page load to check whether `start()`
231233
needs to be called.
@@ -562,7 +564,93 @@ ui.start('#firebaseui-auth-container', {
562564

563565
### Configure Email Provider
564566

565-
The `EmailAuthProvider` can be configured to require the user to enter a display name (defaults to `true`).
567+
You can configure either email/password or email/link sign-in with FirebaseUI by
568+
providing the relevant object in the configuration <code>signInOptions</code>
569+
array.
570+
571+
<table>
572+
<thead>
573+
<tr>
574+
<table>
575+
<thead>
576+
<tr>
577+
<th>Name</th>
578+
<th>Type</th>
579+
<th>Required</th>
580+
<th>Description</th>
581+
</tr>
582+
</thead>
583+
<tbody>
584+
<tr>
585+
<td>provider</td>
586+
<td>string</td>
587+
<td>Yes</td>
588+
<td>
589+
For email sign-in, this should be
590+
<code>firebase.auth.EmailAuthProvider.PROVIDER_ID</code>.
591+
</td>
592+
</tr>
593+
<tr>
594+
<td>requireDisplayName</td>
595+
<td>boolean</td>
596+
<td>No</td>
597+
<td>
598+
Defines whether to require the user to provide a display name during email
599+
and password sign up.
600+
<br/>
601+
<em>Default:</em> <code>true</code>
602+
</td>
603+
</tr>
604+
<tr>
605+
<td>signInMethod</td>
606+
<td>string</td>
607+
<td>No</td>
608+
<td>
609+
Defines whether to use email and password or email link authentication.
610+
This should be
611+
<code>firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD</code>
612+
for email and password sign-in,
613+
<code>firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD</code> for
614+
email link authentication.
615+
<br/>
616+
<em>Default:</em>
617+
<code>firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD</code>
618+
</td>
619+
</tr>
620+
<tr>
621+
<td>forceSameDevice</td>
622+
<td>boolean</td>
623+
<td>No</td>
624+
<td>
625+
Whether to force same device flow. If false, opening the link on a different
626+
device will display a message instructing the user to open the link on the
627+
same device or browser. This should be true when used with
628+
anonymous user upgrade flows. This is only relevant to email link sign-in.
629+
<em>Default:</em> <code>false</code>
630+
</td>
631+
</tr>
632+
<tr>
633+
<td>emailLinkSignIn</td>
634+
<td>function</td>
635+
<td>No</td>
636+
<td>
637+
Defines the optional callback function to return
638+
<code>firebase.auth.ActionCodeSettings</code> configuration to use when
639+
sending the link. This provides the ability to specify how the link can be
640+
handled, custom dynamic link, additional state in the deep link, etc.
641+
When not provided, the current URL is used and a web only flow is triggered.
642+
This is only relevant to email link sign-in.
643+
</td>
644+
</tr>
645+
</tbody>
646+
</table>
647+
648+
#### Email and Password
649+
650+
Email and password authentication is the default sign-in method for Email
651+
providers.
652+
The `EmailAuthProvider` with email and password can be configured to require the
653+
user to enter a display name (defaults to `true`).
566654

567655
```javascript
568656
ui.start('#firebaseui-auth-container', {
@@ -575,6 +663,128 @@ ui.start('#firebaseui-auth-container', {
575663
});
576664
```
577665

666+
#### Email Link Authentication
667+
668+
FirebaseUI supports sign-in and sign-up with email links.
669+
Using email link sign-in with FirebaseUI comes with the following benefits:
670+
671+
- End to end support for email link sign-in with only a few configuration lines.
672+
- Enforces security and privacy best practices.
673+
- Ability to force same device flows or allow cross device flows where a user
674+
can start the flow on one device and end it on another. This also covers
675+
Android where email link sign-in is also supported with
676+
[FirebaseUI-android](https://github.com/firebase/firebaseui-android/) and
677+
coming soon to [FirebaseUI-ios](https://github.com/firebase/firebaseui-ios/)
678+
for iOS support.
679+
- Ability to switch to email link sign-in while continuing to sign-in existing
680+
users with email and password.
681+
- Ability to support account linking, where an existing email link user signing
682+
in with Facebook for the first time using the same email will have
683+
both accounts merged so they can sign in with either (Facebook or email link)
684+
going forward.
685+
- Ability to support anonymous user upgrade as long as the flow starts and ends
686+
on the same device. Users opening the link on a different device will be
687+
notified to open the link on the same device where the flow started.
688+
689+
690+
The sample code below demonstrates how to configure email link sign-in with
691+
FirebaseUI. In this example, cross device flows are allowed and additional state
692+
is passed in the URL, as well as the ability to configure the link to open via
693+
mobile application too.
694+
695+
```javascript
696+
ui.start('#firebaseui-auth-container', {
697+
signInOptions: [
698+
{
699+
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
700+
// Use email link authentication and do not require password.
701+
// Note this setting affects new users only.
702+
// For pre-existing users, they will still be prompted to provide their
703+
// passwords on sign-in.
704+
signInMethod: firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD,
705+
// Allow the user the ability to complete sign-in cross device, including
706+
// the mobile apps specified in the ActionCodeSettings object below.
707+
forceSameDevice: false,
708+
// Used to define the optional firebase.auth.ActionCodeSettings if
709+
// additional state needs to be passed along request and whether to open
710+
// the link in a mobile app if it is installed.
711+
emailLinkSignIn: function() {
712+
return {
713+
// Additional state showPromo=1234 can be retrieved from URL on
714+
// sign-in completion in signInSuccess callback by checking
715+
// window.location.href.
716+
url: 'https://www.example.com/completeSignIn?showPromo=1234',
717+
// Custom FDL domain.
718+
dynamicLinkDomain: 'example.page.link',
719+
// Always true for email link sign-in.
720+
handleCodeInApp: true,
721+
// Whether to handle link in iOS app if installed.
722+
iOS: {
723+
bundleId: 'com.example.ios'
724+
},
725+
// Whether to handle link in Android app if opened in an Android
726+
// device.
727+
android: {
728+
packageName: 'com.example.android',
729+
installApp: true,
730+
minimumVersion: '12'
731+
}
732+
};
733+
}
734+
}
735+
]
736+
});
737+
```
738+
739+
When rendering the sign-in UI conditionally (relevant for single page apps),
740+
use `ui.isPendingRedirect()` to detect if the URL corresponds to a sign-in with
741+
email link and the UI needs to be rendered to complete sign-in.
742+
You can also just use
743+
[firebase.auth().isSignInWithEmailLink(window.location.href)](https://firebase.google.com/docs/reference/js/firebase.auth.Auth#isSignInWithEmailLink).
744+
745+
```javascript
746+
// Is there an email link sign-in?
747+
if (ui.isPendingRedirect()) {
748+
ui.start('#firebaseui-auth-container', uiConfig);
749+
}
750+
// This can also be done via:
751+
if ((firebase.auth().isSignInWithEmailLink(window.location.href)) {
752+
ui.start('#firebaseui-auth-container', uiConfig);
753+
}
754+
```
755+
756+
Additional state passed in the <code>url</code> can be retrieved on sign-in
757+
completion via the signInSuccess callbacks.
758+
759+
```javascript
760+
// ...
761+
signInSuccessWithAuthResult: function(authResult, redirectUrl) {
762+
// If a user signed in with email link, ?showPromo=1234 can be obtained from
763+
// window.location.href.
764+
// ...
765+
return false;
766+
}
767+
```
768+
769+
FirebaseUI uses the
770+
[history API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to
771+
clear the URL from query parameters related to email link sign-in after the
772+
one-time code is processed. This prevents the user from re-triggering the
773+
sign-in completion flow again on page reload or if the user signs out and tries
774+
to sign in again in a single page application, etc.
775+
776+
When same device flows are not enforced, a user going through account linking
777+
flow (eg. user signing in with Facebook with an email that belongs to an
778+
existing email link user) opening the link on a different device would be given
779+
the choice to continue sign-in with email link without merging the Facebook
780+
credential or instructed to open the link on the same device where the flow was
781+
initiated to successfully merge both accounts.
782+
783+
You cannot use email/password and email/link sign-in at the same time. Only one
784+
mode can be configured at a time. However, if you previously signed up users
785+
with passwords. Switching to email/link will only apply to new users and
786+
existing password users will continue to be prompted for password on sign-in.
787+
578788
### Configure Phone Provider
579789
580790
The `PhoneAuthProvider` can be configured with custom reCAPTCHA parameters
@@ -866,6 +1076,13 @@ anonymousUser.linkWithCredential(permanentCredential);
8661076
The user will retain the same `uid` at the end of the flow and all data keyed
8671077
on that identifier would still be associated with that same user.
8681078
1079+
Anonymous user upgrade is also supported by email link sign-in in FirebaseUI.
1080+
An anonymous user triggering the email link option will, on return from clicking
1081+
the link, upgrade to an email link user.
1082+
However, `forceSameDevice` must be set to `true` in the email `signInOption`.
1083+
This is to ensure that when the user clicks the link, it is opened on the same
1084+
device/browser where the initial anonymous user exists.
1085+
8691086
#### Handling anonymous user upgrade merge conflicts
8701087
8711088
There are cases when a user, initially signed in anonymously, tries to
@@ -1136,6 +1353,8 @@ FirebaseUI sign-in widget supports Cordova applications. This includes
11361353
email/password and all OAuth providers (Google, Facebook, Twitter and GitHub).
11371354
Phone authentication is not supported due to the limitation in the underlying
11381355
Firebase core SDK.
1356+
Email link authentication is not yet supported due to the inability to detect
1357+
the incoming link when the user clicks it to complete sign-in.
11391358

11401359
### Available providers
11411360

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
feature - Added support for email link sign-in: https://github.com/firebase/firebaseui-web#email-link-authentication.

demo/public/app.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ function getUiConfig() {
6161
{
6262
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
6363
// Whether the display name should be displayed in Sign Up page.
64-
requireDisplayName: true
64+
requireDisplayName: true,
65+
signInMethod: getEmailSignInMethod()
6566
},
6667
{
6768
provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
@@ -91,7 +92,8 @@ ui.disableAutoSignIn();
9192
* @return {string} The URL of the FirebaseUI standalone widget.
9293
*/
9394
function getWidgetUrl() {
94-
return '/widget#recaptcha=' + getRecaptchaMode();
95+
return '/widget#recaptcha=' + getRecaptchaMode() + '&emailSignInMethod=' +
96+
getEmailSignInMethod();
9597
}
9698

9799

@@ -176,12 +178,16 @@ var deleteAccount = function() {
176178

177179

178180
/**
179-
* Handles when the user changes the reCAPTCHA config.
181+
* Handles when the user changes the reCAPTCHA or email signInMethod config.
180182
*/
181-
function handleRecaptchaConfigChange() {
183+
function handleConfigChange() {
182184
var newRecaptchaValue = document.querySelector(
183185
'input[name="recaptcha"]:checked').value;
184-
location.replace(location.pathname + '#recaptcha=' + newRecaptchaValue);
186+
var newEmailSignInMethodValue = document.querySelector(
187+
'input[name="emailSignInMethod"]:checked').value;
188+
location.replace(
189+
location.pathname + '#recaptcha=' + newRecaptchaValue +
190+
'&emailSignInMethod=' + newEmailSignInMethodValue);
185191

186192
// Reset the inline widget so the config changes are reflected.
187193
ui.reset();
@@ -206,13 +212,22 @@ var initApp = function() {
206212
});
207213

208214
document.getElementById('recaptcha-normal').addEventListener(
209-
'change', handleRecaptchaConfigChange);
215+
'change', handleConfigChange);
210216
document.getElementById('recaptcha-invisible').addEventListener(
211-
'change', handleRecaptchaConfigChange);
217+
'change', handleConfigChange);
212218
// Check the selected reCAPTCHA mode.
213219
document.querySelector(
214220
'input[name="recaptcha"][value="' + getRecaptchaMode() + '"]')
215221
.checked = true;
222+
223+
document.getElementById('email-signInMethod-password').addEventListener(
224+
'change', handleConfigChange);
225+
document.getElementById('email-signInMethod-emailLink').addEventListener(
226+
'change', handleConfigChange);
227+
// Check the selected email signInMethod mode.
228+
document.querySelector(
229+
'input[name="emailSignInMethod"][value="' + getEmailSignInMethod() + '"]')
230+
.checked = true;
216231
};
217232

218233
window.addEventListener('load', initApp);

0 commit comments

Comments
 (0)