How to extend firebase authentication login session from the client side? - javascript

The question is in the title. I have done some research but it seems like I can't find a solution to extending the life of the login session when using firebase authentication.
Currently, I have a file that logs the user in from the front-end. After logging in with Firebase Authentication, I pass the firebase id token to the server:
//[index.php]
auth.onAuthStateChanged(function(user) {
if (user) {
//Retrieve the firebase id token
user.getIdToken().then((idToken) => {
//Send the idToken to the server
sendIdTokenToServer();
});
} else {
//The user is logged out, redirect to login page
}
});
From the server side, I verify the firebase id token, and assign it to $_SESSION['firsebase_id_token'] if the token is valid.
//[server.php]
//Pseudo verifying the token, if the token is valid, record it
if (verifyToken($token)) $_SESSION['firebase_id_token'] = $token;
Now, from this point on, I am trying to verify the token before processing anything from the server side. For example:
//[test.php]
//Before processing anything, validate the token
if (verifyToken($_SESSION['firebase_id_token'])) {
//Perform an action because the user is still logged in
} else {
//Redirect the user to login page because they are logged out/the token cannot be verified
}
I am not certain this is the right approach to the problem (so please suggest the correct approach), they are just what I think is right when reading the documentation. All I want to do is to verify the user (that logged in from the client side) from the server side before performing any administrative tasks. The problem is after a very short period of time, the $token isn't valid any more, so the request cannot be made.
How do I extend the firebase id token session from the client side?

Instead of using onAuthStateChanged, which is only triggered when the user signs in or out, you should be using onIdTokenChanged, which is triggered whenever the user's auth token is refreshed (every hour automatically, or on demand when you call getIdToken(true)).

Related

Why would you want to sign out after creating a session in Firebase?

I'm looking at the Firebase auth docs here and specifically this code example for the client-side code for creating a session:
firebase.auth().signInWithEmailAndPassword('user#example.com', 'password').then(user => {
// Get the user's ID token as it is needed to exchange for a session cookie.
return user.getIdToken().then(idToken = > {
// Session login endpoint is queried and the session cookie is set.
// CSRF protection should be taken into account.
// ...
const csrfToken = getCookie('csrfToken')
return postIdTokenToSessionLogin('/sessionLogin', idToken, csrfToken);
});
}).then(() => {
// A page redirect would suffice as the persistence is set to NONE.
return firebase.auth().signOut();
}).then(() => {
window.location.assign('/profile');
});
The first section there makes sense-- sign in and create a session. But then the middle then calls signOut -- what? Why would you want to do that? There is a comment preceding this code in the docs that reads:
On success, the state should be cleared from the client side storage.
Unclear if that comment is referring to the signOut call. Not really sure why you would do that, either way....then firebase thinks the user is signed out, but your server has an active session for that user.
Could anyone shed any insight on this?
There is a line of code from that sample that's important for context:
// As httpOnly cookies are to be used, do not persist any state client side.
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE);
With persistence disabled, there is no saved sign-in state. When the page reloads, redirects, or somehow navigates away, the user is effectively signed out, because their token isn't remembered. The point of the entire sample is to show how to put that token into a cookie, which will be persisted as cookies normally are, and also sent to the server on future requests and can be verified with the Firebase Admin SDK. If this is not what you're trying to do, then this page of documentation isn't relevant.
The signOut that happens in later is merely ceremonial. As the comment above it says:
A page redirect would suffice as the persistence is set to NONE.
Signing out would be an explicit note to the reader of the code that the idea is to use the token stored in the cookie, not in Firebase Auth's own persistence (which, again, was disabled above).

How to detect idToken expiry?

I have a login page that authenticates users using
signInWithEmailAndPassword() using Javascript client SDK.
If a login is successful, user is redirected (along with the idToken) to the member page.
On the server side (nodejs using firebase admin SDK), the member page checks the validity of idToken and if valid, it gets the user-specific data from Firebase and displays it on the webpage. On the member page, there is lots of data to see/edit/delete etc. So it's not inconceivable that a user might spend more than an hour in this page.
My problem is, I couldn't find a way to detect if the idToken has expired. Ideally I would like to refresh and get a new idToken. Is that possible? If that is not possible, I would like to redirect the user to login page when idToken expires.
But I am not able to figure out how to achieve either one. Looks like onAuthStateChanged and onIdTokenChanged are not triggered when idToken expires. And I am not able to do a forceRefresh of idToken like, firebase.auth().currentUser.getIdToken(true). Because on member page, firebase.auth().currentUser returns null.
Any suggestion on how to handle this scenario?
Thanks.
Using the Firebase Node.js Admin SDK, you can check for a revoked or expired ID token when calling verifyIdToken() by setting the checkRevoked parameter to true.
verifyIdToken(idToken: string, checkRevoked?: boolean): Promise<DecodedIdToken>
checkedRevoked: boolean
Whether to check if the ID token was revoked. This requires an extra request to the Firebase Auth backend to check the tokensValidAfterTime time for the corresponding user. When not specified, this additional check is not applied.
admin.auth().verifyIdToken(idToken, true)
.then(function(decodedToken) {
let uid = decodedToken.uid;
// ...
}).catch(function(error) {
// Handle error for expired ID token
});
Alternatively, the ID token payload claims may be checked on the client. The documentation for how to Verify ID tokens using a third-party JWT library show the payload claims.
exp expiration time: Must be in the future. The time is measured in seconds since the UNIX epoch.
jwt.io references libraries that support client-side token verification.
Also see: How to decode the JWT encoded token payload on client-side in angular 5?

