I have an internal web app for employees, which uses the OAuth 2.0 flow for authentication. That allows me to check the email address of the user authenticating, and check that they are in fact an employee.
I would like to be able to assign custom roles to users, for example "Support", and then be able to check during authentication what roles the user have, so my application can perform authorization accordingly. I'd like the roles to be manageable through the G Suite admin dashboard as much as possible.
Can someone point me in the right direction on how to implement this?
Related
I'm looking for guidance as to how I should introduce authentication and authorization into my Rails application. I apologize if this gets long, but I'm trying to provide the context necessary to help me understand what roads I should go down to achieve this.
First off, my technologies:
Rails API BE
React FE
Business Requirements:
Invite only (Invite from root admin user)
Multiple types of users
Root Admin (invite users and assign types)
Users
Attorney, Paralegal, Client (each has different roles / capabilities)
Walkthrough
Root Admin User creates accounts for attorneys and paralegals. These accounts go out via an invitation to join.
Paralegals can create clients. When created, an invite goes out to the client to join the application. Paralegal assigns attorneys to be responsible for the clients.
Different Roles
Clients manage their own data
Paralegals can 'validate' client data
Attorneys can 'Approve' Paralegal changes
Bottom line:
We need each type of user to log into the application
Each user gets a role specific to their capabilities
These capabilities will involve different UI capabilities in React
React will need to know that
The user is authenticated
The user is authorized only for certain actions
These capabilities will involve REST calls to Rails
Rails will need to validate that
The user is authenticated
The user is authorized only for certain actions
I've done this in the past using Devise but am looking to move authentication and authorization to the cloud to allow for future app development ideas. That's where I'm not sure what to do. I've been reading a lot of different possibilities and at this point I'm just not sure which path I should choose. So I'm looking for advice how to pull authn/authz out of Rails and into the cloud.
After all this, I think my question is just -- could someone point me down which road I should go? AWS Cognito? Auth0? Stick with Devise? How does Rails work with cloud auth providers?
Really, just anything helps.
Any advice would be appreciated.
After a lot of reading and trial and error I got my target design working:
IdentityServer4 (standalone with AspNetIdentity) with IdentityUser database
MVC Client (standalone), this is the frontend to the users, no database link at the moment
1-n WebAPIs which serve the functionality to the MVC Client and have their own databases
At the moment I use an already existing IdentityUser database and point the IS4 to this database, added roles and claims manually for testing purpose.
My question is about best practice to register new users.
As the MVC Client is the frontend to the user, a link to the user registration should appear here.
But where is the registration technically done?
Should I do it in the MVC Client (with the default IdentityUser Registration) and point the database to the IS4 database or
should I add a register function in the IS4 app to keep the MVC Client free of any database dependencies and point the MVC Client "register" link to this IS4 register function?
Basically IdentityServer has two responsibilities:
Authenticate the user
Authorize the client
The 'problem' with IdentityServer is that the user is not restricted to one application. While the MVC website may be your front, IdentityServer does not relate users to a particular application. Once authenticated, the user can access all applications that use IdentityServer as an authentication server.
So does it make sense to register the user on the MVC website? Probably not, because the user can access the (future) 'mvc2' website as well.
The creators of IdentityServer acknowledged this, so they created the PolicyServer:
We think that tightly coupling "Identity and Access Management" in a
single solution is the wrong approach. These two concerns should be
clearly separated.
In other words: authentication is part of IdentityServer, authorization (of the user) is not.
Getting back to the question, registration of the user should be managed by IdentityServer. Because that is the only application that has access to the Identity store. Besides, users can also register without being redirected by an application.
The key is how to manage the authorization (of the user). This isn't actually part of IdentityServer. I won't go into detail as this is outside the scope of the question.
But to answer your question, what I would do (including email verification, but without automatic login):
Add registration functionality to the IdentityServer and implement a ReturnUrl (like is already the case for login).
Add a link on your mvc website to the register function on IdentityServer. Let the user register in IdentityServer, send an email verification link which sends the user to the login page (persisting the return url), allowing the user to redirect back to the mvc website once registered and logged in.
How to add authorization to the registered user is a different question.
I would not use "User Management" and "User Registration" interchangeably. There is a lot more to user management than just registration. But to answer your question:
Should I do it in the MVC Client (with the default IdentityUser
Registration) and point the database to the IS4 database or
You could, and there would not be anything terribly wrong with that. This will heavily depend on your business requirements, but most often I have seen "User Registration" built into the identity providers (your IdentityServer4 in this case).
I have a single realm with 3 single-page applications and a shared backend. I want to restrict the access to one of the SPAs so that users without a specific role can't log in.
But once you create a user in the realm, he can log in to every SPA client. I can restrict the endpoints of the backend but I don't want to programmatically reject the user in the specific SPA but automatically on the login page.
I tried to use client roles which don't seem to have an effect in this case. The only solution I have found so far is to create separate realms which I think is conceptually the correct way but unfortunately brings up some practical issues, e.g. the administrators of one realm must be able to manage (CRUD) users of another realm which seems fairly unintuitive.
users without a specific role can't log in - it isn't good requirement. How system will known if user has a specific role without log in (authentication)? Keycloak provides Open ID Connect SSO protocol, which is designated for authentication. After successful OIDC authentication is token generated, which may contains also user role. So only then authorization can be applied. So let's change requirement to: users without a specific role can't access SPA, which better fits into OIDC concept.
The mature OIDC SPA libraries offer authorization guard (name can differs, it is some kind of post login function), where authorization can be implemented. Authorization requires to have a specific role in the token usually, otherwise user is redirected to the custom route, e.g./unauthorized. That's the page, where you can say a reason for denying access. Common use case is also customization of the app based on the user roles. For example users with admin role will see more items in the menu than standard users - that's also kind of authorization. Random example of SPA library with authorization guard (I'm not saying that's a best implementation) - https://github.com/damienbod/angular-auth-oidc-client/issues/441
Keep in mind that SPA is not "secure" - user may tamper code/data in the browser, so in theory user may skip any authorization in the browser. He may get access to SPA, so it's is important to have proper authorization also on the backend (API) side. Attacker may have an access to SPA, but it will be useless if API denies his requests.
BTW: You can find hackish advices on the internet how to add authorization to the Keycloak client with custom scripting (e.g. custom scripted mapper, which will test role presence). That is terrible architecture approach - it is solving authorization in the authentication process. It won't be clear why user can't log in - if it is because credentials are wrong or because something requires some role in the authentication process.
You should indeed not create multiple realms, since that is besides the point of SSO systems. Two approaches are possible in your - presumably - OAuth 2.0 based setup:
restrict access at the so-called Resource Server i.e your backend
use a per-SPA "scope" for each SPA that is sent in the authentication request
The first is architecturally sound but perhaps less preferred in some use cases as you seem to indicate. The second approach is something that OAuth 2.0 scopes were designed for. However, due to the nature of SPAs it is considered less secure since easier to spoof.
I was able to restrict users access to application using following approach:
I've created to clients in my default realm (master) i called my clients test_client1 and test_client2 both of them are OIDC clients with confidential access by secret
I've created a role for each of them, i.e. i have role test_client1_login_role for test_client1 and test_client2_login_role for test_client2.
I've created a two users - user1 and user2 and assign them to client 1 and client2 role. But to restrict access to client1 i have to delete default roles:
That did the trick, when i am logging with user2 i see test_client2 and not test_client1 as available application:
But i did n't delete roles from user1 and therefore i could see both clients when i am log in with user1:
Therefore you should use different clients for your applications, assign to each of a client specific role and remove from users default roles and add one releted to specific application.
I'm new to OAuth2 and trying to figure out what is the best practice for the following scenario:
I'm implementing 'ToDo' web service (CRUD for 'tasks')
I'm using OAuth2 and Google as auth provider to get user details (email, name)
Now I need to implement project-specific roles for users ('admin', 'user')
Speaking in terms of OAuth2 - Google doesn't 'own' my service, so it cannot help me with storing/providing 'ToDo'-specific roles, is it correct?
What is the common/best approach to implement it, do I need to create my own authorization service where I'll need to store relations like userinfo -> project-specific role?
Well, it depends what, exactly, you're looking to do.
If you have users, and those users have specific roles that you have assigned to them already, then you're just using Google's OAuth service as an identity service. You don't need to implement your own authorization service, but you will need to keep track (typically in your own database) a relationship between the userid and the roles for that users.
If the goal is to create a service where the user can delegate specific permissions they have to a third-party service, then you will certainly need to implement your own OAuth server. This will allow the user to limit the scopes that are necessary for the third-party service to do its job.
It is easy for you to setup your own authorization and resource server rather than depending on google services. In your own authentication server you have more control over your roles and users you specify.
You can setup and authentications server using spring boot app and using dependencies like Spring-starter-security, spring-security-oauth2 and etc.
Yes, you'll have to use your own Authorization Server that can then issue tokens that have realm-specific roles associated with them.
I'm working on an MVC4 site using SimpleMembership to handle user accounts and role based authentication. We have another site and we'd like to implement a single sign on system allowing users from the existing site to log in to the one I am building. What would be the best way to achieve this and hopefully leverage to the existing roles based authorization I'm using on the MVC4 site. Is it possible to have multiple membership providers (i.e. use the built in one and if the user is not found, attempt to authenticate via a custom provider that I'll write (once I work out how!). Or would it be better to abandon the built in membership/roles and roll my own?
I also thought of letting WebSecurity check the local database and if the user is not found, query the 2nd database and if the users credentials are valid, create a local account for them. One issue with this approach is if a user called Fred registers on the MVC site, and then a user from the other site called Fred logs in, we couldn't create them a local account with the same username. We could prefix/suffix the username with some text to indicate that they are from the other site but then we lose the single sign on feature.
We will also want to integrate AD authentication for staff in the future.
So essentially I'm looking for the best way to authenticate users from multiple databases and keep using roles based authentication?
I've also done a little digging was wondering if ADFS might be useful for this.
Any help or advice would be greatly appreciated!
I recommend the use of an Identity server to handle all your login request and switching to a claim based authentication instead of a role based authentication if you can.
I personally went with Thinktecture IdentityServer
pluralsight.com have a good course on it.
Thinktecture IdentityServer is build on top of simple Membership and it supports multiple protocol such as
WS-Federation
WS-Trust
OpenID Connect
OAuth2
ADFS Integration
Simple HTTP
I recommend checking it
Good Luck