I have an Angular site hosted on Firebase https://account.mydomain.com, and some Firebase/Google Cloud functions hosted at https://functions.mydomain.com.
I am trying to set up the scenario described in the articles at the end of this question.
In brief I,
- log in through Firebase auth on account.mydomain.com
- POST the idtoken obtained from a successful login to sessionLogin, a firebase function using onRequest which verifies the id token, and creates a session cookie, returning this in the response.
- make another seperate GET to the checkAuthStatus function endpoint to verify the cookie and get an access token which I use to authenticate on https://account.mydomain.com.
The whole aim of this is to use the session to authenicate against any subdomains of mydomain.com. However my issue is that the cookie is never set after step 2, despite being visible in the set-cookie header of the network response.
Set-Cookie:
__session=; Path=/; Domain=mydomain.co.uk; Expires=Mon, 09 Dec 2024 22:33:54 GMT; Max-Age=432000; HttpOnly; Secure; SameSite=None
This cookie doesn’t appear in the Chrome Devtools Application tab for account.mydomain.com. And it isn’t sent with my request in step three, even if I include ‘withCredentials: true’ on my GET request.
This is the body of the function I am posting to,
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Allow-Origin', 'https://account.mydomain.com');
if (req.method === 'OPTIONS') {
// Send response to OPTIONS requests
res.set('Access-Control-Allow-Methods', 'POST');
res.set('Access-Control-Allow-Headers', ['Authorization', 'Content-Type']);
res.set('Access-Control-Max-Age', '3600');
res.status(204).send('');
return;
}
else {
// Get the ID token passed and the CSRF token.
console.log(req.body.idToken);
const idToken = req.body.idToken.toString();
const auth = getAuth(app);
auth.verifyIdToken(idToken).then((decodedToken) => {
// Set session expiration to 5 days.
const expiresIn = 60 * 60 * 24 * 5 * 1000;
auth
.createSessionCookie(idToken, { expiresIn })
.then(
(sessionCookie) => {
// Set cookie policy for session cookie.
const options = { maxAge: expiresIn, httpOnly: true, secure: true, sameSite: 'none' as const, domain: 'mydomain.com' };
res.setHeader('Cache-Control', 'private');
res.cookie('__session', sessionCookie, options);
res.send('Cookie set');
return;
},
(error) => {
res.status(401).send('UNAUTHORIZED REQUEST!');
}
);
}).catch((error) => {
// Handle error
console.error('Error creating sessionLogin:', error);
res.status(401).send('UNAUTHORIZED REQUEST!');
});
}
});
And this is the code which is making the requests from my Angular site,
var responsePromise = new Promise<void>((resolve, reject) => {
signInWithPopup(this.afAuth, provider)
.then(async (result: UserCredential) => {
return result.user.getIdToken().then(idToken => {
var functionBaseUrl = 'https://account.mydomain.co.uk'; //Hosted
var body = {
idToken: idToken
};
axios.post(functionBaseUrl + '/sessionLogin', body).then(function (response) {
console.log(response);
axios.get(functionBaseUrl + '/checkAuthStatus', {
withCredentials: true,
headers: {
'Content-Type': 'application/json'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.error(error);
});
})
.catch(function (error) {
console.error(error);
});
});
})
.catch((error) => {
console.error(error);
});
});
Can anyone spot why this isn’t being set, or provide any further information on now I could diagnose this issue? I don’t appear to have any cors problems, and I also belive I have set the cookie with the correct configuration for a cross site cookie. Can anyone spot, or explain what I might be missing?
The articles,
https://dev.to/johncarroll/how-to-share-firebase-authentication-across-subdomains-1ka8
https://dev.to/brianburton/cross-domain-firebase-authentication-a-simple-approach-337k