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.
Related
OAuth 2.0 protocol provides permissions delegation of a user so that third-party apps can operate on its behalf. A typical way this is done on the OAuth flow is requesting a user consent to either approve or deny access for the app (Okta example). Here is an official spec describing how it works in general concepts.
I'm looking for the standardized approach to perform the same flow but for the user groups (e.g. organizations). GitHub does that in some way for organizations, so it looks like organizations represent just a group of user accounts. Are there any standardized approaches to this problem?
If not maybe there are any recommended ways how its typically done architecturally or can fit into OAuth 2.0/OpenID Connect protocols.
The OAuth 2.0/OpenID Connect protocols do not cover how access control is performed.
You can, within the OAuth 2.0/OpenID Connect protocols, pass OAuth Scopes or use the OIDC user info endpoint data to allow the resource server to make determination for Access Control.
Many of the commercial products within this area allow the use of LDAP as a back-end for authentication and will even convert LDAP Groups to Scopes.
I would assume, but I do not know, that GtHub stores data with a link (like a group) for the on Organization and/or the user. I know GitHub exposes this using OAuth Scopes.
Oh, and the OAuth Spec is at: https://oauth.net/2/
But if you require Authentication of users then you need to be using OpenID Connect which is built on-top of OAuth 2.0.
Remember that "OAuth 2.0 is NOT an Authentication protocol"
-jim
There are limits to what you can show on the consent screen and dynamically calculated data is not usually supported.
You ought to be able to express a high level scope that you can present to the user though.
In terms of authorizing based on a user's organisations the claims caching technique here can be useful:
https://authguidance.com/2017/10/03/api-tokens-claims/
That is:
* Use OAuth for user identification and high level checks
" Then do the real Authorization based on your back end data
I'm making some assumptions here, but I believe the issue arises from trying to authenticate two things at once.
If the organization is what you need, then go ahead and create a flow to authenticate the organization as the principal subject (via a user who has access to it), instead of actually authenticating the user itself.
Once the access token is generated, you do not necessarily need to know which user generated it anymore (or at least, the token itself does not need to know). If your user needs to be able to view and/or revoke access tokens, they should still be able to do that, since they have access to the organization in your app.
Our business use case is that we have four to five services deployed as java spring web applications. These services have user/customers derived from either registration process or some existing running applications exposed as rest services. We intend to make a single portal which provides users to be able to use a single account / credential to log into many services directly.
With internal approach we assume having individual customer table for each services. And a common Login table for all services whose id is tagged/mapped as foreign key in individual customer table of each services.
Also some services can be accessed without registration , in that case we fetch the data via customers account id from some third rest service and store it in individual services/application customer table and in common Login Table if not already present.
For services which require registration we store the customer credentials in login table if not present; and also in service/applications customer table with a common login table mapping.
But we need a secure portal with session tracking , session timeout just like Single Sign On
With some research we have narrowed the approach to implement the above scenario with either SSO or Oauth2 which her is applicable.
Refer the link (https://stormpath.com/blog/oauth-is-not-sso ) for more insight.
Can someone suggest which approach SSO or Oauth2 is applicable for our business usecase ?
if SSO , which is the best opensource simple SSO for java Spring applications?
if OAuth2 , what will act as Client application, Authorization Server , Resource Owner and Resource Server? As we have services(Java applications) as client application hosted in Common Application/Portal? will the common login table act as resource owner ?
You will likely want SpingSAML. If the applications are hosted on separate paths, like example.org/app1 and example.org/app2 then you could use a Shibboleth Service Provider as the SAML SP for the applications.
You'll still need an Identity Provider of some sort, which SpingSAML can't do, but there are innumerable IdP implementations out there: i.e. Shibboleth Identity Provider, ADFS, or a commercial IdP like Okta, OneLogin, Ping, etc.
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 wrote an API in rails which is of micro services architecture.
In my API i need to implement Role authorization to authorize each and every user using their roles.
Is there any gem that fits into micro services architecture or should I write my own logic to authorize users.
i was using gem authorization gem but it does provide much capability that fits into micro services architecture.(rolify)
Is there any other that suits micro services architecture?
Thanks in Advance.
Whenever you have to implement MicroServices in Rails, then I prefer to put your authentication and authorization (role based permissions) using JWT (JSON Web Token). Because in MicroServices, there are multiple different projects which are deployed on different servers and communicating with each other through APIs and you require only one API Gateway, where user provides the login credentials and its should work for all different projects. I wont prefer devise because it creates a session after successful login which is Stateful, while JWT is Stateless.
Statelessness means that every HTTP request happens in complete isolation. When the client makes an HTTP request, it includes all information necessary for the server to fulfill that request. The server never relies on information from previous requests. If that information was important, the client would have sent it again in this request.
In case of JWT, each request comes with a token something like "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NjUwOTYxMzMsInN1YiI6MX0.e9yeOf_Ik8UBE2dKlNpMu2s6AzxvzcGxw2mVj9vUjYI" which will contain all required info in its payload for login. Please refer https://restfulapi.net/statelessness.
The token should also include the role or permissions (e.g. admin role) of user and based on role it should fetch the data and its relatively faster than Stateful requests. Because in case of Stateful requests (as happens in traditional Web Apps), it stores the session_id in cookies and sends the session_id with request. So on server side, first it fetches its user info and check whether its valid user, then fetch its role and then after successful authentication and authorization, it fetches requested data. While in case of JWT, since the role and username comes within token itself which would be decoded on server side, and directly fetches the requested data from DB. JWT (or Statelessness) helps in scaling the APIs to millions of concurrent users by deploying it to multiple servers. Any server can handle any request because there is no session related dependency.
Difference between Stateful and Stateless, please refer https://restfulapi.net/statelessness and https://nordicapis.com/defining-stateful-vs-stateless-web-services.
For more info about the implementation, please refer http://pacuna.io/2016/06/03/rails-and-jwt and https://github.com/nsarno/knock.
The devise gem is the leader in the industry. All of its methods are fully customizable - they can be used as a before_action (typical usage but not ideal for micro services) and can also be used as just another method in your code (inside a block, in a 'if' statement, etc). Checkout the github page here
https://github.com/plataformatec/devise
It has so much functionality, I could teach en entire course on this gem. There's a lot to learn if you aren't familiar yet.
Thanks for the Answers guys,
Coming to the answer,i have implemented my own way of authorization.
I had come up with a design where User -> Roles -> Resources -> Permissions
Here the resources are individual parts where every user has some permissions upon using a resource and role has set of defined set of resources with some permissions like
read_only,read_create,read_update etc
Each user can have any number of roles, thus user having a permission to access a specific resource.And i perform this check for each action using
before_action
Thanks,
Suresh
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