What is best practice when registering new users on an Identity Server 4 based infrastructure? - asp.net-core

I am in the process of adding an Identity Server 4 implementation to serve authentication and authorization for a ASP.NET Core Web API. Clients will be a native iOS app, and MVC web app and potentially an Angular SPA later down the line.
I am able to provide tokens on an « offline access » basis to the iOS client using AppAuth - which is great.
I am just not sure about some of the architectural choices to make:
1/ where should the registration of new users take place? The literature recommends that the IS4 server be limited to login and logout endpoints, for security purposes. Does that mean that the clients or the APIs should handle creation of users in the store? I thought the whole point of IS4 was that clients and APIs don’t have access to the store? It would seem logical that the addition and modification of users be handled by the only part of the system that has access to the store, no?
2/ is it safe to persist (1) tokens (2) the user store and (3) business data ok the same database - different tables but same database on same server? Is it better to separate databases?
3/ is it safe to have the Identity server app hosted on a sub domain to the domain where the client app will live? The API is already on another sub domain on this same domain.
Thanks

1/ where should the registration of new users take place? The literature recommends that the IS4 server be limited to login and logout endpoints, for security purposes. Does that mean that the clients or the APIs should handle creation of users in the store? I thought the whole point of IS4 was that clients and APIs don’t have access to the store? It would seem logical that the addition and modification of users be handled by the only part of the system that has access to the store, no?
You can extend IDS4 to add user management. Per IDS4 docs it is a middleware that adds the spec compliant OpenID Connect and OAuth 2.0 endpoints to an arbitrary ASP.NET Core application. But this doesnt mean that you can not extend it. Here is a sample.
2/ is it safe to persist (1) tokens (2) the user store and (3) business data ok the same database - different tables but same database on same server? Is it better to separate databases?
This depends more to your deployment model and your considerations for availability and scalability rather than safety. I suggest you to read more here to be able to make the best decision.
3/ is it safe to have the Identity server app hosted on a sub domain to the domain where the client app will live? The API is already on another sub domain on this same domain.
This again has nothing to do with safety as is more of availability/scalability matter

I have thoughts as following:
1/ where should the registration of new users take place? The
literature recommends that the IS4 server be limited to login and
logout endpoints, for security purposes. Does that mean that the
clients or the APIs should handle creation of users in the store? I
thought the whole point of IS4 was that clients and APIs don’t have
access to the store? It would seem logical that the addition and
modification of users be handled by the only part of the system that
has access to the store, no?
Suggestion: If I am starting applications from scratch and there is no existing interface for user registration, then I will prefer to provide user registration flow as part of IdS.
2/ is it safe to persist (1) tokens (2) the user store and (3)
business data ok the same database - different tables but same
database on same server? Is it better to separate databases?
Suggestion: Both options are fine, but best one, is one, which suitable to your application architecture. For example if I have Service oriented or Microservice architecture, then separate database is more feasible. But if you have only one application as user registration point and other applications will use that database as user store, then it is already part of an application database. I may prefer to have IdS tables in separate Database until, unless there is some limitation.
3/ is it safe to have the Identity server app hosted on a sub domain
to the domain where the client app will live? The API is already on
another sub domain on this same domain.
Suggestion: if you are serving multiple organizations, then IdS can be on different domain, otherwise, it is generally practiced to be on sub domain.

Related

Share credentials between 2+ internal MVC Core 2 apps w/o Identity Server

