diff --git a/addon/authenticators/firebase.ts b/addon/authenticators/firebase.ts index ac6896d..b62f509 100644 --- a/addon/authenticators/firebase.ts +++ b/addon/authenticators/firebase.ts @@ -1,6 +1,11 @@ import { getOwner } from '@ember/application'; -import { Auth, User, UserCredential } from 'firebase/auth'; +import { + Auth, + User, + UserCredential, + UserInfo, +} from 'firebase/auth'; import BaseAuthenticator from 'ember-simple-auth/authenticators/base'; import { @@ -15,17 +20,51 @@ interface AuthenticateCallback { (auth: Auth): Promise; } +interface CherryPickedUser { + displayName: string | null; + email: string | null; + phoneNumber: string | null; + photoURL: string | null; + providerId: string; + uid: string; + emailVerified: boolean; + isAnonymous: boolean; + providerData: UserInfo[]; + refreshToken: string; + tenantId: string | null; +} + +interface AuthenticatedData { + user: CherryPickedUser; +} + +function parseCherryPickedUser(user: User): CherryPickedUser { + return { + displayName: user.displayName, + email: user.email, + phoneNumber: user.phoneNumber, + photoURL: user.photoURL, + providerId: user.providerId, + uid: user.uid, + emailVerified: user.emailVerified, + isAnonymous: user.isAnonymous, + providerData: user.providerData, + refreshToken: user.refreshToken, + tenantId: user.tenantId, + }; +} + export default class FirebaseAuthenticator extends BaseAuthenticator { /* eslint-disable @typescript-eslint/no-explicit-any */ private get fastboot(): any { return getOwner(this).lookup('service:fastboot'); } - public async authenticate(callback: AuthenticateCallback): Promise<{ user: User | null }> { + public async authenticate(callback: AuthenticateCallback): Promise { const auth = getAuth(); const credential = await callback(auth); - return { user: credential.user }; + return { user: parseCherryPickedUser(credential.user) }; } public invalidate(): Promise { @@ -34,10 +73,15 @@ export default class FirebaseAuthenticator extends BaseAuthenticator { return signOut(auth); } - public restore(): Promise<{ user: User | null }> { + public restore(): Promise { return new Promise((resolve, reject) => { const auth = getAuth(); + if (auth.currentUser) { + resolve({ user: parseCherryPickedUser(auth.currentUser) }); + return; + } + if ( this.fastboot?.isFastBoot && this.fastboot.request.headers.get('Authorization')?.startsWith('Bearer ') @@ -46,7 +90,7 @@ export default class FirebaseAuthenticator extends BaseAuthenticator { if (token) { signInWithCustomToken(auth, token).then((credential) => { - resolve({ user: credential.user }); + resolve({ user: parseCherryPickedUser(credential.user) }); }).catch(() => { reject(); }); @@ -58,11 +102,11 @@ export default class FirebaseAuthenticator extends BaseAuthenticator { unsubscribe(); if (user) { - resolve({ user }); + resolve({ user: parseCherryPickedUser(user) }); } else { getRedirectResult(auth).then((credential) => { if (credential) { - resolve({ user: credential.user }); + resolve({ user: parseCherryPickedUser(credential.user) }); } else { reject(); } diff --git a/tests/dummy/app/controllers/application.ts b/tests/dummy/app/controllers/application.ts index fd6a30c..117e478 100644 --- a/tests/dummy/app/controllers/application.ts +++ b/tests/dummy/app/controllers/application.ts @@ -20,7 +20,7 @@ export default class ApplicationController extends Controller { login(): void { this.session.authenticate('authenticator:firebase', (auth: Auth) => ( createUserWithEmailAndPassword(auth, 'foo@gmail.com', 'foobar') - ).then((credential) => credential.user).catch(() => ( + ).then((credential) => credential).catch(() => ( signInWithEmailAndPassword(auth, 'foo@gmail.com', 'foobar') ))); } diff --git a/tests/unit/authenticators/firebase-test.ts b/tests/unit/authenticators/firebase-test.ts index 2110d83..6f3498b 100644 --- a/tests/unit/authenticators/firebase-test.ts +++ b/tests/unit/authenticators/firebase-test.ts @@ -34,10 +34,26 @@ module('Unit | Authenticator | firebase', function (hooks) { const authenticator = this.owner.lookup('authenticator:firebase'); // Act - const result = await authenticator.authenticate(() => Promise.resolve({ user: 'foo' })); + const result = await authenticator.authenticate(() => Promise.resolve({ + user: { displayName: 'foo' }, + })); // Assert - assert.deepEqual(result, { user: 'foo' }); + assert.deepEqual(result, { + user: { + displayName: 'foo', + email: undefined, + emailVerified: undefined, + isAnonymous: undefined, + phoneNumber: undefined, + photoURL: undefined, + providerData: undefined, + providerId: undefined, + refreshToken: undefined, + tenantId: undefined, + uid: undefined, + }, + }); }); });