Using Firebase for server side authentication - authentication

I have Firebase authentication set up on the client side, and on the server side I can take a JWT token and decode the account ID. But how does this work when I want each page load to be authenticated on the server before the page is generated?
On login or each page load, can I simply store the last JWT token into cookies so that I can read them on my server? Aside from that, I don't know how else for my server to get that information aside from each link being an AJAX call.

This seems to be the only way to do it presuming you're using the firebase auth library to decode and verify the tokens on the server and not some kind of JWT parsing library.
Firebase admin includes methods for decoding and verifying id tokens and extrapolating all the information. This prevents cookie forgery and keeps firebase auth as your single source of truth for whether or not a user is authenticated.
for example (in node):
const admin = require("firebase-admin");
admin.initalizeApp({
credential: admin.credential.cert(yourServiceAccountJsonHere),
databaseURL: "http://YOURDATABASE.firebaseio.com/"
});
admin.verifyIdToken("usertokenasastring") //returns a promise
.then(function(decodedToken){
//process the decoded user token somehow
});
Firebase makes a call to your database, and makes sure that that user is logged in and that all the other information in the JWT makes sense, so you don't have to worry about implementing any kind of verification server side.

Related

Proper way to do jwt refresh tokens with express

I'm thinking of a proper pattern for implementing refresh tokens, but on few steps, I have some questions. I am using nextjs with axios on the frontend and express with cookie-session on the backend.
Here are steps I'm thinking of:
Client sends a log-in request. After logging in I put the access token in the session object and the refresh token into res.cookie, both secure and httpOnly.
// for simplicity options are left out
req.session = { accessToken };
res.cookie("refreshToken", refreshToken)
On every request with axios I supply just the access token. Here's where the first question arises. How would I supply only the access token, without sending the refresh token too, if both are httpOnly?
If the access token is valid do whatever is needed. If not, need to get the refresh token and compare it to a stored one, and so on. Here's the second question. While I understand I need to retrieve the refresh token in this step, how would I do it properly?
Any more advice would be great, thanks.
[EDIT] After some thought I realised that making access token not httpOnly would allow me to send just access token, which would solve my problem. But if that is incorrect please let me know.
Here is the standard pattern - as in this code of mine:
Client sends access token (which may be in an HTTP Only cookie)
When it expires they try to refresh the access token by calling a /refresh endpoint
If the refresh succeeds they retry the API request with the new access token
Otherwise the client redirects the user to sign in again
Don't make the access token non HTTP Only, since any malicious code could then grab it from document.cookie.
This also allows you to set a path of /refresh for the RT cookie, so that it is only sent on refresh requests.
Also ensure that cookies containing tokens are strongly encrypted (AES256) using a symmetric key only known server side. This Express library will do the work for you.

Authorization between nuxtjs and the backend API

I have a Vuejs application created using Nuxtjs. I am also using Django as the backend server, and I made an API to interact with the backend server (Django) and front-end app (Vuejs/Nuxtjs). And any API related fetch are done in the AsyncData function of the page to render the data on the server-side using axios. Also, I am using json web token authentication, and the API generates a jwt token after successful login which is stored in the cookie. So on the backend, it will always check for the request's authorization header for the token. If the request is from a logged in user (authorized token) then return authenticated json data, or else return non authenticated data.
The problem:
When the user navigates to the app, I would like to check if the user is authenticated. If the user is authenticated, render the authenticated page. If not then display non authenticated page.
My thoughts:
When the fetch is done from the App on the AsyncData function, I would check whether there is any value for the cookie. If there is then send the token with the request's authorization header. But, since the page will be rendered on the server first, and not on the client side (where the cookie actually is) it will never find the token for the authorization.
How can I check if the user is already logged in or not so that I can get authenticated and non authenticated data respectively from the API?
Update
When I successfully log in (post authorized email and password), I get a json response back with the token, which I set in the cookie like this:
this.$cookie.set('my_auth_token', this.token, {expires: 15})
How can I retrieve client side cookie and into the nuxt server for server side rendering?
Cookies are exposed in the (Express) Nuxt server through middleware.
Specifically, they can be read from the req.headers.cookie property. You can see an example implementation of this in the Nuxt documentation.
Regarding your implementation: fetching the privileged data from your API using Node would seem to be the ideal way to delegate session handling to that single service (rather than both) and provide SSR for your users.
If you've chosen to instead implement your session handling on the Django service then you'll need to "forward" your cookies by passing them into your axios request headers.
I did something similar using Firebase authentication. There is an example project on Github as well as a blog entry outlining the important files and configuration used in the application.

