Following the codes on this firebase documentation, I'm trying to implement a cookie-based authentication so I could pass the cookie around several subdomains. Here's my main functions that I'm using for loging in and checking session file:
exports.SignInUser = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {
const idToken = req.body.idToken.toString();
const expiresIn = 60 * 60 * 24 * 5 * 1000;
admin
.auth()
.createSessionCookie(idToken, { expiresIn })
.then(
sessionCookie => {
const options = {
maxAge: expiresIn,
httpOnly: true,
secure: true
};
res.cookie('session', sessionCookie, options);
res.json({
status: "ok"
})
},
error => {
res.json({
status: "error",
message: "Unauthorized request!"
})
});
})
})
exports.checkSession = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {
const sessionCookie = req.cookies.session || '';
admin
.auth()
.verifySessionCookie(sessionCookie, true)
.then(decodedClaims => {
res.json({
status: "ok",
data: {
decodedClaims
}
})
})
.catch((error) => {
res.json({
status: "error",
})
});
})
})
Here's the login.html file:
<script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.0.4/firebase-database.js"></script>
<script>
firebase.initializeApp({
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "..."
});
$(function() {
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE);
function postIdTokenToSessionLogin(idToken) {
$.ajax({
url: "http://localhost:5001/...-fea6a/us-central1/SignInUser",
type: 'post',
data: {
idToken,
},
dataType: 'json',
success: function(data) {
console.log(data)
}
});
}
$.ajax({
url: "http://localhost:5001/...-fea6a/us-central1/checkSession",
type: 'post',
success: function(data) {
if(data.status === "ok"){
window.location.href = "/";
} else {
$("#loader-wrapper").hide();
$("#mainrow").fadeIn();
}
},
error: function(){
$("#loader-wrapper").hide();
$("#mainrow").fadeIn();
}
});
$("#signinbtn").on("click",() => {
let errormessage = "";
const email = $("#email").val();
const password = $("#password").val();
if(email.length == 0) errormessage += "Enter a valid email.<br>";
if(password.length == 0) errormessage += "Enter a valid password.<br>";
if(errormessage.length==0){
$("#signinbtn").prop('disabled', true);
firebase.auth().signInWithEmailAndPassword(email, password).then(({user}) => {
return user.getIdToken().then(idToken => {
return postIdTokenToSessionLogin(idToken);
})
})
.then(() => {
return firebase.auth().signOut();
})
.catch(function(error) {
const errorCode = error.code;
const errorMessage = error.message;
$("#signinbtn").prop('disabled', false);
showMessage(errorMessage);
});
} else {
$("#signupbtn").prop('disabled', false);
showMessage(errormessage);
}
})
});
</script>
I'm getting this error when I try this:
Cannot read property 'session' of undefined
I researched and found out that session is absent when it comes to authenticating outside express. So I tried this method instead for functions:
exports.SignInUser = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {
const idToken = req.body.idToken.toString();
const expiresIn = 60 * 60 * 24 * 5 * 1000;
admin
.auth()
.createSessionCookie(idToken, { expiresIn })
.then(
sessionCookie => {
const options = {
maxAge: expiresIn,
httpOnly: true,
secure: true
};
// res.cookie('session', sessionCookie, options);
res.set('Set-Cookie', `__session=${sessionCookie};max-age=${expiresIn};HttpOnly,Secure`)
res.json({
status: "ok"
})
},
error => {
res.json({
status: "error",
message: "Unauthorized request!"
})
});
})
})
exports.checkSession = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {
try {
const sessionCookie = req.cookies.__session || '';
admin
.auth()
.verifySessionCookie(sessionCookie, true)
.then(decodedClaims => {
res.json({
status: "ok",
data: {
decodedClaims
}
})
})
.catch((error) => {
res.json({
status: "error",
})
});
} catch (e) {
console.log(e)
res.json({
status: "error",
})
}
})
})
Which also didn't work (I got Cannot read property '__session' of undefined)
What am I doing wrong? Why doesn't this work? Should I use another method like JWT? Your advice is appreciated.