Skip to content

Commit c538077

Browse files
committed
Add signInWithCustomToken
1 parent 2958818 commit c538077

File tree

5 files changed

+130
-7
lines changed

5 files changed

+130
-7
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import { OperationType, UserCredential } from '@firebase/auth-types-exp';
2020

2121
import { Auth } from '../../model/auth';
2222
import { AuthCredential } from '../../model/auth_credential';
23-
import { User } from '../../model/user';
2423
import { UserCredentialImpl } from '../user/user_credential_impl';
2524

2625
export async function signInWithCredential(
@@ -37,6 +36,6 @@ export async function signInWithCredential(
3736
OperationType.SIGN_IN,
3837
response
3938
);
40-
await auth.updateCurrentUser(userCredential.user as User);
39+
await auth.updateCurrentUser(userCredential.user);
4140
return userCredential;
4241
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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 { expect, use } from 'chai';
19+
import * as chaiAsPromised from 'chai-as-promised';
20+
21+
import { OperationType } from '@firebase/auth-types-exp';
22+
23+
import { mockEndpoint } from '../../../test/api/helper';
24+
import { testAuth } from '../../../test/mock_auth';
25+
import * as mockFetch from '../../../test/mock_fetch';
26+
import { Endpoint } from '../../api';
27+
import { APIUserInfo } from '../../api/account_management/account';
28+
import { Auth } from '../../model/auth';
29+
import { IdTokenResponse } from '../../model/id_token';
30+
import { signInWithCustomToken } from './custom_token';
31+
32+
use(chaiAsPromised);
33+
34+
describe('core/strategies/signInWithCustomToken', () => {
35+
const serverUser: APIUserInfo = {
36+
localId: 'local-id',
37+
displayName: 'display-name',
38+
photoUrl: 'photo-url',
39+
email: 'email',
40+
emailVerified: true,
41+
phoneNumber: 'phone-number',
42+
tenantId: 'tenant-id',
43+
createdAt: 123,
44+
lastLoginAt: 456
45+
};
46+
47+
const idTokenResponse: IdTokenResponse = {
48+
idToken: 'my-id-token',
49+
refreshToken: 'my-refresh-token',
50+
expiresIn: '1234',
51+
localId: serverUser.localId!,
52+
kind: 'my-kind'
53+
};
54+
55+
let auth: Auth;
56+
57+
beforeEach(async () => {
58+
auth = await testAuth();
59+
mockFetch.setUp();
60+
mockEndpoint(Endpoint.SIGN_IN_WITH_CUSTOM_TOKEN, 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 signInWithCustomToken(
69+
auth,
70+
'look-at-me-im-a-jwt'
71+
);
72+
expect(credential).to.be.null;
73+
expect(user.uid).to.eq('local-id');
74+
expect(user.tenantId).to.eq('tenant-id');
75+
expect(user.displayName).to.eq('display-name');
76+
expect(operationType).to.eq(OperationType.SIGN_IN);
77+
});
78+
79+
it('should update the current user', async () => {
80+
const { user } = await signInWithCustomToken(auth, 'oh.no');
81+
expect(auth.currentUser).to.eq(user);
82+
});
83+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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 { signInWithCustomToken as getIdTokenResponse } from '../../api/authentication/custom_token';
21+
import { Auth } from '../../model/auth';
22+
import { IdTokenResponse } from '../../model/id_token';
23+
import { UserCredentialImpl } from '../user/user_credential_impl';
24+
25+
export async function signInWithCustomToken(
26+
authExtern: externs.Auth,
27+
customToken: string
28+
): Promise<externs.UserCredential> {
29+
const auth = authExtern as Auth;
30+
const response: IdTokenResponse = await getIdTokenResponse(auth, {
31+
token: customToken
32+
});
33+
const cred = await UserCredentialImpl._fromIdTokenResponse(auth, null, externs.OperationType.SIGN_IN, response);
34+
await auth.updateCurrentUser(cred.user);
35+
return cred;
36+
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,28 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { OperationType, UserCredential, ProviderId } from '@firebase/auth-types-exp';
18+
import * as externs from '@firebase/auth-types-exp';
19+
1920
import { Auth } from '../../model/auth';
2021
import { AuthCredential } from '../../model/auth_credential';
2122
import { IdTokenResponse } from '../../model/id_token';
22-
import { User } from '../../model/user';
23+
import { User, UserCredential } from '../../model/user';
2324
import { UserImpl } from './user_impl';
2425

2526
export class UserCredentialImpl implements UserCredential {
2627
constructor(
2728
public readonly user: User,
2829
public readonly credential: AuthCredential | null,
29-
public readonly operationType: OperationType
30+
public readonly operationType: externs.OperationType
3031
) {}
3132

3233
static async _fromIdTokenResponse(
3334
auth: Auth,
3435
credential: AuthCredential | null,
35-
operationType: OperationType,
36+
operationType: externs.OperationType,
3637
idTokenResponse: IdTokenResponse
3738
): Promise<UserCredential> {
38-
const user = await UserImpl._fromIdTokenResponse(auth, idTokenResponse, credential?.providerId === ProviderId.ANONYMOUS);
39+
const user = await UserImpl._fromIdTokenResponse(auth, idTokenResponse, credential?.providerId === externs.ProviderId.ANONYMOUS);
3940
const userCred = new UserCredentialImpl(user, credential, operationType);
4041
// TODO: handle additional user info
4142
// updateAdditionalUserInfoFromIdTokenResponse(userCred, idTokenResponse);

packages-exp/auth-exp/src/model/user.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@ export interface User extends externs.User {
4848
delete(): Promise<void>;
4949
toPlainObject(): PersistedBlob;
5050
}
51+
52+
export interface UserCredential extends externs.UserCredential {
53+
user: User;
54+
}

0 commit comments

Comments
 (0)