What is the best way to share credentials between 2+ ASP.Net MVC Core applications, meaning a user can log into one application and will have access to the other application(s). The apps are for external clients but would be hosted on the same server. I am looking for the simplest solution, I don't want to implement an OAuth server unless absolutely necessary. I have considered the following options:
Implement Identity Server 4. This seem like overkill for my use case, looks like this is a significant effort, and may require more time to implement than a simple MS Core Identity solution.
Use MVC Core 2 MS Identity and share the authentication database between the two databases. This implies using a unique DB for each application, but a single DB for authentication.
Sharing authentication cookies between applications (on the same domain etc).
Any other ideas?
It depends on one main thing: what are the domains the sites are being deployed to? Session-based authentication (what websites use) depends on a cookie being set on the client. Importantly, cookies are domain-bound. In other words, a cookie can only be "shared" with sites on the same domain, or subdomains on the same domain if the cookie domain is set as a wildcard.
That right there defines your whole approach. If you've got something like abc.com/site1 and abc.com/site2 or even site1.abc.com and site2.abc.com, you can share the cookie. However, if you're dealing with abc.com and xyz.com, you're borked.
If all the sites are on the same domain (or subdomains on the same domain) then all you need to ensure is that all the sites are using the same data protection setup. In previous ASP.NET sites, encryption was handled via a "machine key", so you simply had to ensure that the machine key was shared. ASP.NET Core uses Data Protection which functions differently, but the basic principle still exists. All the setup needs to be the same across all the sites so they essentially all encrypt and decrypt things in the same way. Since the auth cookie is encrypted, this is absolutely required to shared that cookie. Thankfully, Microsoft has a guide for doing this.
If the sites are on completely different domains, there is no way to share the auth cookie. Period. Full stop. Your only choice then is something like Identity Server.

Authenticating external ADFS users in my SAAS application

Our SAAS system is currently using standard Microsoft.AspNet.Identity.Owin libraries to authenticate users via Bearer tokens, as well social logins such as Facebook/Google/Twitter/etc.
Some of our users are asking for us to start allowing of authentication via ADFS.
I'm trying to understand how this can be done. Unfortunately, all of the blogs appear to dive right into the details without providing a good overview as to what's involved. Furthermore, most blogs talk about trusting a specific Active Directory, while we need to trust a whole number of possible customers' active directories - and do it dynamically. IE: customer registers for an account using custom username/password, then provides our SAAS application with some information about their AD. Afterwards, our SAAS application should trust authentication for users in that AD (just the auth part)
Can anyone provide information on what's involved?
TIA
Agree with #vibronet's points.
Another approach would be to add STS support to your SaaS application. This could be either WS-Fed or SAML. You have tagged the question with Azure so AAD could be an option.
You could then federate with any number of other STS's (like ADFS). Note as stated that each ADFS has to agree to add your metadata.
Another approach would be to use IDaaS (e.g. Auth0, Okta). These would do the Identity heavy lifting for you and would essentially provide the STS capability.
The question has 2 parts,
how to work with an ADFS instance and
how to deal with an arbitrary number of ADFS instances from different
owners.
The answer to 1) is to use the WS-Federation middleware, which can be added alongside the middlewares you are already using. However the initialization of that middleware requires knowledge of the location of the metadata document of the ADFS you want to target; furthermore, the ADFS administrator must provision your app explicitly or no tokens will be issued. Hence, the flow you are suggesting (temporary username/password and subsequent details exchange) might be tricky - but not impossible.
About 2) there isn't a way of wiring up an arbitrary number of different ADFS instances unless you modify the middleware setting pretty heavily. The actual answer is that the standard practice for dealing with that scenario is to rely on one intermediary ADFS (or equivalent) that can broker trust toward all others, while your app only needs to trust the intermediary ADFS.

Microservices - how to solve security and user authentication?

