Skip to content

Commit 56bcf85

Browse files
committed
Add signInWithEmailAndPassword and signInWithEmailLink to auth-next
1 parent 366e9ef commit 56bcf85

File tree

5 files changed

+186
-1
lines changed

5 files changed

+186
-1
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import * as externs from '@firebase/auth-types-exp';
19+
import { signInWithPassword } from '../../api/authentication/email_and_password';
20+
import { signInWithEmailLink } from '../../api/authentication/email_link';
21+
import { Auth } from '../../model/auth';
22+
import { IdTokenResponse } from '../../model/id_token';
23+
import { AuthErrorCode, AUTH_ERROR_FACTORY } from '../errors';
24+
import { EmailAuthProvider } from '../providers/email';
25+
import { debugFail } from '../util/assert';
26+
import { AuthCredential } from '.';
27+
28+
export class EmailAuthCredential implements AuthCredential {
29+
constructor(
30+
readonly email: string,
31+
readonly password: string,
32+
readonly providerId: typeof EmailAuthProvider.PROVIDER_ID,
33+
readonly signInMethod: externs.SignInMethod
34+
) {}
35+
36+
toJSON(): never {
37+
debugFail('Method not implemented.');
38+
}
39+
40+
static fromJSON(_json: object | string): EmailAuthCredential | null {
41+
debugFail('Method not implemented');
42+
}
43+
44+
async _getIdTokenResponse(auth: Auth): Promise<IdTokenResponse> {
45+
switch (this.signInMethod) {
46+
case EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD:
47+
return signInWithPassword(auth, {
48+
returnSecureToken: true,
49+
email: this.email,
50+
password: this.password
51+
});
52+
case EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD:
53+
return signInWithEmailLink(auth, {
54+
email: this.email,
55+
oobCode: this.password
56+
});
57+
default:
58+
throw AUTH_ERROR_FACTORY.create(AuthErrorCode.INTERNAL_ERROR, {
59+
appName: auth.name
60+
});
61+
}
62+
}
63+
64+
async _linkToIdToken(_auth: Auth, _idToken: string): Promise<never> {
65+
debugFail('Method not implemented.');
66+
}
67+
68+
_matchIdTokenWithUid(_auth: Auth, _uid: string): Promise<never> {
69+
debugFail('Method not implemented.');
70+
}
71+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import * as externs from '@firebase/auth-types-exp';
19+
20+
import { Auth } from '../../model/auth';
21+
import { ActionCodeURL } from '../action_code_url';
22+
import { EmailAuthCredential } from '../credentials/email';
23+
import { AuthErrorCode, AUTH_ERROR_FACTORY } from '../errors';
24+
25+
export class EmailAuthProvider implements externs.EmailAuthProvider {
26+
static readonly PROVIDER_ID = externs.ProviderId.PASSWORD;
27+
static readonly EMAIL_PASSWORD_SIGN_IN_METHOD =
28+
externs.SignInMethod.EMAIL_PASSWORD;
29+
static readonly EMAIL_LINK_SIGN_IN_METHOD = externs.SignInMethod.EMAIL_LINK;
30+
readonly providerId: externs.ProviderId = EmailAuthProvider.PROVIDER_ID;
31+
32+
static credential(
33+
email: string,
34+
password: string,
35+
signInMethod?: externs.SignInMethod
36+
): EmailAuthCredential {
37+
return new EmailAuthCredential(
38+
email,
39+
password,
40+
EmailAuthProvider.PROVIDER_ID,
41+
signInMethod || this.EMAIL_PASSWORD_SIGN_IN_METHOD
42+
);
43+
}
44+
45+
static credentialWithLink(
46+
auth: Auth,
47+
email: string,
48+
emailLink: string
49+
): EmailAuthCredential {
50+
const actionCodeUrl = ActionCodeURL._fromLink(auth, emailLink);
51+
if (!actionCodeUrl) {
52+
throw AUTH_ERROR_FACTORY.create(AuthErrorCode.ARGUMENT_ERROR, {
53+
appName: auth.name
54+
});
55+
}
56+
57+
const credential: EmailAuthCredential = this.credential(
58+
email,
59+
actionCodeUrl.code,
60+
EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD
61+
);
62+
63+
// Check if the tenant ID in the email link matches the tenant ID on Auth
64+
// instance.
65+
if (actionCodeUrl.tenantId !== auth.tenantId) {
66+
throw AUTH_ERROR_FACTORY.create(AuthErrorCode.TENANT_ID_MISMATCH, {
67+
appName: auth.name
68+
});
69+
}
70+
71+
return credential;
72+
}
73+
}

packages-exp/auth-exp/src/core/strategies/email_and_password.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import { resetPassword } from '../../api/account_management/email_and_password';
2121
import * as api from '../../api/authentication/email_and_password';
2222
import { Operation } from '../../model/action_code_info';
2323
import { Auth } from '../../model/auth';
24-
import { AUTH_ERROR_FACTORY, AuthErrorCode } from '../errors';
24+
import { AuthErrorCode, AUTH_ERROR_FACTORY } from '../errors';
25+
import { EmailAuthProvider } from '../providers/email';
2526
import { setActionCodeSettingsOnRequest } from './action_code_settings';
27+
import { signInWithCredential } from './credential';
2628

2729
export async function sendPasswordResetEmail(
2830
auth: externs.Auth,
@@ -82,3 +84,14 @@ export async function verifyPasswordResetCode(
8284
// Email should always be present since a code was sent to it
8385
return data.email!;
8486
}
87+
88+
export async function signInWithEmailAndPassword(
89+
auth: externs.Auth,
90+
email: string,
91+
password: string
92+
): Promise<externs.UserCredential> {
93+
return signInWithCredential(
94+
auth,
95+
EmailAuthProvider.credential(email, password)
96+
);
97+
}

packages-exp/auth-exp/src/core/strategies/email_link.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import * as api from '../../api/authentication/email_and_password';
2121
import { Operation } from '../../model/action_code_info';
2222
import { Auth } from '../../model/auth';
2323
import { ActionCodeURL } from '../action_code_url';
24+
import { EmailAuthProvider } from '../providers/email';
25+
import { _getCurrentUrl } from '../util/location';
2426
import { setActionCodeSettingsOnRequest } from './action_code_settings';
27+
import { signInWithCredential } from './credential';
28+
2529

2630
export async function sendSignInLinkToEmail(
2731
auth: externs.Auth,
@@ -46,3 +50,14 @@ export function isSignInWithEmailLink(
4650
const actionCodeUrl = ActionCodeURL._fromLink(auth as Auth, emailLink);
4751
return actionCodeUrl?.operation === Operation.EMAIL_SIGNIN;
4852
}
53+
54+
export async function signInWithEmailLink(
55+
auth: externs.Auth,
56+
email: string,
57+
emailLink?: string
58+
): Promise<externs.UserCredential> {
59+
return signInWithCredential(
60+
auth,
61+
EmailAuthProvider.credentialWithLink(auth as Auth, email, emailLink || _getCurrentUrl())
62+
);
63+
}

packages-exp/auth-types-exp/index.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,16 @@ export interface PhoneInfoOptions {
234234
export interface AuthProvider {
235235
readonly providerId: ProviderId;
236236
}
237+
238+
/**
239+
* A provider for generating email & password and email link credentials
240+
*/
241+
export abstract class EmailAuthProvider implements AuthProvider {
242+
private constructor();
243+
static readonly PROVIDER_ID: string;
244+
static readonly EMAIL_PASSWORD_SIGN_IN_METHOD: string;
245+
static readonly EMAIL_LINK_SIGN_IN_METHOD: string;
246+
static credential(email: string, password: string): AuthCredential;
247+
static credentialWithLink(auth: Auth, email: string, emailLink: string): AuthCredential;
248+
readonly providerId: ProviderId;
249+
}

0 commit comments

Comments
 (0)