IdentityServer3 Client to client authorization - identityserver3

I am in the process of implementing IdentityServer3 in our company but I have hit a blank around how to handle client to client authorization and would appreciate any pointer in the right direction.
This is a summary of our requirements:
We have multiple web site clients that our users access. These are configured using the AuthorizationCode flow. Lets call these WebSiteClientA, WebSiteClientB.
We have multiple WebAPI clients as back end services that could be accessed by either a client (WebSiteClientA, WebSiteClientB) or a user (who has access to WebSiteClientA or WebSiteClientB). Lets call this WebAPIClientA.
Note: Our company owns the users identity as well as all clients.
Initially I though we could configure WebAPIClientA using the ClientCredentials flow. Then WebSiteClientA \ WebSiteClientB would be configured with the client credentials for WebAPIClientA and could generate an access token when it required access to WebAPIClientA, or alternatively generate an access token with limited scopes and hand this access token to the user so the user can access WebAPIClientA directly from the client side.
This would meet almost all our our requirements except 1 big one, we also want to be able to manage what scopes a client has access to for another client and with the approach of using the ClientCredentials flow anyone with the client credentials would be able to generate access tokens for all scopes under that client. ie WebSiteClientA should be able to generate an access token for WebAPIClientA with read & write scopes but WebSiteClientB should only be able to generate an access token for WebAPIClientA with the read scope.
In my mind the client\identity server conversation would be:
WebSiteClientA makes a request to the identity server for an access token to WebAPIClientA for scope X and provides the client secret for WebSiteClientA. The identity server then says yes, you are WebSiteClientA and we can see from our records you have access to WebAPIClientA with scope X, here is an access token.
Is this possible or am I looking at this in the completely wrong way and there is maybe a better approach to meeting the requirements?

It sounds like you're talking about two things.
The first is that in the APIs you need the user's id. To obtain the user id you have a decision if you want to build a trusted subsystem, or if you don't want a trusted subsystem (in the sense that your APIs trust or don't trust the MVC client to pass along the user's identifier). If you do a trusted subsystem, then the client credentials flow from the MVC client to the API is fine. If you don't want a trusted subsystem, then you need the MVC client to obtain an access token for the user (via implicit or hybrid flow).
The second issue you're asking about is if you can control the scopes each client is allowed to request, and you can via the AllowedScopes configuration property (or whatever it's called) on the client configuration. This setting is orthogonal to the first issue mentioned above.

Related

Migrate from JWT to Identity Server 4 without need to re-login website users after deployment

I have an API service that is currently secured using JWT. I'm going to replace JWT with Identity Server 4 and secure my API with Identity Server 4. I had a custom way of generating JWT tokens (JWE). How can I replace JWT with Identity Server 4 without the current signed-in users to the site need to re-login?
Specifically, I wanna use the Skoruba Identity Server 4 project template.
In IdentityServer, the access tokens are generated to authenticate users. The Access tokens have very small limited lifetime as per convention. There's a concept of refresh token which has longer lifetime and the same is used with basic auth to get new access token. This prevents the hassle to sign in again and again.
The refresh tokens are built using a hash and are persisted in a table (if configured).
JWE is a very different setup altogether. I had my users logged out even after a new deployment of IdentityServer4 (using of persistent grants is helping to solve this).
I don't think it's not technically possible to transfer sessions from one environment to another. Both use a encryption decryption strategies which are very different from each other.
You can give a try by writing a custom implementation of TokenCreationService

Restrict front client connexion with groups / roles in a realm