How do I read Passport.js user info on client side?

My app is using Angular2 for the front-end, served by a separate (cross domain) backend server running express and using passport.js for Google Oauth authentication.
When a user is authenticated by the server using Passport (through google oauth), their user data is loaded from the database and included in the credentials, which is used to determine which backend API routes they are authorized to use. (It's based off this tutorial on scotch.io that I'm sure everyone has seen: https://scotch.io/tutorials/easy-node-authentication-setup-and-local )
I want to access this user object in my front-end as well to enable route-guards that depend on a user's access level (defined in their user object on the server).
From this question it seems the data is sent via a JWT and is readable on the front-end, just not changeable, which is fine: https://www.reddit.com/r/Angular2/comments/4ud0ac/ng2_secure_connection_front_to_back/
How do I access and read that token on the client? All I can find is the 'connect.sid' session cookie set by express. The payload of the cookie doesn't fit a standard JWT as it only has 2 sections, not 3.
You are probably not using JWT but cookie-based sessions if you followed the tutorial. The cookie only contains a session ID which your server uses to identify the session from the session store, and using this information you probably dig up something from the database in deserializeUser. That is then available to you in req.user in the backend.
You could of course add the user data to the response of every request but if you really are using cookie-based sessions sending the user object with every response likely makes little sense. You could eg. just add a route that will return the relevant parts of req.user:
app.get('/users', function(req, res) {
res.json({ username : req.user.username });
);

django rest framework - token authentication logout

I have implemented the Token Authentication according to the django rest framework Docs.
Form what I read, the Token Authentication of DRF is quite simple - one token per user, the token doesn't expire and is valid for use always (am I right?).
I understand that there are better practices out there, but for now the DRF token authentication is fine for me.
my question is- what is the best practice for logout with the normal DRF token authentication?
I mean, when the user logs out, should I delete the token from the client side? and then on login get the token again? should I delete the token and generate a new one?
Anyone with experience with this?
Here's a simple view that I'm using to log out:
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
class Logout(APIView):
def get(self, request, format=None):
# simply delete the token to force a login
request.user.auth_token.delete()
return Response(status=status.HTTP_200_OK)
Then add it to your urls.py:
urlpatterns = [
...
url(r'^logout/', Logout.as_view()),
]
WHOLE IDEA OF TOKEN AUTHENTICATION:
Normally in authentication services, there is a lifetime associated with a token. After a specific time, the token will get expired. Here, we get an access token which has an expiry time sent along with it by the server. Now the client needs to send this token everytime in the request header so that the server can identify who the user is. Either we can keep track of when it expires or we can just keep using it until we get an INVALID_TOKEN error. In that case we would have to again get the token from the server.
The lifetime of the access_token is independent of the login session of a user who grants access to a client. OAuth2,lets say, has no concept of a user login or logout, or a session. The token is just used to identify the user if he is who he says he is.
The token is unique for a user and client. You may save it to cookies to enable something like remember me but on the server you don't need to delete it. Whenever the token expires, the client need to send a request to the server to obtain the token again.
Token Expiry in DRF Token Authetication:
Currently, DRF Token authentication does not support this functionality. You would have to implement it yourself or use a third party package which provides this functionality. It should check for token expiry and raise an exception if the token has expired.
To implement it yourself, you can subclass from the DRF Token Authentication class and add your logic.
You can even use a third-party package django-rest-framework-expiring-tokens.
Some References:
1. Token Authentication for RESTful API: should the token be periodically changed?
2. How to Logout of an Application Where I Used OAuth2 To Login With Google?
It sounds like SessionAuthentication is what you are really looking. You can start(login) a session via BasicAuthentication or TokenAuthentication. Then use sessionid as your "token" for the rest of api calls. The "token" expires when you logout or exceed certain timing.
If you run into csrftoken issue using session authentication, this could be a very helpful.

CSRF Token necessary when using Stateless(= Sessionless) Authentication?

Is it necessary to use CSRF Protection when the application relies on stateless authentication (using something like HMAC)?
Example:
We've got a single page app (otherwise we have to append the token on each link: ....
The user authenticates himself using POST /auth. On successful authentication the server will return some token.
The token will be stored via JavaScript in some variable inside the single page app.
This token will be used to access restricted URLs like /admin.
The token will always be transmitted inside HTTP Headers.
There's NO Http Session, and NO Cookies.
As far as I understand, there should(?!) be no possibility to use cross site attacks, because the browser won't store the token, and hence it cannot automatically send it to the server (that's what would happen when using Cookies/Session).
Am I missing something?
I found some information about CSRF + using no cookies for authentication:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
"since you are not relying on cookies, you don't need to protect against cross site requests"
http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
"If we go down the cookies way, you really need to do CSRF to avoid cross site requests. That is something we can forget when using JWT as you will see."
(JWT = Json Web Token, a Token based authentication for stateless apps)
http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
"The easiest way to do authentication without risking CSRF vulnerabilities is to simply avoid using cookies to identify the user"
http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
"The biggest problem with CSRF is that cookies provide absolutely no defense against this type of attack. If you are using cookie authentication you must also employ additional measures to protect against CSRF. The most basic precaution that you can take is to make sure that your application never performs any side-effects in response to GET requests."
There are plenty more pages, which state that you don't need any CSRF protection, if you don't use cookies for authentication. Of course you can still use cookies for everything else, but avoid storing anything like session_id inside it.
If you need to remember the user, there are 2 options:
localStorage: An in-browser key-value store. The stored data will be available even after the user closes the browser window. The data is not accessible by other websites, because every site gets its own storage.
sessionStorage: Also an in browser data store. The difference is: The data gets deleted when the user closes the browser window. But it is still useful, if your webapp consists of multiple pages. So you can do the following:
User logs in, then you store the token in sessionStorage
User clicks a link, which loads a new page (= a real link, and no javascript content-replace)
You can still access the token from sessionStorage
To logout, you can either manually delete the token from sessionStorage or wait for the user to close the browser window, which will clear all stored data.
(for both have a look here: http://www.w3schools.com/html/html5_webstorage.asp )
Are there any official standards for token auth?
JWT (Json Web Token): I think it's still a draft, but it's already used by many people and the concept looks simple and secure. (IETF: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token-25 )
There are also libraries for lot's of framework available. Just google for it!
TL;DR
A JWT, if used without Cookies, negates the need for a CSRF token - BUT! by storing JWT in session/localStorage, your expose your JWT and user's identity if your site has an XSS vulnerability (fairly common). It is better to add a csrfToken key to the JWT and store the JWT in a cookie with secure and http-only attributes set.
Read this article with a good description for more info
https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
You can make this CSRF protection stateless by including a xsrfToken JWT claim:
{
"iss": "http://galaxies.com",
"exp": 1300819380,
"scopes": ["explorer", "solar-harvester", "seller"],
"sub": "tom#andromeda.com",
"xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}
So you will need to store the csrfToken in localStorage/sessionStorage as well as in the JWT itself (which is stored in a http-only and secure cookie). Then for csrf protection, verify that the csrf token in the JWT matches the submitted csrf-token header.