How to remove JWT from DB after cookie is deleted by browser - database

I am using Express and Node.js for my API and another Auth Server. Currently, when a user logs in, a refresh token is sent back in an Http cookie and an access token is sent back and stored in localStorage. I have set it up this way because it allows for the user to have multiple sessions in other tabs/browsers etc. When a user logins, if they hit 'Remember Me' an item in LS is stored that says to login next time, and on app start it checks that and calls the API for login if it's true. It will then send the Access Token stored in LS and the cookie as well. When a user first logins it will get a refresh and store it in the Database in an array of tokens (to let multiple sessions work w/o overriding tokens), and then every subsequent request will check the cookie token vs the one in the DB. This all works fine UNTIL the cookie is deleted. Once the user closes the browser or it removes the cookie manually, the one in the DB stays there and overtime will just rack up tokens.
So my question is: How do I remove the token in the DB once the cookie is deleted/removed?

Related

Authentication with JWT in HTTP only cookie without refresh token

The motto of the upcoming question is "I don't know what I don't know".
I would like to know if there are downsides or security risks with an authentication implementation.
Right now, I'm storing a JWT in an HTTP only cookie to send it from the client (React application) to the server (Spring Boot/Kotlin application). This removes the XSS vulnerability.
The JWT follows the basic principles (encoded secret, expiration date, issuer check, etc.). The server has servlet filters that check an existing cookie for validity on every request. When signing in via the client, the server responds with a valid JWT:
The client will send its cookie with every request, which is furthermore checked for validity by the server's servlet filters on every request. When these checks are positive, the user is authenticated with Spring Security.
As described above, the JWT expires after 1 hour, 1 day, or whatever is configured. That's why I need to refresh it some way or another. Now, instead of using a refresh token and placing it in the client's local storage, I decided to just make a small request to the server and create a new JWT, which is send back via the response again:
Again, when the refresh endpoint is called, the servlet filters will check for validity. So only an already authenticated user will receive a new JWT token that way. Some invalid JWT will not receive a new JWT.
I'm calling this endpoint from the client in an interval and therefore regularly extend the expiration date of the JWT inside the cookie.
What I'm aware of:
With the current refresh mechanism, an access token can be valid indefinitely (when the user is signed in regularly).
I also don't persist valid tokens or sessions in the database, so I can't really invalidate specific user sessions "globally" that way, as the cookie is the only source of truth. But this has nothing to do with the refresh token, I could create such whitelist/blacklist via the user ID instead.
If something really bad happens, I could still
...change the expiration date of all JWT to 0, so every authenticated user will be unauthenticated the next time he sends a request.
...or I could change the JWT secret, from which one no request will be authenticated anymore.
My question is: Has what I'm doing (replacing the JWT inside the cookie) any more downsides?

How jwt token get reissued in azure ad OuthImplicitFlow

Currently the scenario is. When I am trying to access my app,it first sends my app to Microsoft login page and after successful login it returns a id token which is used to retrieve the data from backend server. Now the expiry time of token is approx 1 hr. Now when this token expires, Microsoft issues a new token(JWT Token), it not redirects me back to login page.
But ideally it should be redirected to login page, as in implicit flow, there is no refresh token. Then on what basis it is issuing a new token ?
I am using Microsoft adal library in my front end side for authentication.
here's the link: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow#refreshing-tokens
The implicit grant does not provide refresh tokens. Both id_tokens and
access_tokens will expire after a short period of time, so your app
must be prepared to refresh these tokens periodically. To refresh
either type of token, you can perform the same hidden iframe request
from above using the prompt=none parameter to control the identity
platform's behavior. If you want to receive a new id_token, be sure to
use id_token in the response_type and scope=openid, as well as a nonce
parameter.

How to determine in Keycloak JS adapter whether user is logged in with SSO?

