Assume my company is offering 2 applications, say Mail and Calendar.
Both applications are using OAuth 2 to secure access.
Now Calendar wants to access data from Mail. If those were applications from two different vendors it would be natural for Calendar to ask the user to authorize it's access to Mail etc.
But since the applications come from the same source I'd like them to be able to share data without the user having to explicitly give permissions.
Or to put it differently: I have ID/Access/Refresh tokens for Calendar. How can I exchange them for an Access Token for Mail without bothering the user?
How can this be done in OAuth 2? I control both the applications and the Identity Provider.
The only solution that comes to my mind is for both Mail and Calendar to be the same Application, but that doesn't seem right (and has other issues, e.g. if you want to restrict someone's access to one of them). I could also implement special access outside of OAuth 2 but that is even worse.
A real world example would be Gmail and Google Calendar. They both present OAuth 2 interface to the outside world, but you don't have to allow them to talk to each other.
PS. References to white papers or cases studies would be appreciated
SEPARATED CLIENTS
By default in OAuth you would register multiple clients which get their own tokens. You would then use Single Sign On when navigating between them the first time:
Client ID: app1
Scope: openid scope1
Redirect URI: https://app1.mycompany.com
Client ID: app2
Scope: openid scope2
Redirect URI: https://app2.mycompany.com
If user consent is involved the user has more choice this way of how they grant access to their personal assets.
COMBINED CLIENT
You could potentially combine these into a single entry like this. Note that there is usually a hosting prerequisite of a single base domain in order for token / cookie storage to work:
Client ID: combinedapp
Scope: openid scope1 scope2
Redirect URIs: [https://app1.mycompany.com https://app2.mycompany.com]
PROS AND CONS
The first option is cleanest most of the time, since you avoid tokens with access to too much data. The second option can make sense for related micro-UIs that are really a single app with the same permissions.
APIs AND SCOPES
To share data across apps, companies build API endpoints. You can then have multiple apps that each use scopes representing multiple business areas. See the Scope Best Practices article as a starting point for designing authorization. Eg user logs into calendar app with scopes openid calendar mail - and therefore can get mail data also.
Related
I'm trying to better understand how to make use of OIDC/OAuth in securing a restful API, but I keep getting lost in terminology. Also when I research this question most of the answers are for Single Page Apps, so for purposes of this question assume the API will not be used for an SPA.
Assumptions:
Customers will access a restful API to interact with <Service>.
It is expected that customers will create automated scripts, or custom application in their own system to call the API.
Once setup it is not expected that there will be a real person who can provide credentials every time the API is called.
<Service> uses a 3rd party IDP to store and manage users.
3rd part IDP implements OIDC/Oauth and that is how it should be integrated into <Service>
Questions:
What OIDC/OAuth flow should be used in this situation?
What credentials should be provided to the customer? client-id/client-secret or something else?
What tokens can/should be used to communicate information about the "user"? E.g. Who they are/what they can do.
How should those tokens be validated?
Can you point me to any good diagrams/resources that explain this specific use case?
Am I missing anything important in the workflow?
It sounds like these are the requirements, if I am not misunderstanding you. The solution contains not just your own code and is more of a data modelling question than an OAuth one.
R1: Your company provides an API to business partners
R2. Business partners call it from their own applications, which they can develop however they see fit
R3. User authentication will be managed by each business partner, resulting in a unique ID per user
R4. You need to map these user IDs to users + resources in your own system
OAUTH
Partner applications should use the client credentials flow to get an access token to call the API. Each business partner would use a different credential for their set of users.
Using your own IDP to store users does not seem to make sense, since you do not seem to have an authentication relationship with the actual end users.
Access tokens issued to business partners would not be user specific by default. It is possible that a custom claim to identify the user could be included in access tokens - this would have to be developed in a custom manner such as via a custom header, since it is not part of the client credentials flow.
Access tokens would be verified in a standard OAuth manner to identify the partner - and possibly the end user.
DATA
Model users in your own system to have these fields, then store resources (such as orders) mapped against the User ID:
User ID (your generated value)
Partner ID (company the user is from)
External User ID (an ID that is easy for partners to supply)
Typically each partner would also have an entry in one of your database tables that includes a Client ID, name etc.
If you can't include a custom User ID claim in access tokens, partners have to tell you what user they are operating on when they call the API, supplying the external user ID:
POST /users/2569/orders
Your API authorization needs to ensure that calls from Partner A cannot access any resources from Partner B. In the above data you have all the fields you need to enable this.
SUMMARY
So it feels like you need to define the interface for your own APIs, based on how they will be called from the back end of partner apps. Hopefully the above hints help with this.
I work for a company where we give customer (hundreds/thousands of users) access to 2 sites. One owned by a 3rd party SaaS and one owned by us.
Customers spend alot of time registering for both sites and we also spend alot of time removing accounts when customers no longer need access.
I would like users to register for Site A. After successful authentication; a user can click on a link within the site to access Site B but without the user entering credentials.
I want Site A identity to be used to access site B and its resources. I do not need site B resources to be presented on Site A site, but simply allow users to access site B if already authenticated to site A.
Users may have different roles on site B.
What is my best option? Oauth2 sounds like a good option. But will it satisfy my requirement above?
Who will manage the authorisation server? I presume Site B?
Thank you.
Two main options:
OLD TECH WITH COOKIES
Perhaps the cheapest option is to use hosting domains and have 2 apps like this:
mail.google.com
drive.google.com
Use a cookie issued to the parent domain, google.com
Cookie identifies user, to provide a user id
Rights are looked up in each app from the user id
OAUTH2 AND OPENID CONNECT
This is the option for modern apps and they are usually used together, due to being web, mobile and API friendly.
It is a big job though, including user migration, and usually involves giving users a new password. So it needs to be something your company are prepared to invest in.
The Authorization Server (AS) becomes a shared central resource and it is common to use a Cloud Provider to ensure high availability.
RELATED RESOURCES OF MINE
Initial Code Sample with Cloud AS
User Migration Blog Post
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.
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 have a DashboardApi and an EnterpriseApi on my system. May be one more later.
I am new at IdentityServer3 and I wonder solve my problem.
IdentityServer saves client applications that will use an api. So I have 2 or 3 api. Will I create IdentityServer for all api? Because DashboardApi will consume EnterpriseApi. EnterpriseApi will consume another api.
And users will login to Dashboard application. I could not imagine the organisation.
To answer the question: you may have one instance of IdentityServer being your identity provider/authority across different "resource" APIs as long as they all point back to that same authority when it comes to token validation.
Then an access token used for "DashboardApi" can be used by "EnterpriseApi". It is important to proxy the token properly and in my experience it would be advantageous to create different scopes for each API to have better access as to which calls may be used to proxy into the second API through the first (especially if user consent is a concern).