Avoid refresh token for authentication when using HttpOnly cookie - authentication

I have a solution for an authentication system without using refresh token. Please tell me where are the vulnerabilities of this method.
I assume the following:
Client and Server are on the same domain.
Client is a browser that support HttpOnly cookie.
Client is using a Single Page Application.
The steps are:
User login by making a request to /api/auth with the credentials.
Server authenticate the user and send back a Set-Cookie Header with an HttpOnly cookie containing a JWT.
Client receive and set the HttpOnly cookie. Client also set in Local Storage a variable logged: true.
After sometime User reopen the browser. The Single Page Application check if the variable logged in Local Storage is == true. If so check if it still has the HttpOnly cookie by making a request to /api/check-cookie.
Server respond with true if it find the HttpOnly cookie and it is valid. Otherwise false.
Client, if receive false from /api/check-cookie, will prompt the user with the login.
With this approach the JWT can have a long expiration date and there is no need to keep track of refresh tokens.
Am I missing something?

I like your thinking and had similar ideas, particularly with setting a local storage variable to reflect the state as logged in so I could check that before making a pointless server call to refresh a token that potentially doesn't exist, however, I'm still using the refresh token.
I believe the crux of your issues will be when the user updates on the server side, it won't be reflected on the client side until the user re-authenticates with a new long-lasting, singular token as opposed to when the short-lived access token refreshes, setting the user again with the updated data.

Related

How to use two factor authorization cookie along with single factor authorization cookie

I have a web application with singe factor authorization and now have implemented two-factor authorization. I am using the Microsoft Identity for the log-in. The problem is - so far we have used a cookie to remember the user while providing the username and password. Say that as 'signglefactorcookie'. Now on the authenticator application authorization page(TFA), I have added another cookie for the remember me option. Say that as 'twofactorcookie'. Now how can I make my client request for both cookies when I use the below code?
// Check whether there is a valid session or persistent cookie
if(this.User.Identity.IsAuthenticated){
// Move to a landing page
}
Problem scenario
Now the problem is, if I log in to the single-factor authentication page with the correct user name and password and land at the two-factor authentication page.
Open a new tab and try to access the home page getting success since there is a single factor cookie that is recognized which makes the user authorized.
How can I make it in a standard way?

Secure way to store authorization data inside a PWA

I am trying to design a secure API, which then will be used by a PWA on desktop and mobile.
I have the following flow:
A POST request with the user's credentials is issued to endpoint /session at login.
If the the credentials are correct it will set a Secure, HttpOnly cookie which contains a refresh token with Path=/session/renew. This way it's only sent to that endpoint, cannot be accessed from JavaScript, and will only be set on HTTPS.
The response will also contain a JSON object with an access token. This will be used for every other authorized request. It will be passed along in a Authorization: Bearer ${access_token} header. The token's max age is 30 minutes.
Before the access token expires I can call to /session/renew with the cookie set and this will give me new access token and will also set the new refresh token in the cookie with the same properties as above. The old tokens will be revoked on the server.
The access token is stored in a Redux store. Unfortunately, this poses a problem.
Now if open a new tab, I can request a new token on /session/renew, but with this setup I will "stole" the previous tab's ability to request new tokens as those will be revoked by this call and the user will just get logged-out on that tab.
I see a few solutions, but none seems to be secure enough to me:
Don't revoke the old access and renew tokens when /session/renew is called
Store the access token in session or local storage
I did quite some research and still don't see what would be the correct (and not too complicated) solution here.

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.

fetch httponly cookie persistence through app closures

I am currently using httponly cookie based authentication to authenticate users through a website. On top of this I am creating a react native app which also has to authenticate users, ideally through the same endpoint. At this point users are able to log in through the app and the cookie is correctly send on each subsequent request using credentials: 'include' (fetch). However, if the app is restarted, the cookie does not persist.
So far my searching has led me to the following possible workarounds:
Manage cookies manually by extracting the cookie through something like webview or react-native-cookies, saving the cookie to storage and manually adding it to each subsequent request.
Implement a new endpoint that returns a token and have two authentication flows, one for the website and one for the app.
Have anyone been in a similar situation? Can you point me in the right direction, so not to over complicate my code base and ensure that I am not vulnerable to XSS or other token/cookie theft.
Thanks in advance.
To be honest I never implemented cookie based authentication in react native. How do you handle cookies now ? Basically the flow should be like this:
You authenticate with username and password.
Server will respond with a header "Set-Cookie: sessionIdExample=1234"
Next time when you make a request you should also send that cookie, meaning you have to set a header "Cookie: sessionIdExample=1234"
From your question I guess you don't manually set that cookie, so most probably the http client is doing this for you. Now when you close the app that cookie value is lost as you said. Notice that switching to a token based authentication won't help with this. So what should you do:
Login with username and password.
When you receive that session cookie persist it. You can check async-storage or the more secure react-native-keychain for persisting data.
For the following requests set the session cookie manually.
When you close the app and then open it again, check in your async-storage or keychain if you already have a cookie saved there. If so, set that cookie and everything should work fine.