I'm looking for a way to restrict user access to specific clients in a realm.
I know I can do it with client where Authorization is enabled (fine-grained authorization support) but it doesn't work when trying to connect from front (client need to be public and not confidential).
I'm using a javascript application to login from front-end.
Is there a way to enable Authorization for public client or a work around ?
Thanks.
I'm not sure if this will totally answer your question because it's still not specific enougth but it may give you some further help.
In case you're new to the topic, please see difference between public and confidential clients here.
The current best practice for public clients like HTML/Javascipt applications is to use OpenId Connect with the Authorization Code Flow + PKCE. HTTPS is of course a must have. I recommend you use a javascript openid connect adapter for this like the following for example:
https://github.com/panva/node-openid-client
Basically your authentication / authorization flow is shown here:
When the user wants to login from your frontend client application first a unique verifier is generated which is only available to the exact user / browser session. This value get's hashed as a code challege. Then the user gets redirected to the login page of your authorization server (Keycloak for example) passing some parameters like a redirect uri and the challenge.
With successful login the user get's a session at the keycloak server which also stores the hashed challenge. Then the user gets redirected to given redirect uri (a path in your application) together with a code to obtain an access token. Back in your application you application uses the original value together with the code to get the actual token. The authorization server ckecks the value against the stored challenge and geturns the access token if it matches. You see the extra verifier is to prevent that anybody compromises your code fragment to obtain a token on your behalf.
Now you have an encoded access token in your browser app. Note the token itself is normally only encoded not encrypted but it can be signed. Those signatures can later be used from your backend to ckeck the token integrity but we will come to that soon. Roles, claimes, scopes and so on included in your access token tell you the privileges of the user/identity. You can of course use them to enable/disable functions in your app, block routes etc. but in the end client protection is never really effective so your real authorization ande resource protection happens at your resource server which is your backend (node, .net core, java etc.) maybe a restful Web Api. You pass your access token as a part of the http request header with every request to the backend. Now your backend checks the token integrity (optional) expiration time etc. analyzes scopes, claimes and roles to restrict the resource access.
For example a simple GET myapi/car/{1} may only need a token or can even be annonymous while a POST myapi/cars or PUT myapi/car/{1} may need a special role or higher privileges.
Does that help you out?

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.

How should a Facebook user access token be consumed on the server-side?

