Can I sync oAuth / OpenID user data from a bespoke server - oauth

I am working on a server with a legacy user set and user roles. The server exposes a REST API which use a gross set of roles to authenticate with.
The owners now want to move to a new authentication scheme and OpenID Connect seems like a good fit, due to there being a requirement to identify users. Also the authentication server has to run in a cluster ( there's reasons! )
My question is, is it possible to sync the existing roles on the server to an OpenID container so that any client asking for access to those roles can be authenticated?

Related

Role based authorization in OpenID Connect

Assume that client X uses role based authorization and the client identity is provided by any OpenID Connect provider (e.g. microsoft). User logs in client app and client X wants to authorize user access to e.g. admin page with role. Should client app have some store (e.g. database) where user roles are associated with their subjects received from id_token, or identity provider should do it?
The approach where the client does it seems better to me. If authorization server would handle e.g. 100 clients where any client has it's own roles, I think it's not efficent but some identity providers do it.
So what would be good solution to handle role based authorization using some OpenID Connect server as identity provider?

How to add the notion of "accounts" to Keycloak?

How do I best configure Keycloak so that a user needs to have an account for a client to be able to login into that client?
I have to replace a proprietory SSO-Impl. It deals with users, roles and clients much like Keycloak. However, it also knows about accounts. A user is only allowed to login to a client if he has an account for that client.
In Keycloak, if a user simply exists in a realm he may login to a client of that realm. Nothing else is needed. So no "account" is needed. In the old application, he needs an account as well.
What functionality in Keycloak is best suited to overcome this difference?
I have one idea:
Create a client-role in each client namend "HasAccount" and assign it to users. Then, restrict access if that role is missing.
This is discussed here: "Restrict client access in a single realm with keycloak"
It has at least two drawbacks:
It mixes authentication and authorization in the legacy app. I can understand that. But creating a role was already a workaround. That is why I described my initial problem here.
I have clients in 3+ languages/technologies. Adding functionality there seems like more work than in Keycloak.
Last remark:
Before you ask "This is not single sign on" anymore. It is only for administrative purposes. The admin can allow users to login into a client or not by creating an account or not. The user does not have to login a second time. If he is logged in in App A and has an account for App B, accessing App B works without logging in there.
A user is only allowed to login to a client if he has an account for that client. is really not a task for Identity Provider (IdP). It provides only identity and not authorization.
Of course you can ignore that and implement authorization as well. See: User attribute based web service access control by Keycloak
From the design perspective I would add auth reverse proxy in front of legacy app (but it isn't a best solution for SPA apps). Auth proxy will provide authentication via OIDC protocol and also authorization. Legacy apps may keep own OIDC authentication - it will be seamless auth from the user perspective, because SSO will be used.
Account entity - you can use group entity in the Keycloak instead of original account.

Configuring User Authorization in Client Applications

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"}

OpenId connect (OAuth 2): How does look the flow when Resource Owner is not the end user (SSO)?

I would like to provide some standarized SSO mechanism in my application (some different clients, growing number of services in the backend). I am wondering if OIDC/OAuth 2 is the right tool for it.
In all examples I have seen, end user is the Resource Owner and it grants permissions (or not) to some external apps by redidericting to a page asking for permissions.
My use case is different, I want to use OAuth inside my system (for apis, web pages etc.): resource owner is i.e. some service with database (plus administrator who have access to it), end user tries to get some resources from the system. User cannot grant anything, he can be granted. I think it's the most classic scenario, which can be named Single-Sign-On. Is there any standard flow for this in OAuth 2 (or preferably OpenId Connect)? Is it achievable? Or am I looking at a wrong tool?
OIDC/OAuth can be used for both consumer as well as enterprise scenario's. The consent steps of OAuth are useful in consumer oriented scenario's. When dealing with enterprise scenario's like yours, there's no point in asking consent since it is implicit, at least for the enterprise's apps. That is certainly covered by OAuth/OIDC: the Authorization Server is not required to ask for consent and can (typically) be configured to skip that step for particular Clients. So: using OpenID Connect without consent would be suitable.
For your usecase you can use combination of OpenID Connect and OAuth Client_Creds flow. For example suppose you have a HRMS application which needs to get the employee data to show to the employee from some DB.
Register HRMS with OPenID Provider
Register HRMS as Client to OAuth Server (OpenID Server and OAuth Server can be same)
When User comes to HRMS application:
a. Check for Id_token cookie, if not present then redirect to IDP
b. IDP authenticates and if successful redirects back to SP with ID token
c. If token is valid then SP sets the token as cookie in the browser using another redirect to itself but to the home page
Now All processing will be server side:
a. HRMS app hits the IDP to get the User Data
b. If successful then it hits the OAuth Server to get the access_token
c. if successful then it uses the access_token to talk to DB Service and
get the data
SP=Service Provider, IDP = Identity Provider
Actual flow can be a little different based on security considerations.
Hope this makes it helps.

What OpenID Connect authorization flow should be used to secure Web API resources between an MVC client or its end-users?

What is the correct way to use IdentityServer3 and OpenID Connect (flow and configuration) in order to implement the following:
We have one MVC site Products and one Web API Products.API. We must secure all Web API endpoints:
Some endpoints can and should only be accessible by the MVC application on behalf of an authenticated (logged on) user.
Other endpoints, such as the ones used for account registration, password reset or anonymous operations, need to be authorized to the MVC client site directly, since there is no authenticated user in the picture.
We are currently using the Hybrid Flow, but this was mostly motivated after watching one of Dominick Baier videos. I've looked into https://gist.github.com/jawadatgithub/638c11f08ecc0d76b05c and it seems what we are looking is a combination of Client Credential Flow and Resource Owner Password Credential Flow, but I'm not sure I can even mix two flows as apparently it is not recommendable.
You could split the API into a "service" type API and a "user" API and have separate auth flows but do you really need to have the 2 APIs?
Does the registration code really belong in the API? It sounds like the the MVC app (guessing that it is also your identity provider) should deal with account registration - this is normally a key separation in using Oauth2.0 : the API doesn't concern itself at all with user admin!
If you do refactor the registration functionality to sit with the identity provider / Auth server, then do you still have the need to have 2 auth flows?
If you do, you could use just the password flow and have a fake "admin" user setup in your identity system for the non-user context endpoints. Your MVC app can pass in the credentials for the "admin" user and the API can code for this specific user. It's horrible, I don't recommend it, but I've seen it work!

Resources