Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bc6b973

Browse files
committed
First.
1 parent e74e8fd commit bc6b973

File tree

5 files changed

+230
-0
lines changed

5 files changed

+230
-0
lines changed

firebaseserverapp-next/client.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// [START register_sw]
2+
// Install servicerWorker if supported on sign-in/sign-up page.
3+
if ('serviceWorker' in navigator) {
4+
navigator.serviceWorker.register('/service-worker.js', {scope: '/'});
5+
}
6+
// [END register_sw]
7+
8+
function signInAndRedirect() {
9+
// [START sign_in_and_redirect]
10+
const { getAuth, signInWithEmailAndPassword } = require("firebase/auth");
11+
12+
// Sign in screen.
13+
const auth = getAuth();
14+
signInWithEmailAndPassword(auth, email, password)
15+
.then((result) => {
16+
// Redirect to profile page after sign-in. The service worker will detect
17+
// this and append the ID token to the header.
18+
window.location.assign('/profile');
19+
})
20+
.catch((error) => {
21+
// Error occurred.
22+
});
23+
// [END sign_in_and_redirect]
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "firebaseserverapp-next",
3+
"version": "1.0.0",
4+
"scripts": {
5+
"compile": "cp ../tsconfig.json.template ./tsconfig.json && tsc"
6+
},
7+
"license": "Apache-2.0",
8+
"dependencies": {
9+
"firebase": "^10.0.0"
10+
}
11+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// [START server_admin]
2+
// Server side code.
3+
const admin = require('firebase-admin');
4+
const serviceAccount = require('path/to/serviceAccountKey.json');
5+
6+
// The Firebase Admin SDK is used here to verify the ID token.
7+
admin.initializeApp({
8+
credential: admin.credential.cert(serviceAccount)
9+
});
10+
11+
function getIdToken(req) {
12+
// Parse the injected ID token from the request header.
13+
const authorizationHeader = req.headers.authorization || '';
14+
const components = authorizationHeader.split(' ');
15+
return components.length > 1 ? components[1] : '';
16+
}
17+
18+
function checkIfSignedIn(url) {
19+
return (req, res, next) => {
20+
if (req.url == url) {
21+
const idToken = getIdToken(req);
22+
// Verify the ID token using the Firebase Admin SDK.
23+
// User already logged in. Redirect to profile page.
24+
admin.auth().verifyIdToken(idToken).then((decodedClaims) => {
25+
// User is authenticated, user claims can be retrieved from
26+
// decodedClaims.
27+
// In this sample code, authenticated users are always redirected to
28+
// the profile page.
29+
res.redirect('/profile');
30+
}).catch((error) => {
31+
next();
32+
});
33+
} else {
34+
next();
35+
}
36+
};
37+
}
38+
39+
// If a user is signed in, redirect to profile page.
40+
app.use(checkIfSignedIn('/'));
41+
// [END server_admin]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { headers } from 'next/headers';
2+
import { initializeServerApp } from 'firebase/app';
3+
import { getAuth } from 'firebase/auth';
4+
import { redirect } from 'next/navigation';
5+
6+
// [START server_client]
7+
export default async function MyServerComponent({ params }) {
8+
9+
// get relevant request headers (NextJS)
10+
const authIdToken = headers().get('Authorization')?.split('Bearer ')[1];
11+
12+
// Initialize the Firebase server app instance
13+
const serverApp = initializeServerApp(config, { authIdToken });
14+
15+
// Initialize the auth SDK
16+
const auth = getAuth(serverApp);
17+
18+
if (auth.currentUser) {
19+
redirect('/profile');
20+
}
21+
22+
// ...
23+
}
24+
// [END server_client]

firebaseserverapp-next/sw.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
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

Comments
 (0)