Include resource scopes in audience for IdentityServer3? - identityserver3

I'm trying to use the standard AuthenticationBuilder extension method AddJwtBearer on some new ASP.NET Core web apis that still get bearer tokens created by IdentityServer3. I think my best bet for validating the resource access to the api (required scope in id server3) would be to make sure that I can get the scope value added to the audience like it does in identityserver4, or else add some validation for the scope claim in the config for the AddJwtBearer method if that's possible (looked but didn't see anything).
Is there a way in IdentityServer3 to make the audience of an access token an array and get any resource scopes added to it so that the token validation with just authority and audience will work now with idsrv3 tokens and continue to work cleanly when we upgrade to idsrv4?

This is what solved my issue. The tests on the identityserver GitHub site were awesomely helpful.
I needed to set LegacyAudienceValidation to true:
https://github.com/IdentityServer/CrossVersionIntegrationTests/blob/master/src/CoreApiIdSrv3/Startup.cs#L32
And then add explicit scope validation with the new ASP.NET Core policy system:
https://github.com/IdentityServer/CrossVersionIntegrationTests/blob/master/src/CoreApiIdSrv3/Startup.cs#L16
As background, in IS3 they didn't put the api name in the audience, but only in the scopes collection. In IS4 they put the api name in the audience and the api scopes (which may or may not be the same as the api name) in the scopes.

Related

Keycloak as IdP with own implementation of Resource Server

Is there a way of using Keycloak only to Authenticate user, but with own mapping to roles with Spring?
I would like to authenticate API Gateway in keycloak first, but then provide internal JWT Token with authorized roles inside my microservice world.
In this article, I do map Spring authorities from roles that Keycloak sets in JWTs. Is that what you are looking for?
If what you want is having a hand on access token claims, two cases:
the claim is already in the token but with a different value than what you expect (missing roles, outdated email, ...). Then, it is very likely that Keycloak admin API exposes what you need to update users data. Check that a "confidential" client with required roles is declared with client-credentials flow enabled (or declare a new one) and have relevent resource-server call admin API for updates (with WebClient, RestTemplate, #FeignClient or whatever is capable of using client-credentials flow).
the claim does not exist yet. Then, define a new Keycloak "mapper" to add a private claim. Here is a sample. You can have a look at security module to figure out how this new private claim is parsed (by ProxiesClaimSet) into an Authentication custom implementation.
In any case, the authorization-server (Keycloak) is the only place to define claims, issue JWT and sign it. JWT validation by JWT decoder on resource-server involves much more than just checking expiration date: issuer, issued-at, token integrity (server signs the payload with a private key and exposes a public one to ensure the token content was not modified), and more are verified too.
You want to make access control inside resource-servers? Great! Ensure that authorization header with Bearer access-token is forwarded by the gateway from client(s) to resource-server(s) and configure your resource-server(s) as described in the article above.
P.S.
In the article you'll also find a way to test security rules (both unit and integration) with mocked authentication. This is what, in my opnion, makes resource-server(s) a better place to implement access-control: security rules are of primary business importance and fine grained unit-testing is essential.
Other note, if you go for additional private claim(s) with Keycloak mapper(s), pay attention to pom.xml file, java/main/resources and implemented interfaces of ProxiesMapper into proxies-keycloak-mapper module.
Last, you should also follow the first 3 of those tutorials (for real: write the code and run the tests), it will take you less than an hour and will save you many more hours struggling with your resource-server(s) security implementation.

OpenIdConnect: how to add additional claims in the token?

I'm quite new to OpenIdConnect so excuse me if i still miss some basic concept.
I have a SPA-style web application I'm developing for my company (AspNet Core + Aurelia).
I want to use AzureAD via OpenIdConnect for authentication and authorization, everything works very well so far i'm able to obrain a token and sign in.
the problem is that my application needs to provide to the client's browser some app-specific claims like: can read X, can edit Y...
if i add these claims to the JWT token provided by AzureAD obviously it will became invalid, as the signature will not match the content.
if i generate a new token with the new claims, but signed with the app key, obviously it will be a different token valid only in the context of my app (what if I'll later need to access some other resource using the AzureAD token?, is it a good idea to insert the AzureID token as claim of the newly issued token?)
Are there something I'm missing in the OpenConnectId? or is there a way to add claims to a token issued by a 3rd-party provider like AzureAD while keeping the token valid? Maybe a way to ask AzureAd to add claims to the token and re-sign it?
I think a good way to solve this situation may be to obtain an access_token for my own application's api (from my app backend) in exchange of the id_token provided by azure (after its validation)
so the application frontend in the browser will own two tokens and it will be able to use the correct one for each type of request.
there are some standardized flow that are quite similar to this but not exactly the same.
You could try to use a custom claim mapping policy. This is documented here.
This feature is used by tenant admins to customize the claims emitted in tokens for a specific application in their tenant.
As far as I can understand, this is still in preview stage. So it may require some trial and error verification.
Alternatively, you can define some policy in your application itself. Given that you know client IDs from your application (hence you require to use them for OpenID Connect requests), you may create a simple policy to check tokens and perform verifications.

Implicit flow, but requires access to multiple API's

Say I have a website secured with IdenityServer3. It uses the implicit flow so users are asked for their credentials. Now I'm facing a requirement where this application should access multiple (Web)API's on behalf of the user. These API's are secured using roles.
How do I go about this? Do I get one access_token for all by adding "token" to the ResponseType of the OpenIdConnectAuthenticationOptions? Do I have to change the Implicit flow (to Hybrid?) and manually request access_tokens for each individual API and add those to the user's claims, after authentication?
I'm not sure on how to approach this. Any help would be greatly appreciated.
You can keep using Implicit flow and add "token" to reponse_type (so it becomes "id_token token"). That will give you access token as well. Additionally, you can specify any scopes that those APIs might require in order to include claims that might have to be present for API Authorize attribute to allow the call through.
Once you have the response from IdentityServer in your application along with access token, you call the api with that token in the Authorization header.
I was able to resolve my requirement by moving to a Hybrid flow. For the response type I ended up needing "id_token", "token" and "code". I also had to retrieve the user claims manually in a separate request and manually add them to the user's identity, because adding "token" besides the "id_token" would remove all claims from the server response (to keep the token smaller).

Renew access token and protect static files

I have question regarding setup of access token renewal/refresh. Our Setup:
Implicit flow
Angular SPA using bearer token for API
Thin MVC frontend serving cshtml containing SPA
Short access token (10min)
20 min Idsrv cookie sliding (used as activity timeout)
The application has to apply to some strict security rules and intellectual property.
We need to renew the access token before it expires and API returns 401.
I’ve looked at the oidc-client-js to handle that. But that would remove the option of authenticating the static files like we do today, since there would no longer be a cookie for the MVC app.
Is there a way of securing them, or is that just something that we have to accept when building a SPA with OpenID Connect?
If you would like to enforce authorization on static files then this needs to be done by server-side code. Since your client is using an MVC backend, my recommendation would be to use the Hybrid Flow in conjunction with the Katana OpenID Connect middleware. You may then pass on any tokens you would like to use from the server-side code to your SPA via your view (cshtml).
The middleware required is available on NuGet:
install-package Microsoft.Owin.Security.Cookies
install-package Microsoft.Owin.Security.OpenIdConnect
The following snippet allows for configuration in your OWIN pipeline (taken and slightly altered from this tutorial):
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "https://localhost:44319/identity",
ClientId = "mvc",
RedirectUri = "https://localhost:44319/",
ResponseType = "code id_token",
Scope = "openid offline_access",
SignInAsAuthenticationType = "Cookies"
});
Using this flow, you are no longer given tokens immediately but will need to exchange the auth code returned ("code" grant type) for a pair of tokens being the:
access_token (the one you are already receiving in implicit flow)
refresh_token (this can be used at the token endpoint to renew the access_token)
The main things to note about the above configuration are response type and scope.
Response type is no longer just asking for tokens (implicit) but now asks for code.
Scope includes "offline_access" scope which will return the refresh_token.
Like this we have solved both your access token expiry problem and have begun to solve your static asset problem by moving authorization to the back-end. To help you with the next part I would need to know how you are serving your assets as there are different ways depending on whether you are using OWIN to serve or IIS.

IdentityServer 3 + Asp.net Identity: Scopes, Claims and Clients - Clarifications

I'm almost figuring out how the different pieces of an Authentication and Authorization server architecture work. I really think that IdentityServer is a great piece of software.
I'm trying to summarize my discoveries, to settle a base for my questions.
IdentityServer issues tokens using OpenID Connect. Issued tokens are ID Tokens and Access Tokens.
Tokens are requested - as stated by OpenID Connect protocol - to clients by using OAuth 2.0 flows. One flow for each client.
During the flow beginning, client requests a collection of scopes (at least "openid", that's because he has to state that an OpenID Connect flow has been activated)
A client may ask all the scopes that he is authorized to ask. Using the Entity Framework plugin for IdentityServer, this information is contained in the ClientScope table. If the client requests a scope that he isn't authorized to request, the flow is interrupted.
Scopes may "contain" claims. This means that if a scope contains a group of claims, whenever the client is issued a token, this token contains also all the corresponding user's claims. For example: let call "roles" a scope that contains "role" claim. As soon as the client is authorized, the received token will contain all the user's roles (as claims).
Each requested scope, if authorized, is "translated" in a claim with the name "scope". This means that if a client requests, for example, a defined "api" scope, the generated identity will have at least a claim called "scope" with value "api".
If all of what I've written is more and less correct, here are my questions:
how are claims defined on asp.net identity tables (i.e. AspNetUserClaims) connected to the IdentityServer ones. For what I've seen the matching is made on the name. Is this conclusion correct? In other words, if my client has to receive a "role" claims (because he has asked for the "roles" scope), will the "Asp.Net Identity" plugin for IdentityServer just release the "role" claims defined for the authenticated user?
referencing the "EntityFramework" plugin tables, what's the meaning of the "ClientClaims" table? I cannot get how claims can be directly connected to client... What am I missing?
let's suppose that in my resource server I've an action protected with a ResourceAuthorize attribute like this:
[ResourceAuthorize("Read", "Orders")]
In my AuthorizationManager I check for the presence of a claim "order_read" or a claim "api". Those are two different scopes defined in my AuthorizationServer, one just for "order reading" and the last for a complete API access. The first may be asked by third-party clients, while the latter no. Is that a good practice?
I cannot understand what my client should do with the id_token. Should I ignore the problem, as I'm using the js library OIDC Token Manager? Are the security controls performed by this library?
Last question: when my application presents the Access Token, how is the ClaimsIdentity generated? Is right to say that it's generated after validating the token on the Identity Server? Does this means that IdentityServer will get the access token and translate it in a set of claims?
Thanks for your clarifications!
Marco
Yep, you got the gist of it. As for your questions:
how are claims defined on asp.net identity tables
That's up to you. IdentityServer doesn't mandate an identity management library. The IUserService extensibility point is where you bridge that gap. We have a starter version of IUserService, but it's a code-based NuGet so you can change it to really do what you need.
I cannot understand what my client should do with the id_token
It is mainly used to pass back to IdentityServer at signout time (to authenticate the signout request).
when my application presents the Access Token, how is the ClaimsIdentity generated
There is middleware (AccessTokenValidation) to validate the access token. The result is the claims form the token, which are then turned into a ClaimsIdentity and then made available to any processing downstream (such as your Web API code).
what's the meaning of the "ClientClaims" table
The Client configuration has a Claims property if you'd like to issue claims on behalf of the client. Check the docs: https://identityserver.github.io/Documentation/docsv2/configuration/clients.html
let's suppose that in my resource server I've an action protected with a ResourceAuthorize attribute like this
This is unrelated to IdentityServer, and is part of the IdentityModel library. ResourceAuthorize is a framework for using the user, the resource, and the action being performed into account when trying to decide the authorization outcome.