Skip to content

Commit f4e95e0

Browse files
committed
Cleanup
1 parent edaff9a commit f4e95e0

File tree

8 files changed

+91
-103
lines changed

8 files changed

+91
-103
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"@angular/platform-browser": "^9.0.0 || ^10.0.0 || ^11.0.0",
4949
"@angular/platform-browser-dynamic": "^9.0.0 || ^10.0.0 || ^11.0.0",
5050
"@angular/router": "^9.0.0 || ^10.0.0 || ^11.0.0",
51+
"cookie": "^0.4.1",
5152
"firebase": "^7.0.0 || ^8.0.0",
5253
"firebase-admin": "^8.10.0",
5354
"firebase-functions": "^3.6.0",
@@ -57,6 +58,7 @@
5758
"husky": "^4.2.5",
5859
"inquirer": "^6.2.2",
5960
"inquirer-autocomplete-prompt": "^1.0.1",
61+
"js-cookie": "^2.2.1",
6062
"open": "^7.0.3",
6163
"rxfire": "^3.9.7 || ^4.0.0",
6264
"rxjs": "^6.5.3",
@@ -79,10 +81,12 @@
7981
"@angular/platform-server": "^9.0.0 || ^10.0.0 || ^11.0.0",
8082
"@firebase/app-types": "^0.6.1",
8183
"@nguniversal/express-engine": "^11.0.0",
84+
"@types/cookie": "^0.4.0",
8285
"@types/fs-extra": "^7.0.0",
8386
"@types/gzip-size": "^5.1.1",
8487
"@types/inquirer": "^0.0.44",
8588
"@types/jasmine": "^3.3.13",
89+
"@types/js-cookie": "^2.2.6",
8690
"@types/node": "^12.6.2 < 12.12.42",
8791
"@types/request": "0.0.30",
8892
"@types/semver": "^7.1.0",

sample/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
"core-js": "^3.6.5",
3333
"firebase": "^8.0.0",
3434
"first-input-delay": "^0.1.3",
35-
"ngx-cookie-service": "^10.1.1",
3635
"proxy-polyfill": "^0.3.2",
3736
"rxjs": "~6.6.3",
3837
"tslib": "^2.0.1",

sample/src/app/app.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ApplicationRef, Component } from '@angular/core';
1+
import { ApplicationRef, Component, isDevMode } from '@angular/core';
22
import { FirebaseApp } from '@angular/fire';
33
import { debounceTime } from 'rxjs/operators';
44

@@ -26,6 +26,8 @@ import { debounceTime } from 'rxjs/operators';
2626
})
2727
export class AppComponent {
2828
constructor(public readonly firebaseApp: FirebaseApp, appRef: ApplicationRef) {
29-
appRef.isStable.pipe(debounceTime(200)).subscribe(it => console.log('isStable', it));
29+
if (isDevMode()) {
30+
appRef.isStable.pipe(debounceTime(200)).subscribe(it => console.log('isStable', it));
31+
}
3032
}
3133
}

sample/src/app/app.module.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { AppComponent } from './app.component';
66
import { ServiceWorkerModule } from '@angular/service-worker';
77
import { environment } from '../environments/environment';
88

9-
import { AngularFireModule } from '@angular/fire';
9+
import { AngularFireModule, FIREBASE_APP_NAME } from '@angular/fire';
1010

