I'm working on an application which clients are organizations; each organization has many employees, the users of the application. Not all the employees are users of the application, so each organization has a manager that sign up the employees that will be users.
One of our clients is asking us to use their LDAP authentication system, so that users don't have to learn a new login and password.
Currently, authentication is done using Devise. I've found an article in their wiki (https://github.com/plataformatec/devise/wiki/How-To:-Authenticate-via-LDAP) that explains how to add a new Warden strategy to deal with LDAP.
I've done a small modification so that if a user is authenticated by LDAP but not registered in the application, it will not create a new account for him, but show an invalid login message: https://gist.github.com/jdanielnd/a0e6a73f3f5f9b3462a6.
However this is the behavior I need: the organization model will have a flag for LDAP authentication and a LdapSettings object with the LDAP settings data.
If the user email belongs to a user in an organization that uses LDAP authentication, it will grap the LDAP settings from that organization and try to authenticate the user.
If the user email doesn't not belong to user in an organization that uses LDAP authentication, it tries to authenticate him against the database as usual.
I don't know much about Devise. Is it possible? Does anyone have any idea how can I achieve this?
Thanks!
Related
We are using auth0 as our B2B user management tool in a multitenancy SaaS application,
for each tenant we have an organization on auth0 and a specific connection(of type auth0)
and we create each user for a specific organization on the organization connection.
right now we are using OAuth, getting our customers organization name from the subdomain of the request (lets say stackoverflow is the organization and the host is company.com -> path would be stackoverflow.company.com)
we are using an authentication service that takes the subdomain, convert it to org_id with auth0 API and redirects to our auth0 /authorize endpoint. Aftherwards we retrieve the access token and if its valid, we "confirm" that the session is okey and keep on working with this session. the access token becomes irrelevant at this point.
Our backend is spring-security based application.
we tried to use the SAML authentication because working with access token on a session-based backend seems a bit wierd but we noticed we cant use org_id there and we must use the “prompt organization” screen of auth0, which is bad for us because we dont want our customers to enter their customer name in a different screen.
so few questions on this topic:
should we do it using SAML?
is there any way to send org_id to auth0 with the SAMLRequest so we wont have to ask our customers to enter their organization name?
are we doing this the right way?
Background Explanation
When it comes to Identity Server 4, I come to a road block when i think about the design of user management in the client applications.
At this point, I have Identity Server setup using ASP Identity User Accounts as its user store.
I've built the UI for adding users to the Identity Server User Store.
I've tested setting up a client which is an MVC application, and I'm at the point where i can successfully authenticate with Identity Server and receive the openid identity token in my client application.
Identity Server is providing my client application with authentication.
Now, i need to concentrate on authorization within my app. This is where i get stuck, I need to create users local to the application, where user privileges within the application are stored.
I will need to link / associate the user in Identity Server to the user in the client application.
One way to do this would be to store the sub in the identity token as a user claim in the client application database (Asp Identity). This way, when a user authenticates i can locate them in the local db, based on the sub in the token.
The sub would have to be the user's unique id in the identity server user store. This way, if the user's email is changed, we can still link the two user accounts.
The user accounts in the client application wouldn't require passwords or email addresses, it would be purely claims and roles that are used for authorization across the application, as well as any other application specific information.
Question
Communication between Identity Server and the client application must need to exist when creating users in the client application?
We need to associate the two accounts?
We need to ensure that the client user account being created also has an Identity Server user account to be successfully authenticated?
When in the process should these tasks be complete? Im looking for some guidance in the flow of the communication between the two applications?
EDIT
Is it feasible that there are no User Accounts in the client application at all?
By this i mean that all user claims for a user are stored in the User store of Identity Server.
When a client authenticates with the IDP it requests only the user claims that are specific to the client application.
Example user claims in the User Store :-
"clientA_role" : "administrator"
"clientB_role" : "user"
When Client Application A authenticates, it requests only the scope clientA_role
This feels bad!
Any suggestions?
If you have many client applications then the way I recommend to do the user management is:
User Management Service:
Create a separate service for users management that identityserver will use as user store and applications will use as user repository when user metadata is needed.
Also why would you do something like:
Example user claims in the User Store :-
"clientA_role" : "administrator"
"clientB_role" : "user"
why not
just "roles": "user"? and in your application you will protect your resources using Authorize[Role] annotation.
do not create different fields for different applications, think of it as general user management service, I am pretty sure that standardizing your identity management will make it easier and will gain you maintainability and flexibility.
IdentityServer service handles identity management:
might be a good idea to keep user store inside the same service providing authorization if you feel that your application does not have such deep users management needs.
again in this case, store standard claims and return the claims you need inside an id_token or access-token.
Update:
For a specific user that have different roles in different applications:
let us say we have the following:
1- User1 has user role in first app and admin role in second app, then
User1.Roles{"FirstAppUser","SecondAppAdmin"}
2- User2 has admin role in both apps, then:
User2.Roles{"FirstAppAdmin","SecondAppAdmin"}
I'm using google OAuth for login to my web application.
I want to assign ADMIN, USER roles. I am using tomcat 8 with Spring Boot. After logging in, I want to redirect users to specific pages based on their roles.
How can I assign roles to the users, I don't see the way to do it ?
So here some hints :
Use a table to hold the urls corresponding to each roles
Use a table to hold the users, with login/password and reference to the correct role for them
Do you OAuth login process, and at the end get the url corresponding to the user login
The oAuth is used for authentication only, in your use case, the JWT will resolve your problem by setting the claims.
I am creating an application where the only way users can create an account and then subsequently login is through OAuth.
I only have one Oauth2 authentication source.
Ideally, the User would press one button on my app, ask for their Oauth credentials, and if they are not a user, begin to create a user profile. If they are a user, log them in.
I think that Devise is an overall superior choice and i personally prefer it for my authentication routines. And it supports oauth2. So i would certainly recommend Devise.
I'd like to allow my users to login to my website using my login system, or FB Connect or Google Login. I wouldn't want to use big libraries (like dotnetOpenAuth) for only those 2 options - So how should I accomplish this?
Additional question - how should I bind the FB/Google user to my inner user system? I'd like to allow to login using both of them (I could for example login using FB and then login with Google, and still be bound to the same user).
I'm using ASP.NET MVC 2
Thanks!
If you don't like to use big libraries like DotnetOpenAuth you will have to manually implement the OpenID protocol. Here are the specifications you will need to conform to.
This being said, I would recommend you using an existing library. DotnetOpenAuth is the reference library for .NET.
Also a small remark: OpenId and OAuth are different standards and are designed to achieve different things: OpenId is for authentication while OAuth is for authorization.
As far as identifying the same user which could log from different OpenID providers is concerned you will need something to identify them. For example with DotnetOpenAuth when creating an authentication request to the OpenID provider you could require the FullName and the Email:
using (var openid = new OpenIdRelyingParty())
{
var request = openid.CreateRequest(Identifier.Parse(openid_identifier));
request.AddExtension(new ClaimsRequest
{
BirthDate = DemandLevel.NoRequest,
Email = DemandLevel.Require,
FullName = DemandLevel.Require
});
}
and use this information to identify the user within your internal database.
So here's the idea:
You create an internal database table which will contain your site users. At the beginning this table is empty.
A user comes to your site and wishes to use it. He is not yet authenticated so you ask him for his credentials. You provide him the ability to choose his OpenId provider and prepare an authentication request and redirect him to his provider for authentication.
The user authenticates with his provider and is redirected back to your site. At this moment you know his claimed identity and you add the user to your users table. Now the user can always come back to your site and login.
You could provide the possibility to your authenticated users to add another OpenId provider (just like StackOverflow does). The important idea is that the user needs to already be authenticated to your site in order to do this. So he could enter his alternative OpenId provider and get redirected to this provider for authentication. Once he authenticates he is redirected back to your site and because he was already authenticated to your site you could add to the users table his alternative OpenId provider.
The controller action which will handle the redirect from the OpenId provider should check whether the user is already authenticated to your site and if not authenticate him using FormsAuthentication.GetAuthCookie and passing the claimed identity. If the claimed identity doesn't exist in your internal users table you need to add it. If the user is already authenticated to your site it means that he is adding an alternative OpenId provider to his profile, so you would update your users table and add the new provider to it.