I'm implementing an identity server using IdentityServer3, and want to restrict a particular ClientCredentials client to a set of IP addresses.
I've tried a few things:
I see an AllowedCorsOrigins property on the Client object, and if I enable this I see IdentityServer logging warnings, but it doesn't prevent access.
Injected OwinEnvironmentService into my UserService's constructor - UserService doesn't seem to be used by the ClientCredentials flow.
Is this possible, or am I misunderstanding how to use ClientCredentials?
This is not easily possible with the client credentials flow. But you could implement a customized m grant type instead.
https://identityserver.github.io/Documentation/docsv2/advanced/customGrantTypes.html
Related
This is just a general question about microservice architecture. Why do 2 or more internal services still need token auth like oauth2 to communicate with each other if the outside world doesn't have access to them? Couldn't their apis just filter internal IP addresses instead? What are the risks with that approach?
Why do 2 or more internal services still need token auth like oauth2 to communicate with each other if the outside world doesn't have access to them?
You don't need OAuth2 or token authentication, but you should use it. It depends on how much you trust your traffic. Now in the "cloud age" it is common to not own your own datacenters, so there is another part that own your server and network hardware. That part may do a misconfiguration, e.g. traffic from another customer is routed to your server. Or maybe you setup your own infrastructure and do a misconfiguration so that traffic from your test environment is unintendently routed to your production service. There is new practices to handle this new landscape and it is described in Google BeyondCorp and Zero Trust Networks.
Essentially, you should not trust the network traffic. Use authentication (e.g. OAuth2, OpenID Connect, JWT) on all requests, and encrypt all traffic with TLS or mTLS.
Couldn't their apis just filter internal IP addresses instead? What are the risks with that approach?
See above, maybe you should not trust the internal traffic either.
In addition, it is now common that your end-users is authenticated using OpenID Connect (OAuth2 based authentication) - JWT-tokens sent in the Authorization: Bearer header. Most of your system will operate in a user context when handling the request, that is located within the JWT-token, and it is easy to pass that token in requests to all services that are involved in the operation requested by the user.
For internal services it's usually less about verifying the token (which in theory was already done by the external-facing gateway/api), and more about passing through the identifying information on the user. It's very common for even internal services to want to know who the requesting/acting user is for permissions and access control, and sometimes it's just easier to tell every service creator who needs user-scoping to accept a JWT in the Authorization header than it is to say, "look for the user ID in the X-COMPANY-USER-ID header".
You can implement very granular role based access control(RBAC) on the apis exposed by Microservices using Oauth which you can not do using filtering IP address.
In most OAuth2 typical use cases, the scope is used by resource owner password grant type, or authorization code flow, where a user login is required.
It seems that scope is mainly used to control access of users' resource. For example, to authorize a 3rd party client to access the resource owner (user) resource at another server.
In some cases, user is not present. For example, a company wants to provide a API for another company only. Client credential is being used. Most API gateway products have subscriber management option to control which client ID can access which APIs. In that case, is it still meaningful to use OAuth scopes to manage access to APIs? Why?
Besides, I cannot find any examples using scopes along with client-credential grant type. Is it rare use case?
The Client Credentials grant type is used to access protected resources that both sides own/control/trust.
Scopes are supported by this grant type. They are typically not used because the trust is already there and limiting that trust via scopes is not required.
In other words, the reason that scopes are not used is that if the trust is not there, other grant types are more appropriate.
I have an OAuth2 server that is able to give me an access token based on my client ID & secret.
I have a microservice where other servers can perform actions respective to its job.
However, I need to authorize the token to ensure it has the permissions to do that.
Is it common for the server to forward the access token to the auth server and get a response back that includes the details such as scope? etc.
Yes and no.
For the entry point, you definitely need to check the access token's scope by asking it to oauth2 provider, but you probably don't want to do it everytime it's following code to call the provider whenever it requires scope check.
In Spring framework, that authorized information is stored in SecurityContext, and any code in the same VM can access it by calling SecurityContextHolder.getContext().getAuthentication(). Probably you can implement similar thing with your language and platform you are using, so that authorized information can be shared by others, with thread-safe way.
However, in microservice world, each microservice could or could not have the scope its client used. For example, let's say there is client A, calling microservice B's C method, and B's C calls another microservice's H's I method.
Depends on what scope is required for the method B.c() and H.i(), even if your code can propagate the OAuth2 scope to the following microservice, client A's call could end up having insufficient scope exception and fails.
If you are lucky, then yeah client's call will succeed.
I had the same issue, and there wasn't any clear silver bullet or best practice for what to do with OAuth2 scope in Microservice world. I feel like it just all depends on what's your service topology look like and how it is designed.
I'm implementing my own OpenID Connect provider using Identity Server 4.
I understand, that once issued an access token, clients can use it to obtain claims about the end-user from the userinfo endpoint. Which works great, by the way.
However there are certain use cases where it might be necessary to obtain claims about other users in the system. Think about a user who is head of a department. Clients might want to get email addresses of other users in this department on behalf of this user to notify them about something.
My question is: Is such functionality covered by OpenID Connect or is there a feature in Identity Server 4 to help with this?
I see that I could implement this myself by exposing part of my identity service as just another api protected by the identity server itself. For my use case it would probably be enough to flag certain claims as public for other users, so they can be accessed like any other resource. However there might be some security issues I might be overlooking. Also I would be interested if there was a non-proprietary way to do it, so it could be used by arbitrary clients, and show up in the discovery document.
Any input on this topic would be highly appreciated!
I have a scenario where my Resource Server (RS) can connect to multiple databases and it can be multi-tenant. It has an environment configuration where I can say: Env A points to database A and belongs to tenant A; Env B points to database B and belongs to tenant B;
Our desktop apps store that information in a data structure that is sent to RS on every call and our web apps store it inside ASP.NET Session. The user select the environment at login.
Now we are moving our APIs completely to REST services and protecting them with oAuth2 using IdentityServer4.
I need to send that environment value to the APIs and I think that should be part of the access token.
The first question is: Is that correct? Can a access token have that kind of information?
The second is: Which is the best IdentityServer4 service that I should extend to inject that value as a claim inside access token and consequently inside ClaimsPrincipal.
The third is: Sometimes I don't have a user to select the environment at login (client credentials grant, for example). In this case, is the correct treat environment as a client claim? There is a way to have dynamic client claims?
Sorry about the long question!
Regards,
Diogo
If that claim is about the users (or clients) identity - yes - it is a candidate for the token.
Add the claim to the resource scopes that represent your API - this way the claim type will be requested in the profile service and you can add it to the token.
Client claims are not dynamic though.