Skip to content

Passwordless #529

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 8 commits into from
Mar 15, 2018
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
16 changes: 16 additions & 0 deletions packages/auth-types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export interface ApplicationVerifier {

export interface AuthCredential {
providerId: string;
signInMethod: string;
}

export interface AuthProvider {
Expand All @@ -109,7 +110,10 @@ export interface ConfirmationResult {

export class EmailAuthProvider extends EmailAuthProvider_Instance {
static PROVIDER_ID: string;
static EMAIL_PASSWORD_SIGN_IN_METHOD: string;
static EMAIL_LINK_SIGN_IN_METHOD: string;
static credential(email: string, password: string): AuthCredential;
static credentialWithLink(email: string, emailLink: string): AuthCredential;
}
export class EmailAuthProvider_Instance implements AuthProvider {
providerId: string;
Expand All @@ -122,6 +126,7 @@ export interface Error {

export class FacebookAuthProvider extends FacebookAuthProvider_Instance {
static PROVIDER_ID: string;
static FACEBOOK_SIGN_IN_METHOD: string;
static credential(token: string): AuthCredential;
}
export class FacebookAuthProvider_Instance implements AuthProvider {
Expand All @@ -132,6 +137,7 @@ export class FacebookAuthProvider_Instance implements AuthProvider {

export class GithubAuthProvider extends GithubAuthProvider_Instance {
static PROVIDER_ID: string;
static GITHUB_SIGN_IN_METHOD: string;
static credential(token: string): AuthCredential;
}
export class GithubAuthProvider_Instance implements AuthProvider {
Expand All @@ -142,6 +148,7 @@ export class GithubAuthProvider_Instance implements AuthProvider {

export class GoogleAuthProvider extends GoogleAuthProvider_Instance {
static PROVIDER_ID: string;
static GOOGLE_SIGN_IN_METHOD: string;
static credential(
idToken?: string | null,
accessToken?: string | null
Expand All @@ -162,6 +169,7 @@ export class OAuthProvider implements AuthProvider {

export class PhoneAuthProvider extends PhoneAuthProvider_Instance {
static PROVIDER_ID: string;
static PHONE_SIGN_IN_METHOD: string;
static credential(
verificationId: string,
verificationCode: string
Expand Down Expand Up @@ -191,6 +199,7 @@ export class RecaptchaVerifier_Instance implements ApplicationVerifier {

export class TwitterAuthProvider extends TwitterAuthProvider_Instance {
static PROVIDER_ID: string;
static TWITTER_SIGN_IN_METHOD: string;
static credential(token: string, secret: string): AuthCredential;
}
export class TwitterAuthProvider_Instance implements AuthProvider {
Expand Down Expand Up @@ -238,6 +247,8 @@ export class FirebaseAuth {
): Promise<any>;
currentUser: User | null;
fetchProvidersForEmail(email: string): Promise<any>;
fetchSignInMethodsForEmail(email: string): Promise<any>;
isSignInWithEmailLink(emailLink: string): boolean;
getRedirectResult(): Promise<any>;
languageCode: string | null;
onAuthStateChanged(
Expand All @@ -250,6 +261,10 @@ export class FirebaseAuth {
error?: (a: Error) => any,
completed?: Unsubscribe
): Unsubscribe;
sendSignInLinkToEmail(
email: string,
actionCodeSettings: ActionCodeSettings
): Promise<any>;
sendPasswordResetEmail(
email: string,
actionCodeSettings?: ActionCodeSettings | null
Expand All @@ -266,6 +281,7 @@ export class FirebaseAuth {
email: string,
password: string
): Promise<any>;
signInWithEmailLink(email: string, emailLink?: string): Promise<any>;
signInWithPhoneNumber(
phoneNumber: string,
applicationVerifier: ApplicationVerifier
Expand Down
52 changes: 52 additions & 0 deletions packages/auth/demo/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,29 @@
</button>
</form>

<!-- Sign in with email link -->
<div class="group">Sign In with Email Link</div>
<form class="form form-bordered no-submit">
<input type="email" name="email" id="sign-in-with-email-link-email"
class="form-control" placeholder="Email" />
<button class="btn btn-block btn-primary"
id="send-sign-in-link-to-email">
Send Sign In With Email Link
</button>
<button class="btn btn-block btn-primary"
id="send-sign-in-link-to-email-current-url">
Send Sign In With Email Link Current URL
</button>
</form>
<form class="form form-bordered no-submit">
<input type="text" name="emailLink" id="sign-in-with-email-link-link"
class="form-control" placeholder="Link" />
<button class="btn btn-block btn-primary"
id="sign-in-with-email-link">
Sign In With Email Link
</button>
</form>

<!-- Password Reset Process -->
<div class="group">Password Reset</div>
<form class="form form-bordered no-submit">
Expand All @@ -280,6 +303,20 @@
Confirm Password Change
</button>
</form>
<!-- Fetch Sign In Methods/Providers -->
<div class="group">Fetch Sign In Methods/Providers</div>
<form class="form form-bordered no-submit">
<input type="email" name="email" id="fetch-providers-email"
class="form-control" placeholder="Email" />
<button class="btn btn-block btn-primary"
id="fetch-sign-in-methods-for-email">
Fetch Sign In Methods For Email
</button>
<button class="btn btn-block btn-primary"
id="fetch-providers-for-email">
Fetch Providers For Email
</button>
</form>
</div>
<div class="tab-pane" id="user-section">
<!-- Profile updates -->
Expand Down Expand Up @@ -359,6 +396,21 @@
</button>
</form>

<form class="form form-bordered no-submit">
<input type="email" name="email" id="link-with-email-link-email"
class="form-control" placeholder="Email" />
<button class="btn btn-block btn-primary"
id="send-link-email-link">
Send Email Link To Link Or Reauthenticate User
</button>
<input type="text" name="emailLink" id="link-with-email-link-link"
class="form-control" placeholder="Link" />
<button class="btn btn-block btn-primary"
id="link-with-email-link">Link With Email Link</button>
<button class="btn btn-block btn-primary"
id="reauth-with-email-link">Reauthenticate With Email Link</button>
</form>

<form class="form form-bordered no-submit">
<input type="text" id="unlinked-provider-id" class="form-control"
placeholder="Provider ID" list="provider-id-options" />
Expand Down
165 changes: 165 additions & 0 deletions packages/auth/demo/public/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,49 @@ function onSignInWithEmailAndPassword() {
}


/**
* Signs in a user with an email link.
*/
function onSignInWithEmailLink() {
var email = $('#sign-in-with-email-link-email').val();
var link = $('#sign-in-with-email-link-link').val() || undefined;
if (auth.isSignInWithEmailLink(link)) {
auth.signInWithEmailLink(email, link).then(onAuthSuccess, onAuthError);
} else {
alertError('Sign in link is invalid');
}
}

/**
* Links a user with an email link.
*/
function onLinkWithEmailLink() {
var email = $('#link-with-email-link-email').val();
var link = $('#link-with-email-link-link').val() || undefined;
var credential = firebase.auth.EmailAuthProvider
.credentialWithLink(email, link);
activeUser().linkAndRetrieveDataWithCredential(credential)
.then(onAuthUserCredentialSuccess, onAuthError);
}


/**
* Re-authenticate a user with email link credential.
*/
function onReauthenticateWithEmailLink() {
var email = $('#link-with-email-link-email').val();
var link = $('#link-with-email-link-link').val() || undefined;
var credential = firebase.auth.EmailAuthProvider
.credentialWithLink(email, link);
activeUser().reauthenticateAndRetrieveDataWithCredential(credential)
.then(function(result) {
logAdditionalUserInfo(result);
refreshUserData();
alertSuccess('User reauthenticated!');
}, onAuthError);
}


/**
* Signs in with a custom token.
* @param {DOMEvent} event HTML DOM event returned by the listener.
Expand Down Expand Up @@ -581,6 +624,52 @@ function onUpdateProfile() {
}


/**
* Sends sign in with email link to the user.
*/
function onSendSignInLinkToEmail() {
var email = $('#sign-in-with-email-link-email').val();
auth.sendSignInLinkToEmail(email, getActionCodeSettings()).then(function() {
alertSuccess('Email sent!');
}, onAuthError);
}

/**
* Sends sign in with email link to the user and pass in current url.
*/
function onSendSignInLinkToEmailCurrentUrl() {
var email = $('#sign-in-with-email-link-email').val();
var actionCodeSettings = {
'url': window.location.href,
'handleCodeInApp': true
};

auth.sendSignInLinkToEmail(email, actionCodeSettings).then(function() {
if ('localStorage' in window && window['localStorage'] !== null) {
window.localStorage.setItem(
'emailForSignIn',
// Save the email and the timestamp.
JSON.stringify({
email: email,
timestamp: new Date().getTime()
}));
}
alertSuccess('Email sent!');
}, onAuthError);
}


/**
* Sends email link to link the user.
*/
function onSendLinkEmailLink() {
var email = $('#link-with-email-link-email').val();
auth.sendSignInLinkToEmail(email, getActionCodeSettings()).then(function() {
alertSuccess('Email sent!');
}, onAuthError);
}


/**
* Sends password reset email to the user.
*/
Expand Down Expand Up @@ -615,6 +704,41 @@ function onConfirmPasswordReset() {
}


/**
* Gets the list of IDPs that can be used to log in for the given email address.
*/
function onFetchProvidersForEmail() {
var email = $('#fetch-providers-email').val();
auth.fetchProvidersForEmail(email).then(function(providers) {
log('Providers for ' + email + ' :');
log(providers);
if (providers.length == 0) {
alertSuccess('Providers for ' + email + ': N/A');
} else {
alertSuccess('Providers for ' + email +': ' + providers.join(', '));
}
}, onAuthError);
}


/**
* Gets the list of possible sign in methods for the given email address.
*/
function onFetchSignInMethodsForEmail() {
var email = $('#fetch-providers-email').val();
auth.fetchSignInMethodsForEmail(email).then(function(signInMethods) {
log('Sign in methods for ' + email + ' :');
log(signInMethods);
if (signInMethods.length == 0) {
alertSuccess('Sign In Methods for ' + email + ': N/A');
} else {
alertSuccess(
'Sign In Methods for ' + email +': ' + signInMethods.join(', '));
}
}, onAuthError);
}


/**
* Fetches and logs the user's providers data.
*/
Expand Down Expand Up @@ -966,13 +1090,43 @@ function getParameterByName(name) {
* the input field for the confirm email verification process.
*/
function populateActionCodes() {
var emailForSignIn = null;
var signInTime = 0;
if ('localStorage' in window && window['localStorage'] !== null) {
try {
// Try to parse as JSON first using new storage format.
var emailForSignInData =
JSON.parse(window.localStorage.getItem('emailForSignIn'));
emailForSignIn = emailForSignInData['email'] || null;
signInTime = emailForSignInData['timestamp'] || 0;
} catch (e) {
// JSON parsing failed. This means the email is stored in the old string
// format.
emailForSignIn = window.localStorage.getItem('emailForSignIn');
}
if (emailForSignIn) {
// Clear old codes. Old format codes should be cleared immediately.
if (new Date().getTime() - signInTime >= 1 * 24 * 3600 * 1000) {
// Remove email from storage.
window.localStorage.removeItem('emailForSignIn');
}
}
}
var actionCode = getParameterByName('oobCode');
if (actionCode != null) {
var mode = getParameterByName('mode');
if (mode == 'verifyEmail') {
$('#email-verification-code').val(actionCode);
} else if (mode == 'resetPassword') {
$('#password-reset-code').val(actionCode);
} else if (mode == 'signIn') {
if (emailForSignIn) {
$('#sign-in-with-email-link-email').val(emailForSignIn);
$('#sign-in-with-email-link-link').val(window.location.href);
onSignInWithEmailLink();
// Remove email from storage as the code is only usable once.
window.localStorage.removeItem('emailForSignIn');
}
} else {
$('#email-verification-code').val(actionCode);
$('#password-reset-code').val(actionCode);
Expand Down Expand Up @@ -1153,11 +1307,19 @@ function initApp(){
e.preventDefault();
}
});
$('#sign-in-with-email-link').click(onSignInWithEmailLink);
$('#link-with-email-link').click(onLinkWithEmailLink);
$('#reauth-with-email-link').click(onReauthenticateWithEmailLink);

$('#change-email').click(onChangeEmail);
$('#change-password').click(onChangePassword);
$('#update-profile').click(onUpdateProfile);

$('#send-sign-in-link-to-email').click(onSendSignInLinkToEmail);
$('#send-sign-in-link-to-email-current-url')
.click(onSendSignInLinkToEmailCurrentUrl);
$('#send-link-email-link').click(onSendLinkEmailLink);

$('#send-password-reset-email').click(onSendPasswordResetEmail);
$('#verify-password-reset-code').click(onVerifyPasswordResetCode);
$('#confirm-password-reset').click(onConfirmPasswordReset);
Expand Down Expand Up @@ -1202,6 +1364,9 @@ function initApp(){

$('#set-language-code').click(onSetLanguageCode);
$('#use-device-language').click(onUseDeviceLanguage);

$('#fetch-providers-for-email').click(onFetchProvidersForEmail);
$('#fetch-sign-in-methods-for-email').click(onFetchSignInMethodsForEmail);
}

$(initApp);
Loading