What are best practices for sub-domain-based accounts in Django? - django

The use case is pretty straight forward SaaS:
each account gets a sub-domain
each account has multiple users, with multiple roles
Most of my searches turn up apps/packages from 2007-2009, and I am not sure that what I find is still relevant.

For me this simple snippet is enought to get account name from subdomain: http://djangosnippets.org/snippets/1119/, there is also a newer middleware: https://github.com/tkaemming/django-subdomains. In django database you could use this domain name as a prefix for username and keep all of them in django standard auth_user table (just add/cut this prefix during authentication or when you want to dispaly this name).
What problems do you have with these snippets?
The only problem from my point of view is automatic setup of subdomains, but it depends on your hosting, does it has these API or not.

Related

Is there a way to know if an user owns a domain?

I'm developing a webapp(Django) that let users have an eshop just with a few clicks. I serve the shops under https://shopname.mydomain.es but then I give them the option to use a domain if they want.
For example one of my users (user1) buys "happyuser.com" in a domain provider of his choice. Then I tell them to modify their DNS to point to my server. So far so good, everything works perfectly, I use Nginx to allow access from the connected domains and everything works correctly.
Here comes my doubt. I use a middleware to detect the host, in this case "happyuser.com", I check a table in which I have the relation between user and domain name.
class UserDomain(models.Model):
user = ForeingKey(...)
domain = UrlField(...)
Then I tell Django to serve the correct shop. But what happens if another user (user2) also saves the domain "happyuser.com", how can I know which user shop should I load?. I know is unlikely that this happens, but is there a way to prevent this problem?
You need some form of activation process for the domain before you officially associate it with that user account. For example:
Ask the user to store a particular value (generated randomly for that user) in a DNS TXT record, or set a particular random CNAME subdomain (e.g. ijiqjwv87123rbbv8123.happyuser.com) to point to your domain. Then query that DNS record and see if it's as expected.
Ask the user to set up the DNS records as necessary to point to your server, then make an HTTP request to that custom domain and a specific path (e.g. happyuser.com/check) and expect to receive some specific token from your own server.
Both ways prove that the user has deliberately configured the domain, over which they apparently have control, according to instructions you gave only to them, proving that they must be the owner of the domain for all intents and purposes.
I think you're right, it's a very unlikely issue. There is not much point spending a lot of time on it. Ensure that table with customer domains have unique index on that column, stops the issue form happening and takes few moments to implement.

Multi-tenant Centralized Authentication Server

I am trying to create a centralized authentication server for multiple Django apps (APIs). I've seen posts/recommendations but none fit exactly what I am looking for.
Overview:
Users can be associated to one or multiple projects
Users have same credentials to all projects they are associated to
Use JSON Web Tokens - use payload to add user data, sub-domain (project) to route to, role, etc
Sub-domain will not be used for login. All users will login to same site and will be routed to project they are associated to (or given list if there are multiple). SSO is optional.
Questions/uncertainties:
Q: Should the authentication tokens be created on the authentication server or on each project? ie) Each user having one auth token for all projects or have one auth token for each project?
Q: Roles will be stored in each app. I would like to send the roles along with the authentication token in the JWT. Should this data be redundantly stored on the authentication server? Another other way would be for the authentication server to access the project databases. What is the best way to handle this? Users will have different roles for each project.
Q: Auth server will have basic user information (email/username, password, first/last name, etc). Since foreign keys can't be used between databases I can use a user proxy based on usernames to create the user on each project. Do the app servers need to have access to which authentication tokens are valid?
Taking advantage of pre-existing software:
Another approach I had in mind was to use django-tenant-schemas which takes advantage of Postgres schemas where each one of my projects would be a schema (currently using MYSQL databases). Does it make sense to take advantage of this?
Can I take advantage of an IdP service to offload some of the authentication? Does this easily tie into the Django auth layer?
Your question seems to be multiple so I would split the answer too:
ABOUT THE USERS
Since your users are not part of your "mutitencancy model" you have two options here:
Replicate your user data among the different tenant databases (via triggers and what not).
Write your own authentication middleware that verifies users in the right database (lets call it root database since now on). You can use user ids to from the root database and verify manually that they match, which is a bad idea.
That means your database schema will be something like this:
root database (all common data here)
project 1 database (with it's own user data or referencing root)
project 2 database (with it's own user data or referencing root)
Now for authentication tokens
You have the same options as above:
Keep them in the root database and write your own middleware.
Replicate them.
How to implement the whole thing
Since your use case is pretty particular, you may encounter some resistance from existing software. But creating your own multitenant solution is not that hard

Multi authentication in laravel5.5 with role specific users

How to implement multiple authentication with one model named User? There are different roles attached to this model. I need to implement multiple authentication as user and administrator.
Better not to call it “multi authentication”. Multi authentication is a completely different conecpt. Basically you will have to have 2 guards setup.
But if you are using one single guard (user guard in this case) you will have to simply assign roles by creating a new column in users model called “roles” or what ever you prefer.
After you have setup the roles colum in your users model, create a middleware and configure the rest. Explanation:
In your “role” middleware or whatever you prefer, specify what roles are which and who has access to where. And include that middleware inside your controller in use.
If you stil want to have a multi authentication like one login and redirect separately for users and administrators, I’d suggest you to look at “the dev marketer” multi auth tutorial. It is a well explained and all the source code can be found in whole on github.
Keep in mind that the laravels default /login route is meant for normal user login (atleast for me). You can create a /admin/login route with the above mentioned tutorial.
Hope this helps. Good luck :)

Django Open ID - Assign permissions to users who have never logged in by email

I'm using django-auth with the django-auth-openid extension to use OpenID (specifically, Google) to log users into my site. I have a user base of about 90 who will be using the site. All of them have Google accounts, and will be using them to access the site. Since the user base is set (there is no registration allowed, only admins can add users), I already have an exhaustive list of all of my users, including their email addresses and other information. How can I allow these users to login with their Gmail addresses without making them register first? Essentially, I'd like to make django-auth-openid match OpenID Gmail addresses to rows in the existing django-auth Users table. Is this possible?
Thanks!
I ended up using the python-social-auth library (which has Django support built in). The documentation for use with Django isn't great, but between the docs and the provided example it was relatively easy to integrate it with my existing django-auth setup. After that, I just deleted the 'create_user' pipeline from the SOCIAL_AUTH_PIPELINE tuple in my settings, and, that way, only users with existing OpenID connections were allowed in (no new registrations occurred from OpenID logins). This meant, though, that I had to create those connections (between OpenID identifiers and Users) manually, but that was pretty easy to do just using the Django Python shell.

How do I allow users to map their domains to a url on my site?

How do I allow users to map their domains to a url on my site? (like how tumblr or blogger does)
The app is being developed in Django. I want the users to be able to map their domains to mydomain.com/username (is this possible or do I need to have a format like username.mydomain.com?)
Also my app runs on a VPS so I have my nameservers as ns1.mydomain.com and ns2.mydomain.com.
easiest way is through domain cloaking. most domain name providers will allow users this option.
another easy idea is to provide your users with a very generic html page that just includes their url on your site in an iframe and have them places that as their default directory index (e.g. index.html).
both the aforementioned would always show the base domain (without trickery). as noted below, a CNAME DNS record would take care of this, assuming they have the ability to edit DNS records...
www.someuserdomain.com. CNAME username.yoursite.com
In that case, you will have to consult your specific hosting setup for how to programmatically change your DNS settings. Whether you can actually do this depends on the host. If your server is running a DNS server that you have access to, you can probably change it that way.