I recently learned how OIDC provides user identity on top of OAuth 2, and also managed to create an OIDC login to my webapp. However, when it comes to the authorization part, it is unclear how the application should know what scopes to request for the API?
For example, certain endpoints should be protected with the 'admin' scope, as well as respective UI elements should be hidden from non-admin users. The enforcement part I can implement easily, but when the user logs in, the app needs to know if the user is an admin or not - i.e whether or not to request the 'admin' scope / show the admin-related UI parts.
Is there any standard way of representing app-specific details in the user profile that comes from the IDP? What disturbs me most is that such information - to my knowledge - cannot be added to user profiles that come from e.g Google/Twitter/Facebook, so one needs either a) an extra layer (IdentityServer/OpenAM/etc), or b) extra user profile data in the webapp's DB.
My first thought was to add custom claims by doing a) - but when it comes to integrating with existing IDPs, it might not be possible to adjust all the user profiles (e.g large corporate databases), so I am assuming the app itself should be flexible enough to translate existing user profile data to 'admin/not-admin'.
Is there a better solution?
In my opinion it's not a good practice to base your authorization on the claims returned by your identity providers.
This responsibility should be delegated to the UMA server. It's up to him to decide or not to grant a request access to a protected resource.
For example, image that we have the following scenario :
Context : An e-commerce enterprise has internally developed a tool used by his marketing team, to retrieve information about his most loyal clients.
The application has been developed in WPF and interact with a RESTFUL API to retrieve the clients.
Only this application and users that belong to the marketing group are authorized to retrieve the list.
Problem : How the application can access to the protected operation ?
workflow
Solution : the workflow is made of three big steps :
Identity token : retrieve an identity token with implicit grant-type. The token is returned to the client in a callback parameter
RPT token : the identity and access token (valid for the scopes uma_authorization & uma_protection) are passed in the request to retrieve the RPT one.
When it is received by the WPF application, the token is passed in the Authorization header to retrieve the loyal clients. Both parameters are required by the authorization policy.
Check RPT token : the token is checked against the introspection endpoint, this endpoint is offered by the UMA server.
As you can see internal policies are used by the UMA server to grant / or not access to the resource.
Authorization policy is out of scope of the UMA specification, you have to define it yourself :'(.
I have developed a product (open-source) to easily manage authorization policies. If you are interested you can test the demo here :
http://lokit.westus.cloudapp.azure.com/Demo
Note : If you are not satisfied about claims returned by external identity providers, you can always enrich them (read the use case : "assign role to resource owner" in the documentation)
Related
There are established and popular protocols for identity providers to provide a client with properties about the logged in user.
For example in OpenID Connect (OIDC) the client can request access to certain scopes and then read claims about the authenticated user. The use case is the usage of centrally maintained user data, like name, department, e-mail etc.
I'm looking for way for the client to write custom properties about the authenticated user back into the identity provider.
Use cases:
a client application needs to save some app-specific preferences about the user and
a client application enables to user to edit some existing properties that are relevant for other client applications, too
(Yes, it would be trivial to design my own REST-like endpoint for this, but I'm looking for an open standard, in order to make it easier for clients.)
Have a look at System for Cross-domain Identity Management, aka SCIM. This is an out-of-the-box Rest API that an IDP should provide, and which should also enable you to save custom attributes against users.
Typically it is called by back end components, which use the client credentials grant to get a separate token with which to call the SCIM endpoint.
With OAuth we configure an "Authorization Server" (STS) with one or more "clients" (i.e. SPA web app). Those clients are configured to allow access to one or more "resources" (i.e. API). When a client initiates an OAuth flow (i.e. Authorization Code + PKCE) a "resource owner" (user) is authenticated and at the end of the "flow" an "Access Token" (and maybe a refresh token) is provided to the client which can now be used to access resources (API).
Lets assume that the Access Token is a JWT with claims and that the client now has the ability to read those claims.
UI and component visibility is something that I'm not sure I have done correct in the past:
As the access token's intent is really to drive API access is it wrong to also use it to drive UI component visibility (i.e. determine if we should show a menu item or enable an edit button based on JWT claims in the access token)?
A concern here is we could start adding claims that are really just for the UI / web app out of connivence and have nothing to do with a resource.
Note: it should be obvious that "hiding" a menu item in a web app does
nothing to actually protect a resource so this is more about user
experience
Or - should we be using the OIDC User Info endpoint and have it configured to provide enough information to drive the UI experience?
Or - should we have an API endpoint that will return a payload that describes UI component visibility for the current user?
Or is there another recommended approach that should be used?
As you indicate, it is not recommended for UI clients to use claims in access tokens. They are intended only for use by APIs.
A common pattern is to enforce this by issuing access tokens to clients in a confidential opaque / reference token format, such as a UUID. This can also be a more secure way of dealing with sensitive claims, such as personally identifiable information (name, email etc).
The client also receives an ID token, and personally I prefer to limit ID token claims to protocol claims such as when and how the user authenticated. This ensures that you don't inadvertently reveal PII, eg in logout redirects. A client can get identity fields such as name and email by sending the access token to OAuth user info endpoint.
When fields are more domain specific it can make sense for the client to get its security rules from an API endpoint, that can be tailored to what the client needs. This might include whether orders are editable, which columns the user is allowed to see, and so on. If preferred, the SPA can make a single call to the API, which looks up user info, then returns a transformed result.
Sometimes SPAs use a backend for frontend, in which case the main difference is that the UI receives HTTP-only cookies. In this case the same techniques transfer naturally, where the UI must ask the backend for user info, claims and security rules.
Our team is starting to build out a SMART on FHIR (SoF) application. SoF uses OAuth2 access_tokens to represent authorizations. Our app is using the code grant to get a token (https://oauth2.thephpleague.com/authorization-server/auth-code-grant/).
I'm pretty new to OAuth2 (used to SAML) and have been reading up on the standard. I think we may be conflating what the access_token is intended to represent.
Is the intent in OAuth2 that the access_token represents the permissions the resource owner (end user) has granted to the client (web application) to perform on their behalf?
Or is the intent to rely that the resource owner (end user) is allowed to preform certain operations?
For example say the auth token request has a scope called 'contacts-update'. If we get an access_token back with this scope, does that mean the user has allowed the application to attempt to update contacts (on their behalf) or does it mean that the user has the underlying requirements (they are in the update contacts role) to be able to update contacts?
As you wrote, the OAuth2 access token represents a permission delegation from a resource owner to a client (application), so the client can perform operations on behalf of the resource owner. That's also why there is a consent page - the user agrees on giving the application permissions (scopes) it requested.
Sometimes, people want to use OAuth2 as a central authentication server and a permission configuration for their applications. They want each application to see all permissions the user has configured for it. Then it doesn't make sense for application to ask for specific scopes, but to configure the OAuth2 server to return all relevant for that application (identified by a client_id). But I don't think this is the intended way of usage and the OAuth2 specification doesn't cover this scenario.
OAuth2 can also be used for authentication only, if it supports OpenID Connect extension. Then applications can ask for ID tokens. ID token proves identity of a user and the permissions are handled in each application separately.
I am using Identity Server 4 for authenticate user from a single application page. For the need of the project, I have to use the resource owner password flow.
Identity Server and my application work fine together. Identity Server give an Access Token and I can use this token to access some API that we own.
However, I was asking myself about the Access Token, users and socpes. For now my setup is this one.
I have an API that require the scope API-1.
I have a client (my SPA) where I defined the scope API-1
And I have a user.
In this configuration, it is the client who own the right to access the API, not the user. And I'm wondering how to give this scope to the user and not anymore to the client.
Stupidly, I'm wondering if user can own the scope and not the client. Maybe I've miss or misunderstood something, so please teach me.
In the Resource Owner Password Flow your client will always need to have permission to the scope that your resource is protected by. This does not mean that you cannot protect your API based on claims related to the user however.
If in your API for example you need different permissions based on the user accessing the API look to use the claims information as part of your authorization. In the Resource Owner Password Flow example at http://docs.identityserver.io/en/release/quickstarts/2_resource_owner_passwords.html you will see that it mentions this at the foot of the page, see the two paragraphs as follows:
When you send the token to the identity API endpoint, you will notice one small but important difference compared to the client credentials grant. The access token will now contain a sub claim which uniquely identifies the user. This “sub” claim can be seen by examining the content variable after the call to the API and also will be displayed on the screen by the console application.
The presence (or absence) of the sub claim let’s the API distinguish between calls on behalf of clients and calls on behalf of users.
We are setting up a OAuth 2.0 via PingFederate in our organization. The scenario in question is as follows - We have a website in which the customer would be logging in using user name and password. There are are also links within the site to redirect the customer to a partner site. The partner site would be securely passed some basic information via SSO payload.
The partner site would also need to be able to call back to our Apis (call made in the background) to get additional information about our customer which they will then use to display on their site.
Our Api’s are currently setup to be accessed via access token which the consumers of the Api get by following the Authorization Grant flow.
In the partner redirect scenario we want partner site not go through the Authorization code flow when it makes the Api call because the customer would have already logged into our site to start with using their credentials but instead when we redirect to the partner site provide it securely (SSO payload) the access and refresh token which it can then use to make the Api calls ?.
Is there a grant type that I can invoke telling my authorization provider (PingFederate) that I trust the customer based on the information that he has already provided now give me access token and refresh token and then redirect using that information (None of the grant types that I am aware is able to support it - does Ping OAuth setup support a flow wherein I can say I trust this customer give me access and refresh token )?
It sounds like you'd be combining SAML and OAuth to meet your business need. While it's not defined as a standard grant type, one potential solution is to include an Access Token in the SAML Assertion attribute payload so the partner application can then make calls without going through additional redirects. PingFederate does offer the ability to do this by using OGNL to create an access token in the attribute contract fulfillment. An example of how to do this is in our SDK documentation: https://www.pingidentity.com/content/dam/developer/documentation/pingfederate/server-sdk/9.3/index.html?com/pingidentity/sdk/oauth20/AccessTokenIssuer.html
If you need more guidance on selecting the right OAuth grant type, we have information on our developer portal that covers this. Please refer to: https://www.pingidentity.com/content/developer/en/resources/oauth-2-0-developers-guide.html#get_token