Skip to content

Commit 267c9b6

Browse files
committed
Add signInWithCredential to auth-next (#2963)
* Add signInWithCredential to auth-next * [AUTOMATED]: Prettier Code Styling * Add conditional delays to auth-next (#2934) * Add conditional delays to auth-next * [AUTOMATED]: Prettier Code Styling * Use typescript asserts keyword for typesafe assertions * [AUTOMATED]: Prettier Code Styling * Rebase conflicts & PR feedback * More PR Feedback * Strip debug asserts from prod builds * [AUTOMATED]: Prettier Code Styling * [AUTOMATED]: API Reports * Fix logic in assertion * Revert merge artifacts * PR Feedback * Cleanup & PR Feedback * [AUTOMATED]: Prettier Code Styling * [AUTOMATED]: License Headers * Add more tests * [AUTOMATED]: Prettier Code Styling * Rebase conflicts * Cleanup type exports * PR feedback * Declare abstract class abstractly
1 parent 42a2089 commit 267c9b6

21 files changed

+507
-81
lines changed

packages-exp/auth-exp/src/api/account_management/account.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { ProviderId } from '@firebase/auth-types-exp';
1819
import { FirebaseError } from '@firebase/util';
1920
import { expect, use } from 'chai';
2021
import * as chaiAsPromised from 'chai-as-promised';
2122
import { Endpoint } from '..';
2223
import { mockEndpoint } from '../../../test/api/helper';
2324
import { mockAuth } from '../../../test/mock_auth';
2425
import * as mockFetch from '../../../test/mock_fetch';
25-
import { ProviderId } from '../../core/providers';
2626
import { ServerError } from '../errors';
2727
import { deleteAccount, deleteLinkedAccounts, getAccountInfo } from './account';
2828

packages-exp/auth-exp/src/api/authentication/custom_token.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { ProviderId } from '@firebase/auth-types-exp';
1819
import { FirebaseError } from '@firebase/util';
1920
import { expect, use } from 'chai';
2021
import * as chaiAsPromised from 'chai-as-promised';
2122
import { Endpoint } from '..';
2223
import { mockEndpoint } from '../../../test/api/helper';
2324
import { mockAuth } from '../../../test/mock_auth';
2425
import * as mockFetch from '../../../test/mock_fetch';
25-
import { ProviderId } from '../../core/providers';
2626
import { ServerError } from '../errors';
2727
import { signInWithCustomToken } from './custom_token';
2828

packages-exp/auth-exp/src/api/authentication/sms.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { ProviderId } from '@firebase/auth-types-exp';
1819
import { FirebaseError } from '@firebase/util';
1920
import { expect, use } from 'chai';
2021
import * as chaiAsPromised from 'chai-as-promised';
2122
import { Endpoint } from '..';
2223
import { mockEndpoint } from '../../../test/api/helper';
2324
import { mockAuth } from '../../../test/mock_auth';
2425
import * as mockFetch from '../../../test/mock_fetch';
25-
import { ProviderId } from '../../core/providers';
2626
import { ServerError } from '../errors';
2727
import {
2828
linkWithPhoneNumber,
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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 { OperationType, ProviderId, SignInMethod } from '@firebase/auth-types-exp';
19+
import { expect, use } from 'chai';
20+
import * as chaiAsPromised from 'chai-as-promised';
21+
import { mockEndpoint } from '../../../test/api/helper';
22+
import { mockAuth } from '../../../test/mock_auth';
23+
import { MockAuthCredential } from '../../../test/mock_auth_credential';
24+
import * as mockFetch from '../../../test/mock_fetch';
25+
import { Endpoint } from '../../api';
26+
import { APIUserInfo } from '../../api/account_management/account';
27+
import { IdTokenResponse } from '../../model/id_token';
28+
import { signInWithCredential } from './credential';
29+
30+
use(chaiAsPromised);
31+
32+
describe('core/strategies/signInWithCredential', () => {
33+
const serverUser: APIUserInfo = {
34+
localId: 'local-id',
35+
displayName: 'display-name',
36+
photoUrl: 'photo-url',
37+
email: 'email',
38+
emailVerified: true,
39+
phoneNumber: 'phone-number',
40+
tenantId: 'tenant-id',
41+
createdAt: 123,
42+
lastLoginAt: 456
43+
};
44+
45+
const idTokenResponse: IdTokenResponse = {
46+
idToken: 'my-id-token',
47+
refreshToken: 'my-refresh-token',
48+
expiresIn: '1234',
49+
localId: serverUser.localId!,
50+
kind: 'my-kind'
51+
};
52+
53+
const authCredential = new MockAuthCredential(
54+
ProviderId.FIREBASE,
55+
SignInMethod.EMAIL_LINK
56+
);
57+
58+
beforeEach(() => {
59+
mockFetch.setUp();
60+
authCredential._setIdTokenResponse(idTokenResponse);
61+
mockEndpoint(Endpoint.GET_ACCOUNT_INFO, {
62+
users: [serverUser]
63+
});
64+
});
65+
afterEach(mockFetch.tearDown);
66+
67+
it('should return a valid user credential', async () => {
68+
const { credential, user, operationType } = await signInWithCredential(
69+
mockAuth,
70+
authCredential
71+
);
72+
expect(credential!.providerId).to.eq(ProviderId.FIREBASE);
73+
expect(credential!.signInMethod).to.eq(SignInMethod.EMAIL_LINK);
74+
expect(user.uid).to.eq('local-id');
75+
expect(user.tenantId).to.eq('tenant-id');
76+
expect(user.displayName).to.eq('display-name');
77+
expect(operationType).to.eq(OperationType.SIGN_IN);
78+
});
79+
80+
it('should update the current user', async () => {
81+
const { user } = await signInWithCredential(mockAuth, authCredential);
82+
expect(mockAuth.currentUser).to.eq(user);
83+
});
84+
});
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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 { OperationType, UserCredential } from '@firebase/auth-types-exp';
19+
import { Auth } from '../../model/auth';
20+
import { AuthCredential } from '../../model/auth_credential';
21+
import { User } from '../../model/user';
22+
import { UserCredentialImpl } from '../user/user_credential_impl';
23+
24+
export async function signInWithCredential(
25+
auth: Auth,
26+
credential: AuthCredential
27+
): Promise<UserCredential> {
28+
// TODO: handle mfa by wrapping with callApiWithMfaContext
29+
const response = await credential._getIdTokenResponse(auth);
30+
const userCredential = await UserCredentialImpl._fromIdTokenResponse(
31+
auth,
32+
credential,
33+
OperationType.SIGN_IN,
34+
response
35+
);
36+
await auth.updateCurrentUser(userCredential.user as User);
37+
return userCredential;
38+
}

packages-exp/auth-exp/src/core/strategies/email.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { ProviderId } from '@firebase/auth-types-exp';
1819
import { FirebaseError } from '@firebase/util';
1920
import { expect, use } from 'chai';
2021
import * as chaiAsPromised from 'chai-as-promised';
@@ -26,7 +27,6 @@ import * as mockFetch from '../../../test/mock_fetch';
2627
import { Endpoint } from '../../api';
2728
import { ServerError } from '../../api/errors';
2829
import { Operation } from '../../model/action_code_info';
29-
import { ProviderId } from '../providers';
3030
import * as location from '../util/location';
3131
import { fetchSignInMethodsForEmail, sendEmailVerification } from './email';
3232

packages-exp/auth-exp/src/core/user/id_token_result.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import * as chaiAsPromised from 'chai-as-promised';
2020
import * as sinon from 'sinon';
2121

2222
import { FirebaseError } from '@firebase/util';
23+
import { ProviderId } from '@firebase/auth-types-exp';
2324

2425
import { makeJWT } from '../../../test/jwt';
2526
import { testUser } from '../../../test/mock_auth';
2627
import { User } from '../../model/user';
27-
import { ProviderId } from '../providers';
2828
import { getIdTokenResult } from './id_token_result';
2929

3030
use(chaiAsPromised);

packages-exp/auth-exp/src/core/user/id_token_result.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import * as externs from '@firebase/auth-types-exp';
1919
import { base64Decode } from '@firebase/util';
2020

2121
import { User } from '../../model/user';
22-
import { ProviderId } from '../providers';
2322
import { assert } from '../util/assert';
2423
import { _logError } from '../util/log';
2524

@@ -42,14 +41,10 @@ export async function getIdTokenResult(
4241
const firebase =
4342
typeof claims.firebase === 'object' ? claims.firebase : undefined;
4443

45-
const signInProvider: ProviderId | undefined = firebase?.[
44+
const signInProvider: externs.ProviderId | undefined = firebase?.[
4645
'sign_in_provider'
47-
] as ProviderId;
48-
assert(
49-
!signInProvider || Object.values(ProviderId).includes(signInProvider),
50-
user.auth.name
51-
);
52-
46+
] as externs.ProviderId;
47+
5348
return {
5449
claims,
5550
token,

packages-exp/auth-exp/src/core/user/reload.test.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ import * as chaiAsPromised from 'chai-as-promised';
2020
import * as sinon from 'sinon';
2121
import * as sinonChai from 'sinon-chai';
2222

23-
import { UserInfo } from '@firebase/auth-types-exp';
24-
import { FirebaseError } from '@firebase/util';
23+
import { UserInfo, ProviderId } from '@firebase/auth-types-exp';
2524

2625
import { mockEndpoint } from '../../../test/api/helper';
2726
import { testUser } from '../../../test/mock_auth';
@@ -31,7 +30,6 @@ import {
3130
APIUserInfo,
3231
ProviderUserInfo
3332
} from '../../api/account_management/account';
34-
import { ProviderId } from '../providers';
3533
import { _reloadWithoutSaving, reload } from './reload';
3634

3735
use(chaiAsPromised);
@@ -147,27 +145,6 @@ describe('core/user/reload', () => {
147145
]);
148146
});
149147

150-
it('throws an error if the providerData providerId is invalid', async () => {
151-
const user = testUser('abc', '', true);
152-
mockEndpoint(Endpoint.GET_ACCOUNT_INFO, {
153-
users: [
154-
{
155-
providerUserInfo: [
156-
{
157-
...BASIC_USER_INFO,
158-
providerId: 'naaaah'
159-
}
160-
]
161-
}
162-
]
163-
});
164-
165-
await expect(_reloadWithoutSaving(user)).to.be.rejectedWith(
166-
FirebaseError,
167-
'Firebase: An internal AuthError has occurred. (auth/internal-error).'
168-
);
169-
});
170-
171148
it('reload calls auth.updateCurrentUser after completion', async () => {
172149
mockEndpoint(Endpoint.GET_ACCOUNT_INFO, {
173150
users: [{}]

packages-exp/auth-exp/src/core/user/reload.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
ProviderUserInfo
2323
} from '../../api/account_management/account';
2424
import { User } from '../../model/user';
25-
import { ProviderId } from '../providers';
2625
import { assert } from '../util/assert';
2726

2827
export async function _reloadWithoutSaving(user: User): Promise<void> {
@@ -34,7 +33,7 @@ export async function _reloadWithoutSaving(user: User): Promise<void> {
3433

3534
const coreAccount = response.users[0];
3635
const newProviderData = coreAccount.providerUserInfo?.length
37-
? extractProviderData(coreAccount.providerUserInfo, auth.name)
36+
? extractProviderData(coreAccount.providerUserInfo)
3837
: [];
3938
const updates: Partial<User> = {
4039
uid: coreAccount.localId,
@@ -75,20 +74,15 @@ function mergeProviderData(
7574
}
7675

7776
function extractProviderData(
78-
providers: ProviderUserInfo[],
79-
appName: string
77+
providers: ProviderUserInfo[]
8078
): externs.UserInfo[] {
8179
return providers.map(({ providerId, ...provider }) => {
82-
assert(
83-
providerId && Object.values<string>(ProviderId).includes(providerId),
84-
appName
85-
);
8680
return {
8781
uid: provider.rawId || '',
8882
displayName: provider.displayName || null,
8983
email: provider.email || null,
9084
phoneNumber: provider.phoneNumber || null,
91-
providerId: providerId as ProviderId,
85+
providerId: providerId as externs.ProviderId,
9286
photoURL: provider.photoUrl || null
9387
};
9488
});

0 commit comments

Comments
 (0)