There is a lot of discussion about microservice architecture. What I am missing - or maybe what I did not yet understand is, how to solve the issue of security and user authentication?
For example: I develop a microservice which provides a Rest Service interface to a workflow engine. The engine is based on JEE and runs on application servers like GlassFish or Wildfly.
One of the core concepts of the workflow engine is, that each call is user centric. This means depending of the role and access level of the current user, the workflow engine produces individual results (e.g. a user-centric tasklist or processing an open task which depends on the users role in the process).
In my eyes, thus a service is not accessible from everywhere. For example if someone plans to implement a modern Ajax based JavaScript application which should use the workflow microservice there are two problems:
1) to avoid the cross-scripting problem from JavaScript/Ajax the JavaScript Web application needs to be deployed under the same domain as the microservice runs
2) if the microservice forces a user authentication (which is the case in my scenario) the application need to provide a transparent authentication mechanism.
The situation becomes more complex if the client need to access more than one user-centric microservices forcing user authentication.
I always end up with an architecture where all services and the client application running on the same application server under the same domain.
How can these problems be solved? What is the best practice for such an architecture?
Short answer: check OAUTH, and manage caches of credentials in each microservice that needs to access other microservices. By "manage" I mean, be careful with security. Specially, mind who can access those credentials and let the network topology be your friend. Create a DMZ layer and other internal layers reflecting the dependency graph of your microservices.
Long answer, keep reading. Your question is a good one because there is no simple silver bullet to do what you need although your problem is quite recurrent.
As with everything related with microservices that I saw so far, nothing is really new. Whenever you need to have a distributed system doing things on behalf of a certain user, you need distributed credentials to enable such solution. This is true since mainframe times. There is no way to violate that.
Auto SSH is, in a sense, such a thing. Perhaps it may sound like a glorified way to describe something simple, but in the end, it enables processes in one machine to use services in another machine.
In the Grid world, the Globus Toolkit, for instance, bases its distributed security using the following:
X.509 certificates;
MyProxy - manages a repository of credentials and helps you define a chain of certificate authorities up to finding the root one, which should be trusted by default;
An extension of OpenSSH, which is the de facto standard SSH implementation for Linux distributions.
OAUTH is perhaps what you need. It is a way provide authorization with extra restrictions. For instance, imagine that a certain user has read and write permission on a certain service. When you issue an OAUTH authorization you do not necessarily give full user powers to the third party. You may only give read access.
CORS, mentioned in another answer, is useful when the end client (typically a web browser) needs single-sign-on across web sites. But it seems that your problem is closer to a cluster in which you have many microservices that are managed by you. Nevertheless, you can take advantage of solutions developed by the Grid field to ensure security in a cluster distributed across sites (for high availability reasons, for instance).
Complete security is something unattainable. So all this is of no use if credentials are valid forever or if you do not take enough care to keep them secret to whatever received them. For such purpose, I would recommend partitioning your network using layers. Each layer with a different degree of secrecy and exposure to the outside world.
If you do not want the burden to have the required infrastructure to allow for OAUTH, you can either use basic HTTP or create your own tokens.
When using basic HTTP authentication, the client needs to send credentials on each request, therefore eliminating the need to keep session state on the server side for the purpose of authorization.
If you want to create your own mechanism, then change your login requests such that a token is returned as the response to a successful login. Subsequent requests having the same token will act as the basic HTTP authentication with the advantage that this takes place at the application level (in contrast with the framework or app server level in basic HTTP authentication).
Your question is about two independent issues.
Making your service accessible from another origin is easily solved by implementing CORS. For non-browser clients, cross-origin is not an issue at all.
The second problem about service authentication is typically solved using token based authentication.
Any caller of one of your microservices would get an access token from the authorization server or STS for that specific service.
Your client authenticates with the authorization server or STS either through an established session (cookies) or by sending a valid token along with the request.

WCF using 2 Authentication Methods With Windows Identity Foundation

