1+ function getAuthTokenPlaceholder ( ) {
2+ // [START auth_token]
3+ const { getAuth, getIdToken } = require ( "firebase/auth" ) ;
4+
5+ const auth = getAuth ( ) ;
6+ getIdToken ( auth . currentUser )
7+ . then ( ( idToken ) => {
8+ // idToken can be passed back to server.
9+ } )
10+ . catch ( ( error ) => {
11+ // Error occurred.
12+ } ) ;
13+ // [END auth_token]
14+ }
15+
16+ function getAuthToken ( ) {
17+ // [START get_auth_token]
18+ const { initializeApp } = require ( "firebase/app" ) ;
19+ const { getAuth, onAuthStateChanged, getIdToken } = require ( "firebase/auth" ) ;
20+
21+ // Initialize the Firebase app in the service worker script.
22+ initializeApp ( config ) ;
23+
24+ /**
25+ * Returns a promise that resolves with an ID token if available.
26+ * @return {!Promise<?string> } The promise that resolves with an ID token if
27+ * available. Otherwise, the promise resolves with null.
28+ */
29+ const auth = getAuth ( ) ;
30+ const getIdTokenPromise = ( ) => {
31+ return new Promise ( ( resolve , reject ) => {
32+ const unsubscribe = onAuthStateChanged ( auth , ( user ) => {
33+ unsubscribe ( ) ;
34+ if ( user ) {
35+ getIdToken ( user ) . then ( ( idToken ) => {
36+ resolve ( idToken ) ;
37+ } , ( error ) => {
38+ resolve ( null ) ;
39+ } ) ;
40+ } else {
41+ resolve ( null ) ;
42+ }
43+ } ) ;
44+ } ) ;
45+ } ;
46+ // [END get_auth_token]
47+ }
48+
49+ // [START inject_auth_token]
50+ const getOriginFromUrl = ( url ) => {
51+ // https://stackoverflow.com/questions/1420881/how-to-extract-base-url-from-a-string-in-javascript
52+ const pathArray = url . split ( '/' ) ;
53+ const protocol = pathArray [ 0 ] ;
54+ const host = pathArray [ 2 ] ;
55+ return protocol + '//' + host ;
56+ } ;
57+
58+ // Get underlying body if available. Works for text and json bodies.
59+ const getBodyContent = ( req ) => {
60+ return Promise . resolve ( ) . then ( ( ) => {
61+ if ( req . method !== 'GET' ) {
62+ if ( req . headers . get ( 'Content-Type' ) . indexOf ( 'json' ) !== - 1 ) {
63+ return req . json ( )
64+ . then ( ( json ) => {
65+ return JSON . stringify ( json ) ;
66+ } ) ;
67+ } else {
68+ return req . text ( ) ;
69+ }
70+ }
71+ } ) . catch ( ( error ) => {
72+ // Ignore error.
73+ } ) ;
74+ } ;
75+
76+ self . addEventListener ( 'fetch' , ( event ) => {
77+ /** @type {FetchEvent } */
78+ const evt = event ;
79+
80+ const requestProcessor = ( idToken ) => {
81+ let req = evt . request ;
82+ let processRequestPromise = Promise . resolve ( ) ;
83+ // For same origin https requests, append idToken to header.
84+ if ( self . location . origin == getOriginFromUrl ( evt . request . url ) &&
85+ ( self . location . protocol == 'https:' ||
86+ self . location . hostname == 'localhost' ) &&
87+ idToken ) {
88+ // Clone headers as request headers are immutable.
89+ const headers = new Headers ( ) ;
90+ req . headers . forEach ( ( val , key ) => {
91+ headers . append ( key , val ) ;
92+ } ) ;
93+ // Add ID token to header.
94+ headers . append ( 'Authorization' , 'Bearer ' + idToken ) ;
95+ processRequestPromise = getBodyContent ( req ) . then ( ( body ) => {
96+ try {
97+ req = new Request ( req . url , {
98+ method : req . method ,
99+ headers : headers ,
100+ mode : 'same-origin' ,
101+ credentials : req . credentials ,
102+ cache : req . cache ,
103+ redirect : req . redirect ,
104+ referrer : req . referrer ,
105+ body,
106+ // bodyUsed: req.bodyUsed,
107+ // context: req.context
108+ } ) ;
109+ } catch ( e ) {
110+ // This will fail for CORS requests. We just continue with the
111+ // fetch caching logic below and do not pass the ID token.
112+ }
113+ } ) ;
114+ }
115+ return processRequestPromise . then ( ( ) => {
116+ return fetch ( req ) ;
117+ } ) ;
118+ } ;
119+ // Fetch the resource after checking for the ID token.
120+ // This can also be integrated with existing logic to serve cached files
121+ // in offline mode.
122+ evt . respondWith ( getIdTokenPromise ( ) . then ( requestProcessor , requestProcessor ) ) ;
123+ } ) ;
124+ // [END inject_auth_token]
125+
126+ // [START claim_client]
127+ self . addEventListener ( 'activate' , ( event ) => {
128+ event . waitUntil ( clients . claim ( ) ) ;
129+ } ) ;
130+ // [END claim_client]
0 commit comments