Server-Side Session with Django REST Framework and Token Authentication - django-rest-framework

I am using token-based authentication (via dj-rest-auth 1.1.2) on my Django REST-Framework (DRF v. 3.12.1) project. After an initial view-base login, the server issues a token that the client has to include in the HTTP Authentication header with each request.
What I would like to do is to associate the token authentication with a server-side session, similar to what the Django Session Framework provides. That is, I would like to create a cacheable session object that stores information like user roles, which otherwise would need to be retrieved from the DB with each request.
It seams that there is no ready-made solution for this problem, is there? To my understanding, the Django Session Framework only works with session cookies but not with other tokens. On the other hand, token-based authentication does not create a server-side session, it seems.
My questions:
Is this correct, or am I simply missing some configuration or mis-reading the documentation?
If yes, is there something inherently flawed with my intended approach (which would explain why I cannot find a library that already does it)?
Again if yes, what would be the canonical solution handle complex user roles on each request? Just store them in the DB and let proper caching take care of it?
Thanks for your help!

Related

Is it safe to share authentication state via reactive global store in Vue 3?

I'm building a CMS with vue 3 and want to know if using global store store.store.auth = false/true is a secure way of rendering in/out components that are supposed to be seen only by authenticated users. It goes like this:
User enters credentials in login form
Credentials are sent via HTTP request to backend and checked by laravel sanctum
Response arrives in frontend which sets store.store.auth = true
Components and routes that are supposed to be seen only by authenticated users are rendered via v-if
Is this a secure approach or can it be improved?
The security, in this case, depends almost entirely the backend.
Sanctum does not use tokens of any kind. Instead, Sanctum uses Laravel's built-in cookie based session authentication services. Typically, Sanctum utilizes Laravel's web authentication guard to accomplish this. This provides the benefits of CSRF protection, session authentication, as well as protects against leakage of the authentication credentials via XSS.
src
It seems like sanctum handles the authentication, so you should be fine as long as
store.store.auth value is kept up to date, and
the API does it's own authentication and authorization.
Because the entirety of the application is visible through the js source someone could potentially modify state and display options that they shouldn't see. This would be really-really difficult to prevent in SPA, that's why it is paramount that the backend handles this correctly.
You may be able to use code splitting, to prevent loading parts of the application that require authentication, but this is not security measure.

Store JWT in a NextJS app with a Spring backend

I'm currently building an app using NextJS and some Spring microservices backend, but have encountered some doubts regarding the handling of the JWT.
My problem is that I want to create private pages, so I was storing my JWT token that comes from my Spring backend in an Authorization header and I was storing it on local storage, but when I try to grab my token on ServerSideProps I can't access local storage, so I went to find another solution to where to store my token.
I found out that you can store the token in an HTTP-ONLY cookie, but I have some doubts:
If I save my token on an HTTP-ONLY Cookie in my Spring Security
microservice when the user logs in, it will be available to grab at
any time on my ServerSideProps on NextJS frontend? Or I will have
to somehow save it in my frontend when receiving the response from
/login?
I have an AuthContext which stores the logged user, should I instead ditch cookies and localstorage and just store the JWT here in context and then somehow grabbed it on ServerSideProps, even though you can't access a hook inside there.
I need a little guidance on how people solved this issue using a custom backend, have looked through Google but people mostly use third party auth providers.
Storing cookies in the browser is today a bad idea due to the various security problems that comes with doing that.
A better idea today is to use the BFF pattern as described here:
https://www.youtube.com/watch?v=lEnbi4KClVw&ab_channel=PhilippeDeRyck
https://blog.bitsrc.io/bff-pattern-backend-for-frontend-an-introduction-e4fa965128bf

How to access a secured API in the frontend?

