Skip to content

Commit 5beee59

Browse files
committed
Add signInAnonymously to auth-next
1 parent 53afb64 commit 5beee59

File tree

7 files changed

+234
-0
lines changed

7 files changed

+234
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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 } from 'chai';
19+
import { mockEndpoint } from '../../../test/api/helper';
20+
import { mockAuth } from "../../../test/mock_auth";
21+
import * as mockFetch from '../../../test/mock_fetch';
22+
import { Endpoint } from '../../api';
23+
import { OperationType } from '../../model/user_credential';
24+
import { ProviderId, SignInMethod } from '../providers';
25+
import { signInAnonymously } from './anonymous';
26+
import { APIUserInfo } from '../../api/account_management/account';
27+
28+
describe('core/strategies/anonymous', () => {
29+
const serverUser: APIUserInfo = {
30+
localId: 'local-id',
31+
};
32+
33+
beforeEach(() => {
34+
mockFetch.setUp();
35+
mockEndpoint(Endpoint.SIGN_UP, {
36+
idToken: 'id-token',
37+
refreshToken: 'refresh-token',
38+
expiresIn: '1234',
39+
localId: serverUser.localId!
40+
});
41+
mockEndpoint(Endpoint.GET_ACCOUNT_INFO, {
42+
users: [serverUser]
43+
});
44+
});
45+
afterEach(mockFetch.tearDown);
46+
47+
describe('signInAnonymously', () => {
48+
it('should sign in an anonymous user', async () => {
49+
const { credential, user, operationType } = await signInAnonymously(mockAuth);
50+
expect(credential?.providerId).to.eq(ProviderId.ANONYMOUS);
51+
expect(credential?.signInMethod).to.eq(SignInMethod.ANONYMOUS);
52+
expect(operationType).to.eq(OperationType.SIGN_IN);
53+
expect(user.uid).to.eq(serverUser.localId);
54+
expect(user.isAnonymous).to.be.true;
55+
});
56+
57+
context('already signed in anonymousl', () => {
58+
59+
});
60+
61+
context('already signed in with a non-anonymous account', () => {
62+
63+
});
64+
});
65+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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 { Auth } from '../../model/auth';
19+
import { OperationType, UserCredential } from '../../model/user_credential';
20+
import { AnonymousProvider } from '../providers/anonymous';
21+
import { UserCredentialImpl } from '../user/user_credential_impl';
22+
import { signInWithCredential } from './credential';
23+
export async function signInAnonymously(auth: Auth): Promise<UserCredential> {
24+
const credential = AnonymousProvider.credential();
25+
if (auth.currentUser?.isAnonymous) {
26+
// If an anonymous user is already signed in, no need to sign them in again.
27+
return new UserCredentialImpl(
28+
auth.currentUser,
29+
credential,
30+
OperationType.SIGN_IN
31+
);
32+
}
33+
return signInWithCredential(auth, credential);
34+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export class UserImpl implements User {
5959
tenantId = null;
6060
metadata = {};
6161
providerData = [];
62+
isAnonymous = false;
6263

6364
// Optional fields from UserInfo
6465
displayName: string | null;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface User extends externs.User {
3434
tenantId: string | null;
3535
providerData: externs.UserInfo[];
3636
metadata: externs.UserMetadata;
37+
isAnonymous: boolean;
3738

3839
getIdToken(forceRefresh?: boolean): Promise<string>;
3940
getIdTokenResult(forceRefresh?: boolean): Promise<externs.IdTokenResult>;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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+
import { ProviderId, SignInMethod } from '.';
21+
import { mockAuth } from '../../../test/mock_auth';
22+
import { AnonymousCredential, AnonymousProvider } from "./anonymous";
23+
24+
use(chaiAsPromised);
25+
26+
describe('core/providers/anonymous', () => {
27+
describe('AnonymousCredential', () => {
28+
const credential = new AnonymousCredential();
29+
30+
it('should have an anonymous provider', () => {
31+
expect(credential.providerId).to.eq(ProviderId.ANONYMOUS);
32+
});
33+
34+
it('should have an anonymous sign in method', () => {
35+
expect(credential.signInMethod).to.eq(SignInMethod.ANONYMOUS);
36+
});
37+
38+
describe('#toJSON', () => {
39+
it('throws', () => {
40+
expect(credential.toJSON).to.throw(Error);
41+
});
42+
});
43+
44+
describe('#_getIdTokenResponse', () => {
45+
it('throws', async () => {
46+
await expect(credential._getIdTokenResponse(mockAuth)).to.be.rejectedWith(Error);
47+
});
48+
});
49+
50+
describe('#_linkToIdToken', () => {
51+
it('throws', async () => {
52+
await expect(credential._linkToIdToken(mockAuth,'id-token')).to.be.rejectedWith(Error);
53+
});
54+
});
55+
56+
describe('#_matchIdTokenWithUid', () => {
57+
it('throws', () => {
58+
expect(() => credential._matchIdTokenWithUid(mockAuth, 'other-uid')).to.throw(Error);
59+
});
60+
});
61+
});
62+
63+
describe('AnonymousProvider', () => {
64+
describe('.credential', () => {
65+
it('should return an anonymous credential', () => {
66+
const credential = AnonymousProvider.credential();
67+
expect(credential.providerId).to.eq(ProviderId.ANONYMOUS);
68+
expect(credential.signInMethod).to.eq(SignInMethod.ANONYMOUS);
69+
});
70+
});
71+
});
72+
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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 { AuthProvider, ProviderId, SignInMethod } from '.';
19+
import { signUp } from '../../api/authentication/sign_up';
20+
import { Auth } from '../../model/auth';
21+
import { AuthCredential } from '../../model/auth_credential';
22+
import { IdTokenResponse } from '../../model/id_token';
23+
import { debugFail } from '../util/assert';
24+
25+
export class AnonymousCredential implements AuthCredential {
26+
providerId = ProviderId.ANONYMOUS;
27+
signInMethod = SignInMethod.ANONYMOUS;
28+
29+
toJSON(): never {
30+
debugFail('Method not implemented.');
31+
}
32+
33+
async _getIdTokenResponse(auth: Auth): Promise<IdTokenResponse> {
34+
return signUp(auth, {
35+
returnSecureToken: true
36+
});
37+
}
38+
39+
async _linkToIdToken(_auth: Auth, _idToken: string): Promise<never> {
40+
debugFail("Can't link to an anonymous credential");
41+
}
42+
43+
_matchIdTokenWithUid(_auth: Auth, _uid: string): Promise<never> {
44+
debugFail('Method not implemented.');
45+
}
46+
}
47+
48+
export class AnonymousProvider implements AuthProvider {
49+
providerId = ProviderId.ANONYMOUS;
50+
51+
static credential(): AnonymousCredential {
52+
return new AnonymousCredential();
53+
}
54+
}

packages-exp/auth-exp/test/jwt.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,10 @@ export enum SignInMethod {
3535
PHONE = 'phone',
3636
TWITTER = 'twitter.com'
3737
}
38+
39+
/**
40+
* A provider for generating credentials
41+
*/
42+
export interface AuthProvider {
43+
readonly providerId: ProviderId;
44+
}

0 commit comments

Comments
 (0)