1111
import {
1212
AngularFireAnalyticsModule,
@@ -44,7 +44,7 @@ import { FunctionsComponent } from './functions/functions.component';
4444
import { FirestoreOfflineComponent } from './firestore-offline/firestore-offline.component';
4545
import { FirestoreOfflineModule } from './firestore-offline/firestore-offline.module';
4646
import { UpboatsComponent } from './upboats/upboats.component';
47-
import { CookieService } from 'ngx-cookie-service';
47+
4848
@NgModule({
4949
declarations: [
5050
AppComponent,
@@ -78,13 +78,12 @@ import { CookieService } from 'ngx-cookie-service';
7878
FirestoreOfflineModule
7979
],
8080
providers: [
81-
CookieService,
8281
UserTrackingService,
8382
ScreenTrackingService,
8483
PerformanceMonitoringService,
8584
{ provide: EXPERIMENTAL_COOKIE_AUTH, useValue: true },
8685
{ provide: FIRESTORE_SETTINGS, useValue: { ignoreUndefinedProperties: true } },
87-
{ provide: ANALYTICS_DEBUG_MODE, useValue: true },
86+
{ provide: ANALYTICS_DEBUG_MODE, useFactory: isDevMode },
8887
{ provide: COLLECTION_ENABLED, useValue: true },
8988
{ provide: USE_AUTH_EMULATOR, useValue: environment.useEmulators ? ['localhost', 9099] : undefined },
9089
{ provide: USE_DATABASE_EMULATOR, useValue: environment.useEmulators ? ['localhost', 9000] : undefined },

sample/src/app/auth/auth.component.ts

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ import { Component, OnInit, OnDestroy, PLATFORM_ID } from '@angular/core';
22
import { AngularFireAuth } from '@angular/fire/auth';
33
import firebase from 'firebase/app';
44
import { Subscription } from 'rxjs';
5-
import { filter, map, pairwise, tap } from 'rxjs/operators';
65
import { trace } from '@angular/fire/performance';
76
import { Inject } from '@angular/core';
87
import { isPlatformServer } from '@angular/common';
9-
import { CookieService } from 'ngx-cookie-service';
108

119
@Component({
1210
selector: 'app-auth',
@@ -25,47 +23,24 @@ import { CookieService } from 'ngx-cookie-service';
2523
export class AuthComponent implements OnInit, OnDestroy {
2624

2725
private readonly userDisposable: Subscription|undefined;
28-
private readonly cookieExchangeDisposable: Subscription|undefined;
2926

3027
showLoginButton = false;
3128
showLogoutButton = false;
3229

3330
constructor(
3431
public readonly auth: AngularFireAuth,
3532
@Inject(PLATFORM_ID) platformId: object,
36-
cookies: CookieService,
3733
) {
3834

3935
if (!isPlatformServer(platformId)) {
4036

41-
4237
this.userDisposable = auth.authState.pipe(
43-
trace('auth'),
44-
map(u => !!u)
38+
trace('auth')
4539
).subscribe(isLoggedIn => {
4640
this.showLoginButton = !isLoggedIn;
47-
this.showLogoutButton = isLoggedIn;
48-
});
49-
50-
this.cookieExchangeDisposable = auth.credential.pipe(
51-
filter(it => !!it),
52-
tap(it => console.log(it.credential)),
53-
).subscribe(userCredential => {
54-
const json = userCredential.credential.toJSON() as any;
55-
json._uid = userCredential.user.uid;
56-
cookies.set('session', JSON.stringify(json));
41+
this.showLogoutButton = !!isLoggedIn;
5742
});
5843

59-
auth.user.pipe(
60-
pairwise(),
61-
filter(([a, b]) => !!a && !b)
62-
).subscribe(() => {
63-
cookies.delete('session');
64-
});
65-
66-
auth.getRedirectResult().then(it => console.log('redirectResult', it));
67-
auth.credential.subscribe(it => console.log('credential', it));
68-
6944
}
7045
}
7146

@@ -75,9 +50,6 @@ export class AuthComponent implements OnInit, OnDestroy {
7550
if (this.userDisposable) {
7651
this.userDisposable.unsubscribe();
7752
}
78-
if (this.cookieExchangeDisposable) {
79-
this.cookieExchangeDisposable.unsubscribe();
80-
}
8153
}
8254

8355
async login() {

sample/yarn.lock

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8459,13 +8459,6 @@ next-tick@~1.0.0:
84598459
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
84608460
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
84618461

8462-
ngx-cookie-service@^10.1.1:
8463-
version "10.1.1"
8464-
resolved "https://registry.yarnpkg.com/ngx-cookie-service/-/ngx-cookie-service-10.1.1.tgz#4d7f41ba7d788896c59cb68283df3ae9d8ffcd37"
8465-
integrity sha512-HvBrYHdxMN1NvFJGEIF/8EuAg2fjxj8QwqTv9h6qZGqNLU+lUba8Pb2zRPw1YA+gqKkJawOy5dYNeH0kyPyipw==
8466-
dependencies:
8467-
tslib "^2.0.0"
8468-
84698462
nice-try@^1.0.4:
84708463
version "1.0.5"
84718464
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"

src/auth/auth.ts

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Injectable, Inject, Optional, NgZone, PLATFORM_ID, InjectionToken } from '@angular/core';
2-
import { Observable, of, from, merge, Subject, Subscriber } from 'rxjs';
3-
import { switchMap, map, observeOn, shareReplay, first, filter, switchMapTo, subscribeOn, tap, take, mapTo } from 'rxjs/operators';
1+
import { Injectable, Inject, Optional, NgZone, PLATFORM_ID, InjectionToken, OnDestroy } from '@angular/core';
2+
import { Observable, of, from, merge, Subject, Subscriber, SubscriptionLike } from 'rxjs';
3+
import { switchMap, map, observeOn, shareReplay, filter, switchMapTo, subscribeOn, tap, pairwise, take } from 'rxjs/operators';
44
import {
55
FIREBASE_OPTIONS,
66
FIREBASE_APP_NAME,
@@ -18,7 +18,8 @@ import { isPlatformServer } from '@angular/common';
1818
import { proxyPolyfillCompat } from './base';
1919
import { ɵfetchInstance } from '@angular/fire';
2020
import { REQUEST } from '@nguniversal/express-engine/tokens';
21-
import { experimental } from '@angular-devkit/core';
21+
import { get as getCookie, set as setCookie, remove as removeCookie } from 'js-cookie';
22+
import { parse as parseCookies } from 'cookie';
2223

2324
export interface AngularFireAuth extends ɵPromiseProxy<firebase.auth.Auth> {}
2425

@@ -35,7 +36,9 @@ export const EXPERIMENTAL_COOKIE_AUTH = new InjectionToken<boolean>('angularfire
3536
@Injectable({
3637
providedIn: 'any'
3738
})
38-
export class AngularFireAuth {
39+
export class AngularFireAuth implements OnDestroy {
40+
41+
private disposables: SubscriptionLike[] = [];
3942

4043
/**
4144
* Observable of authentication state; as of Firebase 4.0 this is only triggered via sign-in/out
@@ -76,7 +79,7 @@ export class AngularFireAuth {
7679
@Optional() @Inject(LANGUAGE_CODE) languageCode: string | null,
7780
@Optional() @Inject(USE_DEVICE_LANGUAGE) useDeviceLanguage: boolean | null,
7881
@Optional() @Inject(PERSISTENCE) persistence: string | null,
79-
@Optional() @Inject(EXPERIMENTAL_COOKIE_AUTH) experimentalCookieAuth: boolean | null,
82+
@Optional() @Inject(EXPERIMENTAL_COOKIE_AUTH) private experimentalCookieAuth: boolean | null,
8083
@Optional() @Inject(REQUEST) request: any,
8184
) {
8285
const schedulers = new ɵAngularFireSchedulers(zone);
@@ -120,27 +123,25 @@ export class AngularFireAuth {
120123
shareReplay({ bufferSize: 1, refCount: false }),
121124
);
122125

126+
// HACK, as we're exporting auth.Auth, rather than auth, developers importing firebase.auth
127+
// (e.g, `import { auth } from 'firebase/app'`) are getting an undefined auth object unexpectedly
128+
// as we're completely lazy. Let's eagerly load the Auth SDK here.
129+
// There could potentially be race conditions still... but this greatly decreases the odds while
130+
// we reevaluate the API.
131+
this.disposables.push(auth.pipe(take(1)).subscribe());
132+
123133
const cookieAuthCredential = auth.pipe(
124134
switchMap(auth => {
125-
// grabbed from ngx-cookie-service, they don't support universal
126-
const getCookieRegExp = (name: string): RegExp => {
127-
const escapedName: string = name.replace(/([\[\]\{\}\(\)\|\=\;\+\?\,\.\*\^\$])/gi, '\\$1');
128-
return new RegExp('(?:^' + escapedName + '|;\\s*' + escapedName + ')=(.*?)(?:;|$)', 'g');
129-
};
130-
const cookie = isPlatformServer(platformId) ? request.headers.cookie : document.cookie;
131-
const session = getCookieRegExp('session').exec(cookie)?.[1];
132-
if (session) {
133-
const authCredentialJSON = JSON.parse(decodeURIComponent(session));
134-
const credentialUid = authCredentialJSON._uid;
135-
delete authCredentialJSON._uid;
136-
const authCredential = firebase.auth.AuthCredential.fromJSON(authCredentialJSON);
137-
// TODO investigate, this is likely a security concern but is there a way we could utilize this property
138-
// perhaps we can build the _uid into the application name?
139-
if (auth.currentUser?.uid === credentialUid) {
140-
return of({ user: auth.currentUser, additionalUserInfo: null, credential: authCredential, operationType: null });
141-
} else {
142-
return auth.signInWithCredential(authCredential);
143-
}
135+
const encodedSession = isPlatformServer(platformId) ?
136+
request.headers.cookie && parseCookies(request.headers.cookie).__session :
137+
getCookie('__session');
138+
if (encodedSession) {
139+
const session = JSON.parse(decodeURIComponent(encodedSession));
140+
const authCredential = firebase.auth.AuthCredential.fromJSON(session.credential);
141+
return auth.signInWithCredential(authCredential).then(it => it, (e) => {
142+
console.warn(e);
143+
return null;
144+
});
144145
} else {
145146
return of(null);
146147
}
@@ -149,13 +150,6 @@ export class AngularFireAuth {
149150
shareReplay({ bufferSize: 1, refCount: false }),
150151
);
151152

152-
// HACK, as we're exporting auth.Auth, rather than auth, developers importing firebase.auth
153-
// (e.g, `import { auth } from 'firebase/app'`) are getting an undefined auth object unexpectedly
154-
// as we're completely lazy. Let's eagerly load the Auth SDK here.
155-
// There could potentially be race conditions still... but this greatly decreases the odds while
156-
// we reevaluate the API.
157-
const _ = auth.pipe(first()).subscribe();
158-
159153
const cookieAuthUser = cookieAuthCredential.pipe(
160154
map(it => it?.user)
161155
);
@@ -220,33 +214,6 @@ export class AngularFireAuth {
220214
observeOn(schedulers.insideAngular),
221215
);
222216

223-
if (experimentalCookieAuth) {
224-
225-
/* TODO add the side-effects
226-
it's now seeming like this should be a service instead
227-
228-
this.cookieExchangeDisposable = this.credential.pipe(
229-
filter(it => !!it),
230-
tap(it => console.log(it.credential)),
231-
).subscribe(userCredential => {
232-
const json = userCredential.credential.toJSON();
233-
// TODO do we want to put the instanceId on here too?
234-
// any other properties that we can use from the server side?
235-
json['_uid'] = userCredential.user.uid;
236-
// are we taking on ngx-cookie?
237-
cookies.set('session', JSON.stringify(json));
238-
});
239-
240-
this.user.pipe(
241-
pairwise(),
242-
filter(([a,b]) => !!a && !b)
243-
).subscribe(() => {
244-
cookies.delete('session');
245-
});
246-
*/
247-
248-
}
249-
250217
}
251218

252219
this.idToken = this.user.pipe(
@@ -257,6 +224,33 @@ export class AngularFireAuth {
257224
switchMap(user => user ? from(user.getIdTokenResult()) : of(null))
258225
);
259226

227+
228+
if (this.experimentalCookieAuth) {
229+
230+
this.disposables.push(
231+
this.credential.pipe(
232+
filter(it => !!it)
233+
).subscribe(userCredential => {
234+
const session = {
235+
uid: userCredential.user.uid,
236+
credential: userCredential.credential.toJSON(),
237+
};
238+
// TODO look at security
239+
setCookie('__session', JSON.stringify(session));
240+
})
241+
);
242+
243+
this.disposables.push(
244+
this.user.pipe(
245+
pairwise(),
246+
filter(([a, b]) => !!a && !b),
247+
).subscribe(() => {
248+
removeCookie('__session');
249+
})
250+
);
251+
252+
}
253+
260254
return ɵlazySDKProxy(this, auth, zone, { spy: {
261255
apply: (name, _, val) => {
262256
// If they call a signIn or createUser function listen into the promise
@@ -271,6 +265,11 @@ export class AngularFireAuth {
271265

272266
}
273267

268+
ngOnDestroy() {
269+
this.disposables.forEach(it => it.unsubscribe());
270+
firebase.apps.forEach(app => app.auth().signOut());
271+
}
272+
274273
}
275274

276275
ɵapplyMixins(AngularFireAuth, [proxyPolyfillCompat]);

yarn.lock

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,6 +1784,11 @@
17841784
dependencies:
17851785
"@types/node" "*"
17861786

1787+
"@types/cookie@^0.4.0":
1788+
version "0.4.0"
1789+
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108"
1790+
integrity sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==
1791+
17871792
"@types/duplexify@^3.6.0":
17881793
version "3.6.0"
17891794
resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8"
@@ -1868,6 +1873,11 @@
18681873
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.6.1.tgz#f8b95def0016411c58c7adb4791dff29bc62992c"
18691874
integrity sha512-eeSCVhBsgwHNS1FmaMu4zrLxfykCTWJMLFZv7lmyrZQjw7foUUXoPu4GukSN9v7JvUw7X+/aDH3kCaymirBSTg==
18701875

1876+
"@types/js-cookie@^2.2.6":
1877+
version "2.2.6"
1878+
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f"
1879+
integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw==
1880+
18711881
"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6":
18721882
version "7.0.6"
18731883
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
@@ -4384,6 +4394,11 @@ cookie@0.4.0:
43844394
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
43854395
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
43864396

4397+
cookie@^0.4.1:
4398+
version "0.4.1"
4399+
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
4400+
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
4401+
43874402
copy-concurrently@^1.0.0:
43884403
version "1.0.5"
43894404
resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
@@ -8006,6 +8021,11 @@ jquery@^3.4.1:
80068021
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5"
80078022
integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==
80088023

8024+
js-cookie@^2.2.1:
8025+
version "2.2.1"
8026+
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
8027+
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
8028+
80098029
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
80108030
version "4.0.0"
80118031
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

0 commit comments

Comments
 (0)