Web API 2, OWIN Authentication, SignOut doesn't logout

I'm doing some research for work with a view to using Bearer tokens as an authentication mechanism (i.e. AngularJS UI, authenticates via OWIN in a Web API [2] project).
I have the login working fine, role information and all that is fine, but I cannot get the token to logout.
My startup configuration is this:
OAuthOptions = new OAuthAuthorizationServerOptions() {
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AccessTokenExpireTimeSpan = SESSION_TIMEOUT,
AllowInsecureHttp = true
};
And my logout action is simply this:
public HttpResponseMessage Logout() {
var authentication = HttpContext.Current.GetOwinContext().Authentication;
authentication.SignOut(DefaultAuthenticationTypes.ExternalBearer);
return new HttpResponseMessage(HttpStatusCode.OK);
}
I've left all the authentication stuff out for brevity, but to confirm I am using ExternalBearer when setting up the token.
In my UI I'm storing the token in local storage (no cookies are involved here, which is a deliberate design decision). So I have a logout button on my UI, the Logout action is hit and the code runs fine.
However if I subsequently hit the an action on the API which requires authorisation, the request still goes through (i.e. the user is still authenticated even though they should have been signed out.
Either I'm missing something really obvious (wouldn't be the first time ;-) or there's something more fundamental going on here - finally I'm pinging #leastprivilege as I know this is their area.
Any help or insight would be gratefully received.
Only thing I can think of is that the token is stateless on the server/API side and hence can't be expired or signed out.
If that is the case I guess I could either:
a) Add a refresh token which creates a new token that expires in the past - would this even work? - actually cancel that, it would issue a new token ... the old one would still be valid
b) Store the bearer token in the database and check each time, removing the token on logout (naturally salted, hashed, etc). However this is just bringing us back to having a stateful server.
c) I can (and will) be removing the token from local storage when someone explicitly logs out, however the token is still technically valid if a baddy can intercept the token. Naturally all the above will be over SSL anyway, which should inhibit the bad guys/girls.
d) Perhaps this is why lots of people are storing the Bearer token in a cookie (as a storage mechanism) so once you logout as least the cookie will be removed on the next refresh.
Sorry the above is a bit of a brain dump, just wanting to pre-empt any questions
Since OAuth is not an authentication protocol, there is no notion of signout. Delete the access token on the client - that's all you can do.
If you want to invalidate the token on the server side, add a unique id to it and keep track in your service - you would need to manually build something like that.
I have a beautiful solution here: http://www.nakov.com/blog/2014/12/22/webapi-owin-identity-custom-login-service/. It is custom user session implementation for Web API OAuth bearer token authorization based on OWIN and the standard ASP.NET Identity (Microsoft.AspNet.Identity.EntityFramework). It works as most people may expect:
Web API sessions die after 30 minutes of inactivity.
Session’s life is extended at each authorized HTTP request with additional 30 minutes.
Logout works correctly: after logout the bearer access_token becomes invalid (its is revoked).
Full working source code is available at GitHub: https://github.com/SoftUni/SPA-with-AngularJS/tree/master/Ads-REST-Services
This question has been here for ages (and answered too), but I only wanted to chime in my thoughts.
I would do similar to your (C) option, but use a shorter expiry on the bearer access token something like 10 or 20 minutes, so that when you have logged out and deleted the token on the client, although technically the token is still valid, the bad man will have only the remainder of the expiry time to play with your valid token.
In practice, I would use this together with a long-lived refresh token, so that I can get a new bearer token if it expires and want to continue interacting with the API resources, without having to authenticate again.
As long as I know the bearer token lives in the client side so I don't think that you need a server side "logout" function. Just remove the token from the client local storage should log you out.