There is a lot of good content on the internet that explains how to secure a Spring API with Keycloak: Create a Client that represents the API Service in Keycloak and use a link like the one below to get the access and refresh token:
<Domain>/auth/realms/<realm>/protocol/openid-connect/auth/{some parameters}
This yields both tokens. So far so good.
Now, however, I am not sure how the flow for the frontend accessing the API should look like.
Should the frontend directly access this endpoint and, therefore, obtain the access and refresh token? That would mean that the API can only have the access-type public because there is no way to store the client (the API) secret securely.
Or should there be a third server that somehow stores the refresh token for each user, that the user can call if his access token is no longer valid. This server would then use the client's refresh token (and the client secret that could be stored securely, since it would be in the backend) to get a new access token from Keycloak and would forward it to the user.
I guess the main question that I am asking is, whether the client/user should get the refresh token.
If one needs to implement a logic according to the second option, I would be interested in a link or description of how something like this can be done in Spring.
I think, in either case you need to use the Authorization Code Flow. The implicit flow, which was recommended for SPAs (frontends without a backend server) in former versions of OAuth2 must not be used anymore.
The best option is to have a backend server, so the user retrieves the auth code via redirection and the backend server exchanges this auth code with the access and refresh tokens (and keep them without forwarding them to the frontend).
If there is no backend in place and your frontend needs to retrieve and hold the tokens directly, I would recommend to use the Authorization Code Flow with a public client and the PKCE extension (which - put simply - ensures that the entity asking for the auth code is the same as the entity asking for the tokens and that the auth code was not stolen and used by a foreign entity). There are several sources with more detailed explanations, which might help you, for example: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce
Hope this helps you with your architectural considerations.

IdentityServer4 how to store and renew tokens in authorization code flow

I am looking for the best approach to work with the IdentityServer4 autorization code flow.
My apps system is quite ordinary: I have an MVC client, a WebAPI and the IS. I also use AJAX to request the API from the client side. So I need the access token on the client side to put it into the authorization header.
Is it good idea to store access token in the cookies?
Do I need self-contained or reference token (it is about security, I suppose)?
What is the best approach to renew when it was expired?
I thought about the two strategies:
Update access token when the first 401 status code was recieved. Can be the problem cause I send more than 1 query to the API and I need to synchronized them and recall the first one (to get result);
Every time before API calling call the MVC client method with GetTokenAsync, check the expire time and get or update and get access token. Seems cheating, cause I need to call the MVC client every time when I want to call the API.
Could you help me to find the best way?
"Is it good idea to store access token in the cookies?"
No, not with the authorization code flow. If you are using an MVC web application you should find a way to store tokens in some kind of datastore away from the browser. All the MVC application should administer is a cookie to access future MVC endpoints (that will make subsequent calls to Identity Server with the appropriate access token in the datastore).
"Do I need self-contained or reference token (it is about security, I suppose)?"
That's all up to you and what you think is best for your use cases. If you'd like to see the information in the access token and skip the extra backend call for validation then use reference tokens. Strategy 2 requires you to use self-contained tokens so that you can check the expiry.
"Could you help me to find the best way?
I don't know if I can give the "best" way, but I'd probably go with strategy 2 and use self-contained tokens.
EDIT: If you wanted to use "axios , to get data from the API" then I would suggest using the implicit flow which has no concept of a refresh token. In this case, leaving it in the cookie should be OK.

Angular CSRF token + ruby api

I'm currently running into a lot of issues with the CSRF token.
Our current setup is a Ruby API and an Angular front-end, both live on a different domain.
The Ruby back-end solely serves as an API for the front-end.
I've spend a lot of time researching this problem, but I can't find a proper solution.
So far the solutions I've found are:
Generate the token and insert it into the DOM (Different domains, so can't do that)
Let the API return the CSRF token on a GET request (Doesn't seem to work, and it's not a good solution since I don't want to make an extra request just to get the token)
So I'm rather stuck here and not sure how to continue.
Is the current implementation just not working? How do other people create an API with oauth without running into this issue?
Not sure if this will help but here is a sample of a simple todo api in ruby with angular as frontend, and i am using token for authentication generated after the user fills username and password.
https://github.com/sirfilip/todoapi/blob/master/app.rb (the api written in sinatra and sequel)
https://github.com/sirfilip/todoapiclient/blob/master/public/js/angular-todoapi-plugin.js (angular client api service that is used for communication with the api)
TL;DR: Secure your rails API with the doorkeeper gem.
This SO post seems to be the accepted answer when your api and client exist on the same domain.
In the post they outline the angularJS docs http://docs.angularjs.org/api/ng.$http :
Since only JavaScript that runs on your domain could read the cookie,
your server can be assured that the XHR came from JavaScript running
on your domain.
To take advantage of this (CSRF Protection), your server needs to set
a token in a JavaScript readable session cookie called XSRF-TOKEN on
first HTTP GET request. On subsequent non-GET requests the server can
verify that the cookie matches X-XSRF-TOKEN HTTP header
It seems that the security of storing and transferring the XSRF-TOKEN session cookie in this way hinges on having your api and your front-end be in the same domain. Since this is not the case, you may have to implement another form of authorization for any given client session, like OAUTH. I'd recommend taking a look at the doorkeeper gem. The gem will give you the ability to interact with your api as if you were any other client.

Resources