Django memcached session get deleted - django

Two Django applications(DRF) are running on two separate ports 8001 and 8000 with same host localhost. I am using memcached to store the sessions. Both the application share the sessions from the memcache. when i try to access pages using second application after logining in using first I am getting error :
"The request's session was deleted before the request completed. The user may have logged out in a concurrent request, for example."
I want to build a distributed apps where one app can be used for auth running on a separate docker, so other apps can share the session using memcached
Sessionmiddleware is able to populate the session object in the Request object, but after execution of below line of code in AuthenticationMiddleware
request.user = SimpleLazyObject(lambda: get_user(request))
The session._session dictionary elements got deleted.

In the above case you are running application on two different ports with the same database. If user1 logged in with port 8000 then a session will be created for him. And again user1 logged in with port 8001 then the existing session will be replaced/destroyed by the new session. Because browser treats localhost:8000 and localhost:8001 as two different domains.
To avoid it you can use nginx as a reverse proxy server with same ip 127.0.0.1 or domain localhost. Now, route the api requests to port 8001 and web requests to port 8000.
In above case the domain localhost remains same so django will not replace existing session. So, It will work.
Reference: https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/

To solve this issue we need to add the same secret key in the settings in both Django applications.
Django adds the user in the request body in authmiddleware. The user can be anonymous(unauthenticated) or authenticated user. The session is verified before adding the user in the request. This verification is done as follows.
session_hash_verified = session_hash and constant_time_compare(
session_hash,
user.get_session_auth_hash()
)
This user.get_session_auth_hash() function uses salted_hmac(key_salt, self.password).hexdigest() function for verification. salted_hmac function uses settings.SECRET_KEY for calculating the hash. If both applications secret keys are different then session hasj will not be varified.

Related

Flask application using login session across the website

i have two flask application which using flask_login to authentication the website.
These two app have deploy on separate VM and using the same public ip but different port, for example.
------------------------------------------
APP NO. PUBLIC IP
------------------------------------------
flask_app1 202.102.222.153:80
flask_app2 202.102.222.153:4000
Problem
When i login to the website flask_app1 with some user then i access to the website flask_app2(on the same browser), the flask_app2 it redirect to the main page without do any login and when i check the login Cookies session it have the same session value with flask_app1.
So why these two website can use the same login session and how can i fix that
PS. The user that used to authentication these 2 website also have the same db id.

Making sense of "Storage" in a browser

In this post about sessions, they basically say a session is a way the server has to identify a client (in subsequent requests).
The process consist in giving the client a cookie, that's the id. The client sends a request, the server does something like Session[cookie] --> details.
Some NodeJS/Express servers can create a session on connection, and set the loggin to true after successful authentication. Following the previous paragraph, we could do Session[cookie].loggedIn==true, then allow something.
I can see this either persistent or expiring cookies in the browser "storage" in the console.
But where in the server, and where on my machine is stored this data? Would a persistent cookie persist not only browser shutdown but also PC restart?

How to setup OpenID to work with load balancer?

The stack I'm currently using is:
Keycloak
flask
flask-oidc
nginx as load balancer
The set up I'm having is I have two instances of a service running (instance1, instance2). The issue I'm facing is:
A user uses web browser to authenticate by going to https://mycompany.com/auth/login
instance1 handles this request and redirects the user to Keycloak for authentication
Keycloak redirects the user back to the app using redirect url (https://mycompany.com/auth/auth_callback)
This time the load balancer routes the request to the redirect url to instance2. Here instance2 errors out with a response from Keycloak saying "{'error': 'invalid_grant', 'description': 'Incorrect redirect uri'}", which is very confusing because the redirect uri is correct.
I am not entirely sure why this set up is not working. But after reading through how openID works, I kind of suspect it has to do with the state parameter (https://auth0.com/docs/protocols/oauth2/oauth-state). Again, I am not entirely sure. But it has to be something that's only local to instance1, which instance2 doesn't have.
How do people tackle this issue ? Is this set up even possible?
From the documentation
Note that you should probably provide the library with a place to store the credentials it has retrieved for the user. These need to be stored in a place where the user themselves or an attacker can not get to them. To provide this, give an object that has setitem and getitem dict APIs implemented as second argument to the init() call. Without this, the library will only work on a single thread, and only retain sessions until the server is restarted.
It is referring to credentials_store option in OpenIDConnect instantiation. To support persisted login via multiple application instances, you will need a persisted shared datastore for this use case. You could use a share redis or dynamodb instance.
Implementation of this credentials_store is fairly simple, you can try something like,
class RedisOpenIdCredStore:
def __init__(self):
# Handle Redis instance initialisation here
pass
def __setitem__(self, key, value):
# Set item to redis
pass
def __getitem__(self, key):
# Fetch and return item from redis if present
pass
credential_store = RedisOpenIdCredStore()
oid_connect = OpenIDConnect(app, credential_store=credential_store, ...)

session is not working with https

This is the first time i am doing the deployment from my side and am new to AWS. I have a project deployed on Amazon AWS server for testing purpose. I have set the domain name as: https://domain.biz
I have a login page here where once the user logs in successfully i am setting the userId in the session and navigating the user to dashboard.
In the dashboard i have added a function to check whether session set with value of userId. If the session is not set then i am navigating user back to login page. This is to block the unauthorized access to site.
I am facing problem here. when i was working with the server before adding ssl it is working fine.after https://domain.biz session is working one page.and http://domain.biz works fine. When i have added domain to https then the session is not working. What is the problem here with AWS? Am i missing anything.
Check this : Session lost when switching from HTTP to HTTPS in PHP
Since codeignitor is in php, I suppose this thread could solve your issue.

How to add my Django application in Facebook?

I'm developing a Django application. I need to authenticate users using Facebook and get the user's friends list to invite them to my site. To do this my application has to be registered with Facebook to get the API key. In the process of doing so I'm struck with the list of settings.
"http://localhost/login" --> this is the login page in my application where I have the Facebook-connect button
I need Facebook to redirect the response to "http://localhost/result", where I have a view to parse the result.
Please let me know how to configure Facebook.
Facebook can't redirect the response to 'localhost', as that's obviously local to your machine, hence the name. Your app needs to be somewhere Facebook's servers can actually see it - ie on a public host somewhere.
In other words, you can't develop and test a Facebook app completely on your local machine, as you would with a normal Django app. You'll need to upload it to your host at regular intervals to see any changes.
Alternately, you can set up port forwarding on your firewall/router to allow Facebook to retrieve directly from your localhost. The instructions for doing this vary greatly between different firewall/router manufacturers. What you need to do is open external port 80 and forward it to port 80 (or whatever port you have your HTTP server listening on) on the host machine where your app is, find your public IP address, and then use them as your callback address as follows:
http://<your.ip.here>:80/login
This will allow you to test your FB or FB-Connect app on localhost.