React: check user authenticated by the front-end

How can I check if a token is true? I have an api with laravel passport and the front with react, the user puts email and password, the api checks and if you have user in the db it generates a token and stores it in the local storage, I have a private route, and for that I would need to know if the user is authenticated, the question is, how do I verify that the token is true? Previously I did a logic, but not worked, because if someone opened the console and put any value in the token, it returned true and the person was free to access the system.
I would use this function on my private route, if the user was authenticated I would release the route, so I would need to check on the front, if you have a better idea and can give me an example, thank you in advance!
I usually check the token to the back end server.
So at the front end I use a component that send the token to the backend (usually at componentDidMount) if the response is true I will render the private component and if it is false I will use redirect to the login page.
This is the link https://reacttraining.com/react-router/web/example/auth-workflow
Token couldn't be authenticated from frontend, frontend could save token in localStorage, you need to send the token on backend to authenticate it.
First of all understand the purpose of the problem. create logic that can used to validate the token. basically renew your token mean renew you session and the user has to refreshed with the latest data for the panel.
Token cannot be stored at the client side, it can be initiated and processed at client side but you must always validate, if system feels invalid make a force logout or make the session expired.
If you have a private route which navigate the user to another location make sure then add a additional to use the same token or generate a different token.create the route to check the flag and retrieve the existing token and utilize.
Clear the existing one and create the new one to update the system. Front end only should have navigation path if validated only approve. No client side authentication.

What is it the best solution to hide a single page application private pages with Firebase?

I'm going to explain the problem better with an example, in this Firebase official example https://office-mover-demo.firebaseapp.com/ I can show the hidden page without login with a simple command in the console:
app.classList.remove('is-hidden');
Yes, of course, the data in firebase can be accessed only if a user successful logged in. So my question is: Can i do something to show the structure of the html private part only after a successful login of the user? (Only with static content and firebase auth)
From the Firebase documentation on monitoring authentication state:
// Create a callback which logs the current auth state
function authDataCallback(authData) {
if (authData) {
console.log("User " + authData.uid + " is logged in with " + authData.provider);
} else {
console.log("User is logged out");
}
}
// Register the callback to be fired every time auth state changes
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.onAuth(authDataCallback);
Where the snippet calls console.log, you can just as easily show/hide the HTML.
My solution to this problem - as I understand it - is to set a cookie upon user login containing the user's id or, with an additional call to Firebase, a secret visible only to the logged in client. My server can then read the cookie and determine whether the user is authorized to view the content and only then download it. Thus, I am using Firebase for authentication, but my own server for authorization.
It works, and I can also log the user in to my server using this approach just as if I had received an Oauth token.
However, lacking experience with cookies, I would like to know how secure this is!

Check if user Logged in

hey There I completely new to this kind of work! Actually I want to check if user is successfully logged in!
suppose that i have a menu item:
<li>Java</li>
when user clicks on it:
function CheckSignIn() {
//here i want to check login
if (!login) {
alert('please login');
} else {
window.open('new page url here');
}
}
I know how can i do it with php i.e.
<?php
session_start();
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] == true) {
echo (welcome user);//sort of
} else {
echo "please login!";
}
?>
In simple I want to check if user logs in using javascript and i know i cant use php inside java script can somebody help me please! Its not an assignment but i am learning it to my own
You cannot check session variable using JavaScript since a session variable is stored on server. To do this you'll have to call your server side code asynchronously using js. jQuery ajax can help you make the async call.
Very similar to access-php-variable-in-javascript
Even $_SESSION is a PHP variable so I am sure you should be able to get it in javascript variable.
One way is to send a xhr to the server which returns true or false if a user is signed in (aka a session value is set eventually making a database call), parse the response and return true or false.
Another way is to send an encrypted token (jwt is what I use currently) upon login that is stored in the browser's sessionStorage
So either you have everything on the server side
or you have the clientside UI which makes requests to the server side api.
Both have advantages and disadvantages.
If you have a client side UI that makes requests to an api, like in your example I suggest you send a JWT upon login, store it in the browser's sessionStorage.
Now you'd like to check on the client side if a user is logged in for display purposes. So check if a token in the sessionStorage exists, that means a user is logged in. Now when making a request to the server you send that token in a header field. The server checks the token for validity and if valid performs the operation. If not status 403.
This has downsides, the user needs to log in for every browser window it opens. Storing it in localStorage adds new security considerations, which are out of scope of the question (CSP, X-Frame-Options, and so on). JWT by default uses RSA and SHA256 (RS256).
The flow is:
User fills out login form and hits submit
Server receives the login information and if valid sends a token
If reponse status != 403|401 store the token in sessionStorage
When making a request to a protected resource the client sends the token in a header field.
Server checks token for validity
If valid send protected resource (or content that was requested)
Client renders received content

Categories

Resources