To introduce my current setup, I have 3 components:
Website with some static (CMS) and dynamic parts, a couple of Single Page Applications, everything works on domain spa.com.
REST API, which provides any dynamic functionality (user profile) and is hosted on api.com and requires SSO tokens to work.
SSO server is hosted under sso.com domain
I'd like to determine in my SPA whether user has an active SSO session, so when I'm logged in but I do not have tokens, I can:
do a redirection dance to get tokens
do not allow user to use registration form
I'm using Keycloak JS adapter, which uses iframe mechanism and checks for KEYCLOAK_SESSION cookie and communicates with host window via some flags:
var cookie = getCookie('KEYCLOAK_SESSION');
if (cookie) {
data.loggedIn = true;
data.session = cookie;
}
The problem is that I can not rely on this cookie to check if user is logged in because the cookie has 30 day expiration date, which is way more than an actual Keycloak session lasts, let's say 15 minutes.
This cookie is being set when user gets authenticated and is not refreshed on each token update. I do not understand then it's purpose and the purpose of this flag.
I'm also thinking about relying on local storage and keeping refresh & access token there to determine if user is logged in, either by checking timeout or trying to refresh access token. BUT.. this also is not reliable, because user might have already authenticated using some other application.
To add more context to the problem... one of my SPA applications is a registration wizard, which uses REST API to register user and receives login_hint in return. This login_hint can be used as a wildcard in SSO redirect to pass the challenge and log in immediately.
However, if some other user is already logged in, we get in return session of this other user, not the one that should be logged in because of used login_hint.

Google OAuth2 flow and id_token refresh

I am having troubles in implementing OAuth in the right way.
I use a client/API architecture (Angular for front and Node.js for back) and I would like user to sign in using Google OAuth authentication only.
Here is what I think is the right way for the moment (tell me if I misunderstood something) :
Angular open a Google popup asking user's consent.
Once the user agree, Google Authorization server sends back to angular a verification code.
This verification code is forwarded to an API endpoint.
Then, the API asks Google Authorization server to exchange this code for an access_token, an id_token and a refresh_token.
Google sends those 3 tokens.
The API uses access_token to retrieve user from Google API
The API persists the user
Here is the little dillema, in my opinion, the access_token and refresh_token should be stored into the database and the id_token should be sent back to Angular client.
This way, it would allow the API to ask for resource in Google API and if the token expires it can still ask for a new token thanks to the refresh_token.
Client-side, the id_token is embedded in all requests thus allowing the API to identify the client and verify his authentication with Google certs from https://www.googleapis.com/oauth2/v3/certs.
Supposing this is right way to use tokens, how could I deal with id_token expiration since client does not have any refresh token ?
Thanks !
I do it slightly different (I have the same basic architecture though).
Angular decides the user needs to log in and displays a login popup.
The url in the login popup is not serviced by angular, but is instead directly run off of the backend server: /auth/google . (I use hapijs and bell, personally).
/auth/google is serviced by a bell plugin and initiates the OAUTH dance.
the end of the OAUTH dance results in my node server generating a local token (I just generate random bytes and store them in redis mapped to user ids)
because the initial login popup was created by window.open, the success page (generated on the api side rather than in angular) can use window.opener.postMessage to communicate the token back to the angular runtime.
This way, all my sensitive google credentials (the user's oauth token, refresh token if needed, and my application's api ID and secret) are only on the server, except for during the OAUTH dance relay when they're in a URL string during the client redirects. This is reasonably secure.
Then for all the actual user interactions with the api, I use the token I generated in step four to authenticate. This could be a JWT if you wanted, but I don't do it that way; I just use redis to map from 'longrandostring' -> userId. That lets me (for example) force everyone to re-login if I wipe the redis database that has all the tokens stored, or I can write a lua script to delete all the entries that map to a certain userid.
If you need a refresh token, you can set access_type=offline in the initial request to oauth2/auth, and you'll get a refresh token as part of the response, unless you've previously gotten a refresh token. You can then persist it on the server side and get new access tokens as needed. If you set approval_prompt=force as well, you'll force a new consent screen and be guaranteed a refresh token (but after some small number of refresh tokens granted to a user, older ones expire on the same application so it's best to only request them if really needed).

How do I only initialize on session instance in Express?

I have a website that has Angularjs on the front-end and Expressjs on the backend. I am tyring to implement authenticated and unauthenticated sessions for my users.
The problem I am having is that when a user goes to the website for the first time, there are several http requests that happen simultaneously to gather all of the data for the page. Since the user does not have a session cookie yet, Express generates a new session for each of these initial requests.
My server uses app.use on each request and verifies whether the passed in cookie is in the session store. If it isn't in the session store, then a new session is created. However, the server is called multiple times in a split second on page load, which causes four new sessions to be created - one for each request. How can I overcome this so that only one session is created?

Resources