I'm working on a WCF project that will be our new service layer.
These services will be called by 2 separate clients, the first of which is a WPF application and the other is an ASP.Net web application. The WPF client will be run by internal users and will authenticate with the service via domain authentication and run under the context of that user. The other will be used by external users and needs to authenticate using some separate mechanism then impersonate a "WebUser" account on our domain.
I'm reading a bit about Windows Identity Foundation and it sounds like this might be a good fit. Am I right in thinking I could have 2 token services, one for domain authentication and one for something like ASP.Net membership authentication (Or some similar equivalent) and have each client get it's token from the relevant STS and pass that along to the WCF service?
I'm assuming there is an STS I can use out of the box for domain authentication, but will I have to implement the second one myself to authenticate web users? I can't find a lot of information on this.
Am I thinking along the right lines or should I just be creating duel endpoints for each service each with a different authentication mechanism? Or should I be doing something completely different?
Thanks
The big advantage of using Claims-Based authentication / WIF is that both the task of authenticating the user AND the administration of the user's properties are moved way from the applications to the STS/Identity provider.
You are developing a service layer but the true benefits of using WIF will be for the applications written on top of your layer. The WPF application will no longer need to connect to the AD and fetch the user's groups to figure out what they are allowed to do. The groups will already be visible as claims in the token the user/WIF provides.
The web application (is it just one web application or more?) will no longer need the ASP.Net Membership database with accompanying user administration. This functionality gets moved to the STS.
There is a cost. (There always is, somehow...) Claims-Based authentication has a rather steep learning curve. It takes a while for the quarter to drop for all people involved.
So the answer to your question depends on what kind of users the web application(s?) built upon your service layer have and how many. And how much they wish to know about them. Can you perhaps trust Google / Facebook / Windows Live for authentication? Are the users already in an existing database within your domain? How much work will it take to maintain the user directories? Do your marketing people wish to send them emails regularly? Et cetera.
This is probably not just for the service layer's developers to decide, but something to discuss with people in the rest of your organisation.
If the benefits are not particularly big, the alternative is to simply keep these responsibilities at the web application's server. Each web application will have a good old ASP.Net membership database, it'll authenticate the user all by itself. When asking queries from the service layer, it'll present its web server certificate plus specify the user's name and type.
If the benefits are big enough, you can in principle use ADFS 2.0 for everything. It can also store external users nowadays and it's free if you already have Active Directory. Or the ThinkTecture 2.0 server that Ross recommends. It's easier to customize and perhaps your systems administrators and security folks will not be too enthusiastic about opening the firewall to the ADFS server.
Microsoft has some good reads on WIF, in particular an Overview of Claims-Based Architecture.
You should take a look at identity server as it can indeed handle this scenario.
The person who leads the project above has a great pluralsight video on this exact scenario! You need to sign up to watch it, but they offer a free trial.
Basically you get a token from the identity provider (windows ADFS for the internal client, and what ever you decide for the external users). You will give this token to the federated gateway (identity server probably, but it could be Azure ACS). This will return an authentication token that you can then use with your service.

Single SignOn - Best practice

I need to build a scalable single sign-on mechanism for multiple sites. Scenario:
Central web application to register/manage account (Server in Europe)
Several web applications that need to authenticate against my user database (Servers in US/Europe/Pacific region)
I am using MySQL as database backend. The options I came up with are either replicating the user database across all servers (data security?) or allowing the servers to directly connect to my MySQL instance by explicitly allowing connections from their IPs in my.cnf (high load? single point of failure?).
What would be the best way to provide a scalable and low-latency single sign-on for all web applications? In terms of data security would it be a good idea to replicate the user database across all web applications?
Note: All web applications provide an API which users can use to embed widgets into their own websites. These widgets work through a token auth mechanism which will again need to authenticate against my user database.
I would not integrate the authentication on the database level, as in replicating the db or allowing access from the other servers. This might become hard to maintain. I would prefer a loosely coupled approach by exposing a simple service on your central server that lets the other app servers run authentication requests.
You should look into the following issues (probably more):
How to avoid cleartext transmission of passwords between servers
You probably can't throttle the service if a network of application servers authenticates all their users from the same IP, so you might want to restrict access to certain clients to avoid rogue machines mass-probing for valid accounts.
How to centrally enforce things such as session expiration
How to handle / avoid service downtime
Techniques that might be helpful:
Cryptographic CRAM (to avoid password transmission)
Certificates (to prove the clients' identity)
Alternatively, you might want to have the clients use the central service to obtain a token that is then promoted to and verified by the target server. There's architectures that work similarly (e. g. Kerberos ticket servers) which may serve as inspiration.
You should go for Oauth2 or SAML.