I have a Laravel user database (> 14k customers) and would like to authenticate and authorize all users accross multiple websites of our company (2-5 Laravel and .NET webs) from a single OAUTH server.
https://laravel.com/docs/9.x/passport seems to document only workflow when "OAUTH clients" are added per user (witch nice and also a requirement), but I want to have global "clients" available for all users. I dont want my users to be able to remove their access to other websites of our company and even more be required to add it one by one in order to use it.
Workflow:
User comes to one of company sites (1.company.com, 2.company.com, 3.company.com...) and is redirected to server oauth.company.com and after successful login redirected to the original target website.
User can add aditional clients, but are not required to add 1.company.com or other sites of our network.
Is that even possible with passport?
Related
In the latest version of our SAAS product, we are designing it to allow our customers to deploy multiple instances of the software.
We require the sign up and login to be tightly integrated into the primary domain - the "sells the product to new customers" website PrimaryDomain.com which features "Sign Up" and "Login" forms that use jQuery/AJAX to give responsive feedback on data submission.
When a customer successfully logs in, they are to be presented with a list of all their installed instances of our product. All installed instances of our product can be hosted across dozens of domains, but to keep this question simple, they are hosted on [subdomain].SecondaryDomain.com (code + database).
Every installed instance also features an admin panel which currently customers need to manually login to each individual instance as required.
We want the customer to be able to click on 'view admin panel' next to any of their installed instances and automatically be logged in on [subdomain].SecondaryDomain since they were logged in on PrimaryDomain.com.
SecondaryDomain.com naturally doesnt have access to the cookies or session variables of PrimaryDomain.com so what is the best way to allow SecondaryDomain.com to authorise?
We have considered a few different options, such as;
Researching some clever way that the domains can share cookie/session data?
Generate a token that is passed with the url when clicking 'view admin panel' to the second domain. The token is unique to the userid plus subdomain (such as an md5 hash) and then validating it on the receiving end.
Recording a one-time-use token into the database and sending with the url and having SecondaryDomain.com connect to PrimaryDomain.com's database to verify the one-time-use token and set appropriate session and cookie variables.
The one-time-use token seems like the right approach, but i havent been able to find any concrete answers on (a) if this is even the RIGHT approach, and (b) what the security implications are around it?
I recommend SAML for this case. SAML requires you to have an identity provider (IdP) and service providers (SP). The user will login to the IdP and present the token to any SP visited. The SPs need to be configured to assert the token against the IdP. You probably want to look into Auth0's SAML SSO offering for more information, but there are other providers out there that do the same thing.
I'm building an SAAS with a single database. Tenant in this case is called site.
I want to achieve what Stackexchange does where it has a global login as well as a stackoverflow/softwareengineering/etc login. I'm not sure how to store users. A user can have many sites and sites can have many users. The problem with designing a JoinTable is that the user roles are stored in the User table (im using Symfony3.4). I want separate roles per site/tenant.
Another problem I'm trying to figure out is how to go about logging in. I'm using oAuth2 and to login in I sinply call {{url}}/oauth/v2/token?grant_type=password&client_id=client_id&client_secret=client_secret&username=admin&password=pass. How should I make the user log in to a specific tenant/site? Do I add site_id to the query parameters?
Thanks for reading.
This question is very broad, so I'll take a stab at it.
If you are building out a network of sites, each site would ideally have it's own database. This will ensure sandboxing and the ability to easily migrate a site to it's own infrastructure if needed due to scaling or security concerns.
When dealing with user authentication, it sounds like you'll want a single secure user store that acts as the oauth2 server and each of the sites act as a Oauth client. You'll want to use the Authorization Code flow grant type in OAuth.
Essentially, a user visits Site A. Site A sees they are not logged in via the site's session. It redirects to your OAuth server which shows a login (think of the google login). Since Site A also passed in a callback url, once you've signed in, the OAuth server knows where to redirect the user, along with the valid token information. Then Site A takes that token and exchanges it for an access token on the server-side so now you've got authentication data on Site A.
If you are going to implement your own OAuth handshaking, you should utilize an existing server/client library. For PHP, you can look at the League OAuth server library, or use Laravel Passport, if you're using Laravel. There are other similar packages for other frameworks out there.
Can the same user have multiple sessions to the same app in the same browser as long as another field is added to the authentication process (email, password and website_id)?
I'm building a PHP app that allows the creation of multiple onepage websites. Each website should serve as standalone sites, with different content but they all have the same backend. Each website has a separate set of users/customers. A user can signup on any website but the websites don't necessarily share a user base. This means that a user can go to site1.domain.com and register, and then would have to register again if they wish to visit site2.domain.com.
They will probably register using the same email address, so my user table allows for duplicate email addresses as long as they're not in the same website.
This is sort of a very simple CMS. Kinda like what magento does with multiple websites running under the same instance. They also allow each separate site to have they're own customer base.
I plan to use Laravel for this project. My current approach is this:
Modify the provided user authentication functionality to add the site_id field. This means the user can register with the same email address in multiple sites, and can also log in to all those sites separetly. If they're logged in to site1 and visit site2, they have to log in again and have two separate sessions for what would appear to them as two different apps, but is just the one.
In theory this seems possible to me. A cookie is created for each separate subdomain once they login, which wouldn't work on a different subdomain. I feel like I'm missing something big though, I've never done something similar to this and always relied on Laravel to handle all the session stuff for me. Is this possible without some heavy hacking to the Laravel codebase?
UPDATE
These are my constraints:
The desired affect is that each website appears to be a separate application alltogether and not related at all to the others but all tied to the same backend and with the same routing/views.
userbase and user session cannot be shared between sites. I can make it so a user registers once and can login to every site, but I don't want that. A user should be able to visit every website separately.
every website will have a different subdomain, or in same cases, a different domain alltogether.
PHP sessions are tied to the domain name, so they will automatically have different sessions for each of your apps. You can use route-model binding with a custom resolution to determine the app based on the domain.
routes.php
Route::group(array('domain' => '{site}.com'), function() {
//routes go here
});
RouteServiceProvider (in boot method)
$router->bind('site', function ($value) {
return App\Site::where('custom_domain', $value)->first();
});
This is based on the assumption that you have a Site model with a field in the database called custom_domain. All of the routes available inside the group will have access to the Site using dependency injection. You can adjust the model and field based on your app needs.
You can use the model to customize the login-page for each app, and the apps will have independent sessions for each one.
I've also heard great things about the Landlord package. You use a middleware to define which Site the user is, based on the url. Once that is set, all eloquent queries will be automatically scoped based on the site_id in the database. So User::all() would only return users for the current site.
In my company we have some technology restrictions. Currently I have a IIS server with PHP. IIS is configured to authenticate users over our Active Directory using NTLM.
I have installed WordPress on this server and am able to login on it using admin user (id=1), and any user is able to read articles and post comments anonymously.
"Thanks" to NTLM, I can retrieve users' login with $_SERVER['REMOTE_USER']. This way I can identify (in a plugin) users. But WP doesn't automatically logs them and identifies them.
What I need now is to control users permissions inside Wordpress. I need to attribute roles to them, define groups of people allowed to publish, post and edit without being allowed to publish, comment and register their login on their comments, and also users that are allowed only to read articles (guests) and users not allowed to read articles. Maybe I'll also need to attribute read access relating roles to categories, so that a given role is allowed to read articles from a category and not from another category.
Users are related to departments and have one charge (job title). Users are frequently moving over departments and changing charge. I need to use both to define some roles. I can develop a plugin to hook on some WP filter, retrieve their data and dynamically set their role.
To retrieve their department, charge and name, I could use LDAP. If not possible, I have a MSSQL database that also has their data. So, if I can't use LDAP, I'd need to make WordPress connect to MSSQL and query it.
It's unpractical to register tens of thousands of users in WordPress, and even more to request them to keep their passwords. I need WordPress to identify users and automatically add new ones to its wp_users table. I also need to be able to manually register a few users without requiring them to first enter the site. I then can manually manage users to WordPress roles.
I see 3 possible solutions here:
1) Use IIS's NTLM to authenticate users, and use $_SERVER['REMOTE_USER'] to retrieve their login and log them into WordPress. If they aren't yet registered on wp_users, that's done so. I then query MSSQL for their data. This seems to be the easiest solution.
2) Use IIS's NTLM to authenticate users, and use $_SERVER['REMOTE_USER'] to retrieve their login. Then retrieve their names from AD using LDAP, and provide these data to authenticate WordPress and handle wp_users. This is the most desired solution, but also the most complex.
3) Ignore NTLM and require users to manually provide their login and password to WordPress's login form, then authenticate them over LDAP and handle wp_users. Provided password is their AD one. HTTPS is already working and being forced inside backend. This is the least desired solution, because users are already used to be authenticated from NTLM and may not want or understand the login form (yes...).
Has anybody done that and could help me? Is there a plugin that solves this need, or some open source code I can use as basis to develop a plugin?
I have about 100 websites coded in ASP classic. Each website accepts orders and stores them in database. However, the payment of these orders must be made on another website, also coded in ASP classic. All websites are owned by same company, hosted on same IIS server and use the same SQL Server database.
Now, the user registers by entering some personal information and logs in to one of these website (e.g. website-for-newjersey.com) and places an order. He is then redirected to the payments website (payments.master-website.com on https) where some of his personal information (address, city, state for shipping; name for credit card holders name; etc) appears on the payment form. Credit card specific information is entered on that page.
Because of the sensitivity of information shown on that page, the user must login to the payment website before he/she can view the pre-filled payment form. And I do not want the user to login twice (once on each website). Is there a reliable way of checking if the user is logged in to the referring website using classic ASP.
Long story short
On website B I need to check if the visitor is logged into website A
On website B I need the ID session variable from website A
Both websites use same database server
I need clear instructions
PHP or ASP.NET solution is acceptable if it is generic/portable
From the calling site you could create a guid or some other randomly generated value. Store it on the users record (set to expire in a specified time period) in the database, encrypt it and pass it over SSL to the payment site where it is decrypted and then compared to the database. If they match then the user is logged in, if it doesn't match then they are asked to log in.
Another way although I'm not sure it can be done with different domain names is using sessions. Since they are all on the same machine it might be possible but I'm not 100% sure on that one.
What you asked is called single sign on (SSO) and can be implemented in few ways. There are many topics on this matter, example: What's your favorite cross domain cookie sharing approach? but they all vary due to individual requirements.
In your case you have different domains (so you cannot share cookies across them), you mix http and https (which might be a problem) and you have many applications so you won't make many changes.
So I would recommend to consider Robert's suggestion:
When user is authenticated for the first time (website A) you save a GUID in the database. Add a new table for sessions with columns for GUID, userid, ip and timestamp or save it as a part of orders data. Store GUID in the session object.
On the page that had a link to the payment site set it in the query string or as a hidden variable (if it's a form).
On the other domain (website B) check for the GUID and then look it up in the database. If it wasn't too old then authenticate the user, otherwise redirect him to a login page.
If you cannot change a link to the payment site then you could try to skip the step 2 and validate the user by his ip but this might be too risky.
Pass-port based authentication is a centralized authentication service provided by Microsoft that offers a single logon and core profile services for member sites. For more information, see the following Microsoft Web site:
Passport Authentication Provider
If you can't implement a Single Sign-On at your infrastructure level, you should use Identity Federation which allows applications of different trusted party to share authentication through claims.
This can be done using Security Assertion Markup Language (SAML) directly or with products/standards like :
SimpleSAMLphp
Active Directory Federation Services
Also you can take a look at OAuth or OpenID which are more shared authentication schemes than SSO or identity federation.