I'm working on a solution with others where we have built on a Visual Studio Web Project using MVC (5 I think) and WebApi2.0.
The nature of the solution is that it has 2 DALs, one of the DALs uses SQL to access another applications database, the other DAL uses entityframework codefirst to manage our applications database. There is also a service that is associated with the project so we have done our best to adapt the entire solution into a 3 tier pattern. This means there is a project that contains our BusinessLogic and both our service and our Controllers use it to access the DAL.
So all that out of the way...We are now adding in authentication on the web side. We were stuck for days until we really just embraced Microsoft's default project structure with the OWIN authentication. The downside is that we now have a separate User database that is essentially coupled with the Presentation/Web layer of the solution.
Is there any way to keep all the convenience of the default OWIN authentication in the MVC project AND abstract it out into the LogicLayer? I can't post what we've worked on, but needless to say it's failed every time because we are really struggling to identify what is being done for us behind the scenes (one example is the [assembly: OwinStartupAttribute(typeof(AlarmAggregator.Startup))] annotation). This annotation alone makes me think we will NOT be able to abstract it out.
I know I'm asking to have my cake and eat it too, but I was hoping someone had some insight if it was possible.
At the very least we were hoping there was a way that we could combine our internal database and our user database? I think this would have to happen at the context level? Would it be as simple as pointing our web.config at our internal context?
Since you have not mentioned what those 2 databases are, I assume they are not user databases and out of context. Focusing on the user identity storage, yes its going to be a separate entity unless you are using ADFS, LDAP or something. I would discourage you from building your own identity solution, rather look out for something more widely used and accepted because its a security topic.
Take a look at Thinktecture Identity Server. Its an OpenId Connect based open source solution built in .NET. It comes with its own database, supports same domain SSO, cookie based authentication and supports open id connect. It also supports federated authentication if you want to hookup a ADFS. Its also possible to do social sign in integration with it.
I have integrated .NET, Java and PHP solutions in production to the same instance and everything is fantastic and seamless.
You can host it as a separate service. You can register known clients (your apps and services), their incoming and redirect urls, including post logout Urls, so your application can seamlessly reach out and come back from identity server. The Identity Server comes with all the middleware you would need to protect your APIs and web applications. It also provides REST endpoints for getting and validating access tokens amongst others.
You can also set different scopes to specify the scopes against which a request can be processed.
Much of what I am talking about has directly to do with oAuth 2.0 specs so probably you can read a little about it here if you are not aware of it.
Using a typical oAuth Flow, (e.g implicit flow or authorization code flow), hooking up the right middleware in the Owin pipeline, and decorating your API resources with [Authorize] attribute, your Application will redirect to the identity server page where the user can login. Your APIs(the protected resource) can specify if they are expecting for a specific Scope, when a token is presented and allow to accept/deny your request based on that.
The client registration ensures that only known clients are accepted by identity server(as applications are generally internet facing) and you can either use the MembershipReboot component, also from Thinktecture(also opensource) as your identity store or write your own implementation of a "user service". There are way too many extension points available to play with and you can practically customize everything including the look and feel of the identity server pages to match the UI scheme of your client applications. There is IUserService(to plugin your own user store, ViewLoader to customize UI, CORS policy service to specify allowed origins per client, certificate based TokenSigningService to sign tokens(access/refresh tokens), ScopeStore, ClientStore, TokenHandleStore(to store scopes, client configurations, tokens), ClaimsFilters to filter what claims are included when a token is issued, which is helpful when you use external providers which might return more information that you need to store or provide)
I can go on for ever here but like I said its something available for use and I am using it for multiple applications in production, you can give that a try.
You can have it up and running in 30 mins on your local machine with both Identity Server and MembershipReboot databases setup. The support is very good from the authors and this is a very widely accepted solution for user authentication and authorization.
For example, securing a WebAPI is super simple:
decorate your APIs with [Authorize] and or [ScopeAuthorize] based on your need
This tells the API to go and check if you got something setup for Authorization in the owin pipeline.
In Owin startup just use:
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions()
{
Authority = "http://your-idserver-url"
});
Yes that is all the change you need in your WebAPI. There is a separate way to setup open id configuration for MVC based web applications but that is anyway available in the documentations with sample code.
The documentation is pretty easy to follow and the server is easy to setup. It takes away all the complexity from your App and services so you can focus on what you want your App to do rather than worrying about handling Authentication and Authorization in each of your Apps or services.
Related
I am trying to migrate one of our solution from a Laravel/PHP system to a .Net Core 2-based system. My main problem is regarding Authorization and Authentication.
I have 5 different apps that send REST queries to the Api (e.g. Web Browser, iOS Apps, Android Apps, etc.) and the way I currently handle authentication/authorization is as follows:
A user sends a Username/Password, as well as an App Id (e.g. 'Browser', 'iOS', etc.) and an App description (e.g. 'Chrome-Jacob', 'iPhone-7-Jacob').
If a Token already exists for the pair of App Id / App Description, it is returned. Otherwise, a new token is generated and saved in a Database table named 'Tokens'.
Each token can have a different matrix of permission, which is very granular (e.g. 'Users/ViewAll', 'Users/Create', 'Users/ViewOne', 'Users/ViewMe', etc.)
When a REST query is received with the token in the header, we look for the token's permission matrice in the database and try to see whether the intended feature to be accessed is authorised or not.
It seems that in Core 2, the intended use of token is through JWT. I'm not 100% comfortable with this approach, because I want the user to be able to see all tokens that were generated for his access, all associated permissions and the ability to simply revoke access to a token; whereas with a JWT, it is impossible to know who has what token, until they send it in a request.
My current implementation can generate any random token as long as it's unique in database; it doesn't necessitate any encryption algorithm.
What would be the best approach to replicate the system above in Core 2 ?
I find Microsoft's approach very good for simple applications but I am struggling to override the Authorize Attribute and get the granularity that I wish for.
I find Microsoft's approach very good for simple applications but I am struggling to override the Authorize Attribute and get the granularity that I wish for.
That's quite the opposite. Microsoft did not invent nor were close to the first to start using JWTs. You have taken something that is very common and made your own version of it, something that's not considered secure nor a good practice.
There are two ways to solve the problem at hand:
Using Identity Server 4, a free, open-source system made for ASP.NET Core, made by highly experienced security people, which provides you a customizable OAuth 2.0 / OpenID Connect system. With this, you would need to rework, some parts of the security of the applications, but you would be using industry standards.
Note: this might not be too easy, but scales extremely well
Identity server already gives you all the information about each application and which tokens are valid for which.
While you could do this by hand without too much trouble, I would suggest you to look at ASP.NET Core Identity, the official framework for Authentication and Authorization in ASP.NET Core. Notice that, regarding how to know which tokens/logins are active, Identity recently adopted two interesting tables:
IdentityUserLogin: tells you what users logged in where/how
IdentityUserToken: gives you the tokens that have been provided for a given user.
All this said, it's common to add ASP.NET Core Identity to an Identity Server 4 application, given that the later is not for handling authorization.
https://identityserver4.readthedocs.io/en/release/intro/support.html
I currently issue tokens myself in my web api with JwtSecurityToken and I use standard ASP.NET Core middleware calling AddJwtBearer to verify the tokens. It works fine.
What advantage will give me using OpenID Connect (through IdentityServer4) over the approach described above? How to answer myself question "Do I need OpenID Connect?"
From my basic understanding about OpenID Connect, it is used to allow third parties to access your API. But I make API for myself and not for third parties and I don't know why should I favor IdentityServer/OpenIddict over my simple approach.
I read that if I want Single sign-on I should use this, but JWTs itself aren't bound to any specific domain and I can use single sign-on with just pure JWTs(they're self-contained)
I understand it implements some kind of standard for issuing tokens. (protocol). It might be good if I ever wish to expose some API to third parties. But for internal APIs? Is it worth using it?
This is my current auth flow (from https://jonhilton.net/2017/10/11/secure-your-asp.net-core-2.0-api-part-1---issuing-a-jwt/)
What I really want to implement to secure my Web API:
Login
Logout (invalidate token?)
No consent screen (want to have API only for myself), auth happens in the background in my native desktop, mobile, web app (no redirection)
Remember me feature (refresh tokens?)
Could someone clear out the fuzzy picture of OIDC/OAuth2 for me? i.e. give me some disadvantages going my own way (implementing my own flow) and advantages of using OIDC in place of my own flow.
What will it save me from doing later on (on the client-side for example), and what will not. And most particularly, is it good to start every project using standard flows like OIDC? Will it somehow benefit me in the future?
In any case you will implement OAuth2. Think of Oidc as an extension of OAuth2. The most important thing to keep in mind is seperation of concerns.
Forget Oidc, Identity Server 4 is all about authentication: "who is the user"? Consider Google login. When a user logs in for the first time, the application doesn't know the user, it only knows that Google does.
Authorization takes place on a different level and isn't really a concern of IdentityServer. For that you could take a look at PolicyServer.
So you'll need to keep the user database seperated from the application database. This doesn't mean you need another database, just don't mix contexts. If you have a relation from the "business context" to e.g. the user table in the "Identity context" then you are going to have a problem eventually.
In your setup your web api is both the resource and the identity provider. This means that every new web api you create has to be implemented as both resource and identity provider. For maintainability you could create a seperate web api that acts as an identity provider, while the web api is a resource only. You can implement something like that as long as all apps can read the token.
The same counts for the front. Why should the front have anything to do with the user? All it needs to do is pass the token in order to get the user authorized. In case of IdentityServer, the app contacts it to verify the user and receives a token. It knows nothing about credentials. This is more secure. The client app can be compromised. The credentials can be intercepted.
Having single apps with a specific concern makes things more maintainable. And it is quite easy to add a new resource without having to code when you use IdentityServer. Just add the configuration. It also allows you to add other flows in the future that are not needed at this time. And as a side note, the consent screen is optional.
The bonus is that you can implement SSO, where in your setup that could be harder, if not impossible.
So you don't have to use IdentityServer, nor Oidc. Your setup may be just fine. But if you build something, keep seperation of concerns in mind.
We need to make a central auth server for multiple applications that we build, while still having roles and claims which are specific to that particular application. Let me explain with an analogy using various services by Microsoft.
I sign up for a Microsoft account and hence my authentication info is stored in a central server. Now i login using the account and assume a fresh start i land up at account.microsoft.com, now i go to msdn click on sign in, it takes me to the login page on auth server then to the consent screen and back to msdn logged in, now i go to xbox and does the same thing. Now MDSN and XBOX are two completely different applications with each having it's own Api, web apps and mobile apps, but using the same auth server.
Till now i have been making independent applications using Identity Framework, and am reasonably comfortable with it, but this is comparatively much more complex than what i have done till now. I was looking through IdentityServer4 to have a central auth server and has completed all the tutorials present on the official doc site, so i have a basic idea of the concepts.
What i need is to have each application be able to specify it's own set of roles and claims without even having any kind of knowledge about other applications, and also the central server will be having external authentications enabled, hence ASP.NET Core Identity in central server.
Current Architecture
Central Identity Server (using IdentityServer4, ASP.NET Core Identity, Entity Framework)
One Central DB for Central Server
Multiple Applications Sets (API, MVC App, Xamarin Mobile Apps)
One or more DB for each application as per need
Things i am able to achieve till now
Customize an identity resource to get user claims stored in db but if i add one roles, it returns me the role repeatedly the number of times as the count of API resources and Clients
Alternate solutions that i came up in my mind
Store the claims and roles in application specific DB, but i guess that i will be facing these issues
too much effort wiring up the auth logic, as it will have to first get the identity from central server and then get claims from the application specific DB
not sure how i can do it using asp.net identity on client side
unused table on central auth server
duplication of auth logic across applications
These stack overflow questions gets the most closest but are not the exact solution
ASP.NET Core Identity and Identity Server 4 - [Roles, Claims and
IdentityResources]
IdentityServer, Claims and Roles
How to add additional claims to be included in the access_token using ASP.Net Identity with IdentityServer4
Any guidance that takes me in the right direction will help
EDIT #1 : It seems like someone has flagged this questions as off-topic, so just want to clarify that i am looking for a specific code/solution using identity server 4 and asp.net core identity and not some recommendation, though any guidance apart from the answer is welcome for better clarifications and understanding, but just the code would suffice, and i feel that it's as per the guidelines of the community.
EDIT #2
I tried doing authorization on client side as suggested by #travis.js but i am unable to understand how do i implement the claims on client side something like [Authorize(Roles="Admin")]
I think your alternative solution is the "right" one.
Addressing your concerns:
too much effort wiring up the auth logic, as it will have to first get
the identity from central server and then get claims from the
application specific DB
Sounds like exactly the right amount of effort to me. The Central Server does authentication and each app does its own authorization.
not sure how i can do it using asp.net identity on client side
You don't really need ASP.NET Identity on the client/app side. Identity is handled by your central server.
unused table on central auth server
Non-issue. But you could still use that table for its intended purpose just at a more macro level.
duplication of auth logic across applications
This does not sound like a duplication of logic. The Central Server does identity/authentication and each app is responsible for determining its own authorization logic.
Question: Can we simply hook into the OWIN pipeline to set and retrieve the security authentication ticket (cookie)?
I'm searching for the best approach to roll our own security/membership for an MVC 5 application. I have no issue with registration, sign-in, password change, two factor, password recovery etc. My concern is the pipeline.
Project: The project is a multi-tenant SaaS application that requires many changes to the the Identity framework. We are exploring writing our own, which we have done for many projects in the past.
We do not make use of claims or outside providers such as Google or Twitter for authentication, all accounts are local db role based accounts. The project does not use EF.
We explored creating our own store for Identity, however, by the time it's fully implemented, there were too many areas of concern and it felt as though though the User Manager was simply in the way. Code was starting to bloat beyond a level of what is needed to role our own.
Passwords are created, managed, and stored securely and are not of concern for this question.
We are using our custom authentication mechanism wired in the OWIN pipeline. We are using our own custom middleware into the owin pipeline and thus will enable the authentication to happen
The only process that needs to be done is your middleware should validate the identity and the cookie authentication middle ware in the pipeline will set the cookie based on the established identity.
The way this will be working is the ordering of the middlewares and the use of the AuthenticationManager in the Owin authentication pipeline.
We too are using social logins like Google, Facebook etc that co-exist with our own custom authentication provider middleware, we also use JWT middleware for implicit flow authentication.
Long answer short is : Yes
More details : based on your further post on the exact details that need to be attended to.
If you are willing to consider a hosted solution, I would recommend taking a look at http://aka.ms/aadb2c - the samples referenced by that page will show how to use OWIN middleware to connect to a hosted identity store.
We are running multi-tenanted SaaS app with configurable per-role permissions. We make use of Claims system to store user permissions in the cookie when users login. And that works wonderfully and is really performant.
You don't have to use actual Claims to put your permissions, but you can store bits of information as a Claim on a user cookie that will be used to determine user permissions.
Since your question is a bit vague about the actual implementation I will not bring any code samples - given your hand-rolled security system, most likely my examples will not be applicable. Unless you clarify your question with a specific example of what you are doing.
I want to authenticate a user using a third-party system when they hit a Controller or ApiController with the [Authorize] attribute, but I really don't want to have to create associated users and logins that OWIN requires in order to create the cookie that keeps the user session authorized, because our third-party system is already tracking that.
Normally, you'd map OWIN logins to external logins, but our system, as-is, is so tightly integrated with this third-party system that there are a bunch of reasons (that I won't go into) that we don't want to do that.
Is there a simple way to use ASP.NET MVC5 out of the box that allows you to authenticate to another system, and then mark the session as Authenticated without having to find/register them in OWIN?
Sorry if this isn't a lot to go on. I've not seen any way to go about this without perhaps implementing our own IAuthenticationManager, but I'm not even sure where I'd start to do that.
Thanks for any help you can offer.
I believe OAuth is the only ASP.NET SSO support you get out of the box. It would help if you elaborate on the nature of the third party authentication system, since you'll need to integrate with it in order to provide the SSO experience.
Here are a couple of blog posts explaining how to create custom OWIN authentication middleware, which seems to be what you'll need to do to set ASP.NET Identity based on some information from an external system (header, cookie, token, etc). I used the second approach to integrate with CA SiteMinder (commercial web authentication product).
Owin Auth 1
Owin Auth 2
I ended up solving this by creating my own implementation of IUserStore and its associated classes that wraps the third-party system.