Possible to make Django app #1 authentication automatically give access to Django app #2?

I have two separate Django apps that have separate users and auth systems.
Possible to make authenticating against one of them to automatically grant access to
the OTHER Django app without a second signing in?

Specifically what is going on is that I have a chat app on one Django app and
I want to make a “chat bridge” of sorts that allows users of the OTHER Django app
to also enter chat.

Sincerely,

Chris

My chat app is on the Django app at bighelp.grandmas4hire.com.

I’m trying to access that chat from another app at grandmas4hire.com.

Apparently I can set SESSION_COOKIE_DOMAIN = “.grandmas4hire.com”
on both apps? Is that the easiest way to do this?

cs

What you’re trying to set up is single sign-on between your two Django apps, and there are a few ways to make that work, depending on how they’re hosted. If both apps are on the same domain (or subdomains), the easiest way is to share the same session backend—like Redis or a shared database—and make sure both apps use the same SECRET_KEY and session cookie name. That way, when someone logs into app #1, they’re already authenticated in app #2.

jonhubby

Thanks. Possible to do it without a shared database? For example,
I added these same three settings in both settings.py’s…

DOMAIN = “grandmas4hire.com
SESSION_COOKIE_DOMAIN = “.grandmas4hire.com”
SESSION_COOKIE_NAME = “crossdomainsessionid”

It still didn’t magically allow me to access bighelp.grandmas4hire.com password
protected pages after logging into grandmas4hire.com.

I’ll look into sharing a database of common users if that is the only way.

cs

Also, if put users in a different database, how does
django.contrib.auth.authenticate and django.contrib.login
know to use the new database?

cs

I suggest looking at this from the perspective of the basic principles involved.

What does it mean to be “authenticated” in the context of a web application?

When you authenticate to a Django site, you get a cookie containing a value for a sessionid.

The session associated with that sessionid will have a User object associated with that session. It’s the AuthenticationMiddleware that associates a User object with the HttpRequest being submitted (request.user).

So, what you need to do from a technical perspective will depend upon your level of integration desired.

In the common / generic case, multiple logins from a single source is handled by one of the “token-passing” or “ticket-passing” protocols such as CAS (which is what we use for an SSO solution), or OAuth.

However, in a situation such as yours, you don’t specifically need as complete or comprehensive solution as one of those. Assuming both projects have access to both project’s cookies, you could create your own middleware that gets the sessionid cookie for the other project, and then issues some type of http request to the other project with that sessionid. (This implies that you’ve also created a special view to use as the authentication endpoint.)

If you don’t want to create or install custom middleware, and you only have one or two views where this is necessary, you could add this test to the view on an as-needed basis.

Or, if both projects can have access to the other project’s database, you don’t need to make it an API call - you could have each project query the other project’s session cache to read the sessionid to find the associated User object.

But, all these “simpler” solutions do depend upon the cookies being visible to both projects. If that’s not the case, then you would need to use (or implement) one of the more sophisticated solutions. (I’ll also point out that having cookies visible to multiple domains always creates the possibility of creating an CSRF vulnerability in your system. Whether that’s a concern is only something you can determine.)

| KenWhitesell
June 27 |

  • | - |

you could add this test to the view on an as-needed basis.

you could have each project query the other project’s session cache to read the sessionid to find the associated User object.

Thanks! I only need to give web app #2 access to one page on web app #1. So for web #1’s view,
are you saying replace @login_required with a different decorator that checks
the database of web app #2 if user has not logged into web app #1?

Where/how check the “session cache” on other database? I see the database
has table called django_session with a column called session_key and session_data.
How do I know which row of that table applies to the current user?

But, all these “simpler” solutions do depend upon the cookies being visible to both projects.

Does that just mean making DOMAIN, SESSION_COOKIE_DOMAIN,
SESSION_COOKIE_NAME and SECRET_KEY the same in settings.py
of both?

cs

Sorry, I’m answering these out-of-order as I’m thinking through this.

The last question needs to be answered first:

Absolutely not. They must not all be the same to avoid confusion between the two systems.

<conjecture>
I think you could get by with setting the SESSION_COOKIE_DOMAIN to be the parent domain, and using different SESSION_COOKIE_NAME settings for the two. (The SECRET_KEY shouldn’t be the same.)
</conjecture>

That’s up to you. You could add the other database as a second database in the project, and query it directly, or you could create some type of API in that other system that accepts a sessionid and returns the user in the session.

The key is the sessionid cookie.

Example: I logged on to a Django site. I now have a cookie containing the following:
sessionid=eoapxm4qcqmf1srt1cgwoamnsnx5ribm

Then:

In [1]: session = Session.objects.get(session_key='eoapxm4qcqmf1srt1cgwoamnsnx5ribm')

In [2]: session.get_decoded()
Out[2]:
{'_auth_user_id': '2',
 '_auth_user_backend': 'django.contrib.auth.backends.ModelBackend',
 '_auth_user_hash': 'd7d4f16bd4aa5c3fce5f22524dd420761a4cd3fc6c1777988de3168fd7d49a7d'}

In [3]: User.objects.get(id=session.get_decoded()['_auth_user_id'])
Out[3]: <User: ken>

If the user isn’t logged in you might not have a sessionid cookie, or it might not have the _auth_user_id key in the session, or it might be assigned to the AnonymousUser object - all being cases where the user is not logged in.

Decorator, function call, inline code - your choice. However you want to do it.