IdentityServer3 Multi Tenant IdSvr (single instance) with Multi Tenant Api (single instance) - needed multiple authserver addresses - identityserver3

We have IdSvr single instance with Web Api single instance that both support multi tenant. Our web app is deployed to multiple domains with their own styling on each. The business does not want them to be redirected to the IdSvr such as http://multiauth.identityserver.com. They want to go from a website domain to the IdSvr using http://auth.websitedomain1.com and another would use http://auth.websitedomain2.com, etc
The issue is with the Web Api and setting up the Bearer authentication.
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = Constants.BaseAddress,
RequiredScopes = new[] { "cspwebapi" },
// client credentials for the introspection endpoint
ClientId = "cspclient",
ClientSecret = "8BE96BA5-79F1-4FA4-8E41-6BCE7EA7090F",
});
I can only specify http://multiauth.identityserver.com as the Authority and not multiple such as http://auth.websitedomain1.com and http://auth.websitedomain2.com. The client gets a 401.
So far I have the single instance IdSvr with bindings auth.websitedomain1.com, auth.websitedomain2.com, auth.websitedomain3.com. Now on the Web Api (resource server) I iterate through the array of domain names and create a new app.Map(....) with each domain for the Authority property. The resource server spins up without issue meaning it can see the IdSvr at each domain name. The app.Map(....) segment needs to be the same for all of them...I now have found that doing app.Map('') for all of them will not work for the second or third domain name. Am I on to something here or is this the wrong approach? How else can I configure this to work per the requirements?

Use multiple instances of UseIdentityServerBearerTokenAuthentication in your pipeline, one for each of your IdentityServer installations, each configured with a different authentication scheme (AuthenticationType).
Then in your authorization logic, you can check what auth scheme the token authenticated with and authorize access to data accordingly.

Related

openid jwks rotation - reload on server without internet access

I have a question about the "best practice" of refreshing jwks data.
A customer has an java spring web intranet application with very strict network settings. So, the webserver is not allowed to make requests into the internet.
We must implement a SSO solution with MS Azure. So, we import the well-known openid configuration and import the data from the jwks_uri. Initially this is not a problem. So, the SSO login works - but only till the keys in the jwks_uri changes.
But how should we update the content from the jwks_uri?
The server is not allowed to access this internet resource.
As I have understood this, normally we should reload this data on a daily base. The content of the jwks_uri could change.
Is there a best practice for such a setup?
Or must I convince the security team to allow the server to access this two Microsoft URLs?
In the configuration of this SSO solution, the administrator fetches the wellknown openid configuration and the content from the jwks_uri and pastes the content to the intranet application admin interface.
So, the intranet server knows the public keys from the MS Azure service and can validate the signature of the id_tokens.
But this keys changes from time to time on MS Azure side.
So, is there a best practice for this how the intranet application comes to the new public keys?
Is there any "magic" I do not know?
You should allow the services that depend on AzureAD to also be able to communicate with them. Otherwise, you can't for example
get the tokens if you are using the authorization code flow.
use the refresh tokens to get a new access token
I don't see how you can get it to work if the services both public and internally can't talk directly to AzureAD.
However, there is one alternative and that is to have a local token service (IdentityServer, Keycloak...) to proxy between your local services and the public internet.
In general your services should only trust one token issuer.
The alternative is to provide the keys manually, for example by setting:
.AddJwtBearer("MyScheme", options =>
{
var key = Encoding.UTF8.GetBytes(Configuration["JwtConfig:AccessTokenSecret"]);
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
...
...
};
See sample answer here
How to set Dynamic IssuerSigningKey and TokenDecryptionKey in AddJwtBearer options in ConfigureServices method on Startup.cs file

use single unique client for multiple realm in keycloak

We are using keycloak in a multi-tenant micro-services application.
We have planed to use one realm per tenant.
Also there is single endpoint that all user requests (from all tenants) authenticated with JWT bearer token flow.
Is that possible to create one application client in keycloak and share it amount all realms?
Or we have to create a client (with same name) for each realms?
Is that possible to create one application client in keycloak and
share it amount all realms?
Out-of-the box this is not possible, just like users, clients are defined at the Realm level, and consequently, cannot be shared among realms.

REST best practice cloud

I have a set of REST services on IBM cloud. Ingress is integrated with Appid for authentication. Ingress adds the token id & access id to the authorization header.
Now on the API side (springboot) do I need to validate the user again on every request ? will this be redundant ? If no, which appid api can be used to authorize the user. Any reference to similar example
Already gone through the example on IBM cloud site. One is about ingress & appid integration, but does not talk about REST services layer how to handle the authorization tokens there.
Another is only about spring and Appid, (does not talk about ingress)
Authentication versus Authorization is where the line is drawn. The Ingress integration with App ID does the authentication for you and your REST service (application) can be assured that the request if it comes through is authenticated. Now just because the user exists in your system and has provided the right credential does not mean that he is allowed to access the service he is trying to access or view the data he's trying to view which is where the authorization comes into play - the REST service can use the authorization tokens to figure out if the user has the right access to use the service.
Here's a good article that talks about the use of Roles - https://cloud.ibm.com/docs/services/appid?topic=appid-tutorial-roles
In any application - REST, UI or otherwise - multiple levels of security may be necessary depending on your requirements. Authentication verifies the user is who they claim to be, authorization checks what permissions the user might have. Each application might have its own rules for what the user can access.
In your case, you have authenticated the user facilitated via Ingress with AppID, which supplies a user principal (identity) to your application. However, should every user have access to all of your application endpoints? If the answer is no, then you will need an authorization model, for which a common approach is RBAC (role-based access control).
Even without an RBAC requirement, it is still wise the validate the user's principal in some form for each request. For example, perhaps the user belongs to a domain that you might not expect, or should no longer have access to this specific REST application. Your application server may have features that assist you with a simple authorization feature, or you can custom build your own validation.
At present, as the identity provider, AppID can be the store of the user's role for RBAC. However your application or application server must decide what to do with that role.
If you are looking for a Cloud-centric authorization solution, you may want to consider exploring Istio's authorization policies:
https://istio.io/docs/concepts/security/#authorization-policy
https://cloud.ibm.com/docs/containers?topic=containers-istio

IdentityServer3 Client to client authorization

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.

Multiple Client Types

I have a web application that I would like to use authenticate using MembershipReboot for a subset of users but internally I would also like to use Active Directory.
What's the best practice of authenticating a single web application with two different authentication models? Any code samples would be great.
For this scenario you'll need a UserService for Membership Reboot. This will mean when users log in to Identity Server using the local username & password fields they will use Membership Reebot. You can find this UserService here.
To also use Active Directory you need to configure it as an external identity provider. This will then provide users with the option to log in using their AD credentials.
If you want to specify in your requests which provider to log the user into, check out the acr_values parameter of the Authorization endpoint or the IdentityProviderRestrictions property of the Client class.