Preface
I'm developing several web services and a handful of clients (web app, mobile, etc.) which will interface with said services over HTTP(s). My current work item is to design an authentication and authorization solution for the product. I have decided to leverage external identity providers, such as Facebook, Google, Microsoft, Twitter, and the like for authentication.
I'm trying to solve the problem of, "when a request comes to my server, how do I know who the user is and how can I be sure?". More questions below as well...
Requirements
Rely on external identities to indicate who I'm dealing with ('userId' essentially is all I care about).
The system should use token-based authentication (as opposed to cookies for example or basic auth).
I believe this is the right choice for scaling across multiple clients and servers while providing loose coupling.
Workflow
Based on my reading and understanding of token-based authentication, the following is how I imagine the workflow to be. Let's focus for now on Facebook in a web browser. My assumption is that other external identity providers should have similar capabilities, though I have not confirmed just yet.
Note, as of writing, I'm basing the following off of Facebook login version 2.2
Client: Initiates login to Facebook using the JavaScript SDK
Facebook: User authenticates and approves app permissions (to access user's public profile for example)
Facebook: Sends response to client which contains user’s access token, ID, and signed request
Client: Stores user access token in browser session (handled by SDK conveniently)
Client: Makes a request to my web service for a secure resource by sending along the user’s access token in the authorization header + the user’s ID (in custom header potentially)
Server: Reads user access token from request header and initiates verification by sending a request to the debug_token graph API provided by Facebook
Facebook: Responds back to the server with the user access token info (contains appId and userId)
Server: Completes verification of the token by comparing the appId to what is expected (known to itself) and the userId to what was sent on the client request
Server: Responds to the client with the requested resource (assuming the happy authorization path)
I’m imagining steps 5-9 would be repeated for subsequent requests to the server (while the user’s access token is valid – not expired, revoked from FB side, app permissions changed, etc.)
Here's a diagram to help go along with the steps. Please understand this system is not a single page application (SPA). The web services mentioned are API endpoints serving JSON data back to clients essentially; they are not serving HTML/JS/CSS (with the exception of the web client servers).
Questions
First and foremost, are there any glaring gaps / pit falls with the described approach based on my preface and requirements?
Is performing an outbound request to Facebook for verifying the access token (steps 6-8 above) per client request required / recommended?
I know at the very least, I must verify the access token coming from the client request. However, the recommended approach for subsequent verifications after the first is unknown to me. If there are typical patterns, I’m interested in hearing about them. I understand they may be application dependent based on my requirements; however, I just don’t know what to look for yet. I’ll put in the due diligence once I have a basic idea.
For instance, possible thoughts:
Hash the access token + userId pair after first verification is complete and store it in a distributed cache (accessible by all web servers) with expiry equal to access tokens. Upon subsequent requests from the clients, hash the access token + userId pair and check its existence in the cache. If present, then request is authorized. Otherwise, reach out to Facebook graph API to confirm the access token. I’m assuming this strategy might be feasible if I’m using HTTPS (which I will be). However, how does performance compare?
The accepted answer in this StackOverflow question recommends creating a custom access token after the first verification of the Facebook user token is complete. The custom token would then be sent to the client for subsequent requests. I’m wondering if this is more complex than the above solution, however. This would require implementing my own Identity Provider (something I want to avoid because I want to use external identity providers in the first place…). Is there any merit to this suggestion?
Is the signedRequest field present on the response in step #3 above (mentioned here), equivalent to the signed request parameter here in the ‘games canvas login’ flow?
They seem to be hinted as equivalent since the former links to the latter in the documentation. However, I’m surprised the verification strategy mentioned on the games page isn’t mentioned in the ‘manually building a login flow’ page of the web documentation.
If the answer to #3 is ‘Yes’, can the same identity confirmation strategy of decoding the signature and comparing to what is expected to be used on the server-side?
I’m wondering if this can be leveraged instead of making an outbound call to the debug_token graph API (step #6 above) to confirm the access token as recommended here:
Of course, in order to make the comparison on the server-side, the signed request portion would need to be sent along with the request to the server (step #5 above). In addition to feasibility without sacrificing security, I’m wondering how the performance would compare to making the outbound call.
While I’m at it, in what scenario / for what purpose, would you persist a user's access token to a database for example?
I don’t see a scenario where I would need to do this, however, I may be overlooking something. I’m curious was some common scenarios might be to spark some thoughts.
Thanks!
From what you describe I'd suggest to use a server-side login flow as described in
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2
so that the token is already on your server, and doesn't need to be passed from the client. If you're using non-encrypted connections, this could be a security risk (e.g. for man-in-the-middle attacks).
The steps would be:
(1) Logging people in
You need to specify the permission you want to gather from the users in the scope parameter. The request can be triggered just via a normal link:
GET https://www.facebook.com/dialog/oauth?
client_id={app-id}
&redirect_uri={redirect-uri}
&response_type=code
&scope={permission_list}
See
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#login
(2) Confirm the identitity
GET https://graph.facebook.com/oauth/access_token?
client_id={app-id}
&redirect_uri={redirect-uri}
&client_secret={app-secret}
&code={code-parameter}
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#confirm
(3) Inspect the access token
You can inspect the token as you already said in your question via
GET /debug_token?input_token={token-to-inspect}
&access_token={app-token-or-admin-token}
This should only be done server-side, because otherwise you'd make you app access token visible to end users (not a good idea!).
See
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#checktoken
(4) Extending the access token
Once you got the (short-lived) token, you can do a call to extend the token as described in
https://developers.facebook.com/docs/facebook-login/access-tokens#extending
like the following:
GET /oauth/access_token?grant_type=fb_exchange_token
&client_id={app-id}
&client_secret={app-secret}
&fb_exchange_token={short-lived-token}
(5) Storing of access tokens
Concerning the storing of the tokens on the server, FB suggests to do so:
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.2#token
(6) Handling expired access tokens
As FB doesn't notify you if a token has expired (and if you don't save the expiry date and compare this to the current timestamp before making a call), it's possible that you receive error messages from FB if the token got invalid (after max. 60 days). The error code will be 190:
{
"error": {
"message": "Error validating access token: Session has expired at unix
time SOME_TIME. The current unix time is SOME_TIME.",
"type": "OAuthException",
"code": 190
}
}
See
https://developers.facebook.com/docs/facebook-login/access-tokens#expiredtokens
If the access token becomes invalid, the solution is to have the person log in again, at which point you will be able to make API calls on their behalf once more. The login flow your app uses for new people should determine which method you need to adopt.
I dont' see any glaring gaps / pit falls, but I'm not a security expert.
Once your server has verified the given token (step 8), as you said:
The accepted answer in this StackOverflow question recommends creating a custom access token after the first verification of the Facebook user token is complete. The custom token would then be sent to the client for subsequent requests. I’m wondering if this is more complex than the above solution, however. This would require implementing my own Identity Provider (something I want to avoid because I want to use external identity providers in the first place…). Is there any merit to this suggestion?
IMHO is the way to go. I would use https://jwt.io/ which allows you to encode values (the userId for example) using a secret key.
Then your client attach this token to every request. So you can verify the request without need to a third party (you don't need database queries neither). The nice thing here is there is no need to store the token on your DB.
You can define an expiration date on the token, to force the client authenticate with the third party again when you want.
Let's say you want your server be able to do some action without the client interaction. For example: Open graph stories. In this scenario because you need to publish something in the name of the user you would need the access token stored on your DB.
(I can not help with the 3 and 4 questions, sorry).
Problem with Facebook is that they do not use OpenId connect on top of Oauth (https://blog.runscope.com/posts/understanding-oauth-2-and-openid-connect).
Thus resulting in their custom ways of providing Oauth authentification.
Oauth2 with OpenId connect identity services usually provide issuer endpoint where you can find URL (by appending ".well-known/openid-configuration") for jwk's which can be used to verify that JWT token and its contents were signed by the same identity service. (i.e access token originated from the same service that provided you jwk's)
For example some known openid connect identity providers:
https://accounts.google.com/.well-known/openid-configuration
https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
(btw it is not a coincidence that Attlasian provides only these two services to perform external login)
Now as you mentioned, you need to support multiple oauth providers and since like Facebook not all providers use same configuration of oauth (they use different JWT attribute names, toke verification methods, etc. (Openid connect tries to unify this process)) i would suggest you to use some middleware identity provider like Oauth0 (service not protocol) or Keycloak. These can be used with external identity providers (Social pages as you mentioned) and also provides you with custom user store.
Advantage is that they unify authentication process under one type (e.g both support openid connect). Whereas when using multiple oauth providers with not unified authentication workflow you will end up with redudant implementations and need for merging different information's under one type (this is basically what mentioned middle-ware identity providers solve for you).
So if you will use only Facebook as identity provider in your app then go for it and make implementation directly for Facebook Oauth workflow. But with multiple identity providers (which is almost always case when creating public services) you should stick with mentioned workaround or find another one (or maybe wait till all social services will support Openid connect, which they probably wont).
There may be hope.. This year, Facebook have announced a "limited login" feature, which, if they were to add to their javascript sdks would certainly make my life easier:
https://developers.facebook.com/blog/post/2021/04/12/announcing-expanded-functionality-limited-login/
At the time of writing, I can only find reference to iOS and Unity SDKs, but it does seem to return a normal JWT, which is all I want!

Restricting REST API results based on the user

I am building a messaging application using BackboneJS which naturally persists using a REST interface.
The issue I'm having is that I don't know how to restrict what data a user can pull back from the API. For instance a call to /messages would, at the moment, return messages for ALL users. I would like that resource to only return messages belonging to the current user.
Searching online seems to indicate that oAuth2 is the best way to solve this issue but all the tutorials talk about been redirected to another place to confirm access and retrieve an access token.
Given that my users will have already logged into the message application and that the REST API is actually part of the same application I don't like the idea of asking the users to confirm that my own app can access my own API.
Is there a better way?
oAuth2 is probably your best bet -- you definitely don't want to roll your own security. However, the flavor of oAuth2 you are thinking of is probably not what you want.
oAuth2 has four different flavors, known as authorization grant types:
Authorization code: This is the type you are thinking about. It is often called three-legged oAuth, because there are three actors in the token granting process (app, resource owner, and user). The app asks the user whether it is ok for the resource owner to give specific type(s) of access to the resource. It is a rather complex process that allows the validation of user credentials without allowing the app access to them. This is not necessary in your case, since you are both the app and resource owner.
Client credentials: This is a method for authorizing a client application with the server. It does not use user credentials at all. If you completely trust your client application (all client applications) to correctly protect user data and not expose other user's data to the user using the app, or you are providing only non-user data via the API (for example, map data or catalog data), you might be able to use this fairly simple type of oAuth2. However, if you want to be vigilant in protecting user data (and not allow apps to get to the data without the user providing credentials), you might not use this one.
Resource owner password credentials: The username and password of the user is passed via https to your backend server, which authenticates and authorizes access by providing an access token. The access token can then be passed with each call, and it remains valid for accessing the backend until a configurable time period has elapsed. This means that someone intercepting the token could only use it successfully for a limited amount of time (some number of minutes, generally). The interceptor would not know the username and password of the user. In addition, you can supply the app with a refresh token, which can be used to get a new access token once it has expired (until the refresh token expires -- usually with a significantly longer expiration date). Since the credentials are not passed across the wire often (and must only be passed encrypted), this is often the best solution for protecting user credentials and not requiring the user to pass them in often (good user experience). Implementation is much simpler than for the authorization code grant type.
Implicit: This is the least secure method -- no credentials are validated server side at all. This is usually used for client side scripting languages where credentials cannot be stored safely. If you are worried about security at all, avoid this type if possible.
So, check out OAuth 2.0, and look for the resource owner password credentials grant type.