IdentityServer 4 confused on how it all works - c#

I been reading and watching alot about Identity Server 4 and I am still a bit confused on it as there seems to be so many moving parts.
I now understand that it is a separate project and it handles authenticating users. What I still don't get is how does a user get registered to it? Who stores the username/password?
I am planning to have this setup
Reactjs front end
Asp.net Web Api Core 2
Identity Server
So would it work? All the videos I seen so far talk about doing in memory users what is find for testing but they never talk about registering it over.
I seen some videos where they have an existing database and then hook that up with Identity Server 4 and it checks that database. Yet they don't talk about if your starting fresh or even in their scenario when you sign new people up.
Edit
Camilo Terevinto brought up a point of using "ASP.NET Core Identity" and I been looking into it and have some questions.
My understanding of this is right now like this
A user comes to my reactjs site and wants to login
Gets sent over to Identity Server 4 (IS4) and types in credentials
IS4 looks at my database that contains the ASP.NET Core Identity tables and validates the user
If all is good then it goes to IS4 tables and adds whatever it needs.
Sends back the user and tokens.
Now Reactjs can hit my web api and get other data from it.
My problem is what happens if the user is registering.
A user comes to my reactjs site and wants to register
User see my html/reactjs form and fills it out
Information is sent to webapi and stored in the ASP.NET Core Identity tables
Now what, do I have to send the user to my IS4 where they now have to log in? That just seems bad.
Also in this scenario what would stop someone from just spamming my api with registrations, since it is an open end point.

Who stores the username/password?
The beauty of Identity Server is that it doesn't care. You may use a database, a text file or Active Directory. You are responsible to choose whichever is most appropriate for your use case.
IMO, using ASP.NET Core Identity to manage the CRUD of users (which Identity Server already provides bindings and you can see how it's done in their demos) is the easiest way. If you have used ASP.NET Identity before, what you need to add is just
services.AddIdentityServer().AddAspNetIdentity<YourUserClass>();
ASP.NET Core Identity is an optional ASP.NET Core membership library from Microsoft that allows you to register and login users using both internal (Windows, Database) methods and external (OAuth/OpenId Connect - Faceboook, Google, Microsoft account, etc) systems. Microsoft provides a lot of information in the Microsoft Docs site, look here for an introduction.
In this case, think of ASP.NET Core Identity as a medium to providing Identity Server information of your users, roles and claims. You create users through Identity but the actual authentication and authorization is done by Identity Server.
You could expose REST endpoints for your React application to be able to register (and probably modify?) your users and their roles. For log-in, the ideal way would be to make the React application contact the Identity Server through the implicit flow.
Ask yourself, however, whether Identity Server is needed in your scenario. If the only application being secured by that Identity Server is the React application, it is most likely a waste and you'd be fine using ASP.NET Core Identity on its own.
Regarding your edit, the first flow is almost ok, but:
If all is good then it goes to IS4 tables and adds whatever it needs.
This step does not happen. If all is good, IS4 generates the token and returns it.
Sends back the user and tokens.
IS4, as any OAuth 2.0 or OpenID Connect solution, only returns to the client the generated token. The token itself contains information about the user, though.
Do keep in mind that ASP.NET Core Identity would be hosted in the same application as IS4, and they can easily (if you want) share the same database.
For the second flow, it's pretty easy to log the user in if Identity is in the same application as IS4 (in fact, this is quite common). If they are separated, you'd likely have to make the React application call IS4 as normally.
I said that you could use the same database for Identity and IS4 because, to me at least, it makes sense to keep all the security stuff together (which would be applications and users).
Users information is given by Identity in the Users table, their "profile" data can be stored as Claims (again, using Identity to persist them) and their authorization information either as Claims or as Roles. IS4 will map all roles of a user to a single "roles" claim, so it's your choice there.
As you can see, Identity serves as a store for IS4. Identity creates and maintains the data, IS4 consumes it.
Regarding the login/register process, it's quite common to have these in the IS4 application so that all clients use the same views and the users get the same UX across applications. It's pretty easy to even provide different views for login/register based on client id if need be.
Always remember that every single application that wants to contact your IS4 needs to be registered in the IS4 database as a Client and it needs to be enabled. If an application uses a ClientId from an URL different than the one stored in the database, the request is denied to enhance security when a ClientId is compromised or is publicly known, as it's the case for JavaScript web clients.

Related

How to add some alternative authentication with token on Asp.Net Core?

We have built some Asp.Net Core web API, with the authentication/authorization built on top of Asp.Net Core identy, with some JWT token exchange for our angular frontend. Basically, the users can login with username+password, this provide them a JWT with a short validity that the frontend regularly refresh. If the token is not valid anymore, the user will have to login again.
This part works great.
Now, we have to add another concept, a bit like on Azure Devop, we need to add "agent", those are not users, they will just need to be authenticated, in a slightly different way:
They will run on unnattended(locked) computers
They will be configured once and then run forever
Each agent should NOT be considered as a user. They should not be stored as such(or at least provide a way to distinguish them)
Those agent should only have some kind of token/private key to authenticate themself, that doesn't expire. This method of authentication should not be allowed to other users
So based on this:
Is this something that already exists, or have this pattern a name?
Is there a way to achieve this through Asp.Net Core identity or am I better off ?
Any link or lead on how to implement in parallel of an existing auth would be highly appreciated.

client specific claims identity server4 using asp.net core identity

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.

Abstracting out the OWIN authentication in an MVC web application

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.

Single-sign-on: Which direction should I go?

I have a SaaS web application that caters to multiple education institutions. All clients are hosted in the same application/database. The application is currently written in C# for ASP.Net 4 Web Forms.
Currently my application uses a local/native database for user authentication/authorization.
Our clients are asking us to support single-sign-on where the client is the authentication provider and my application the consumer.
The problem is that the clients are asking for SSO via different protocols/mechanisms like Shibboleth and OpenID Connect. This means I need-to/should create a solution that works with all of these or that is at least extensible.
I came across Thinktecture's IdentityServer, which I think can abstract the various SSO mechanisms used by my clients and return to my app a claims based identity token that my app understands.
I'm struggling a lot with this concept though. Does this mean that my app redirects all authentication requests to the IdentityServer, lets IdentityServer handle the back and forth of say OpenID Connect, and then receives a token back from IdentityServer with the information I need about the user? How does the identity server know the realm of the user (i.e. so it knows which client auth provider to send the user to)? Does the IdentityServer need to validate the existence of the user in my app's local/native database? Can the IdentityServer handle both SSO and local logins?
Is a separate identity server the way to go? It seems like it would be, allowing my app to integrate with one point (the identity server). But, there's not a lot of documentation out there on Thinktecture's IdentityServer other than how to configure it. ADFS may provide a similar solution, but most examples out there speak to ADFS and Azure.
Lastly, I'm assuming that I'll still maintain local/native authorization data about each user as the 3rd party authentication provider can't possibly know the specific authorization needs of my application.
Any thoughts or suggestions out there?
Does this mean that my app redirects all authentication requests to the IdentityServer, lets IdentityServer handle the back and forth of say OpenID Connect, and then receives a token back from IdentityServer with the information I need about the user?
Basically YES. But it depends on how you set it up. Your page could call Authentication provider of the client if you have only one client or one authentication provider. Or you could set up your local IdentityServer (more extensible IMHO) and configure authentication provider of your client as another IdP (identity provider).
How does the identity server know the realm of the user (i.e. so it knows which client auth provider to send the user to)?
If you go with the second option then your app will redirect to IdentityServer and based on home realm it will be automatically redirected to IdP. If no home realm is specified by your application then IdentityServer will show all configured IdPs and user chooses what IdP to authenticate at.
Does the IdentityServer need to validate the existence of the user in my app's local/native database?
It depends on you. If you wish to verify the existence of the user in your local database then you may do so by extending IdentityServer.
Can the IdentityServer handle both SSO and local logins?
Yes, it can.
Is a separate identity server the way to go? It seems like it would be, allowing my app to integrate with one point (the identity server).
You can always use IdentityServer and integrate it in your local application. Or you can use Shiboleth as your local authentication provider. Both are implementing standards like WS-Federation, WS-Trust or OpenId and both are open source so you can extend/modify it to your liking.
But, there's not a lot of documentation out there on Thinktecture's IdentityServer other than how to configure it.
I can't really say how much documentation is there. But if you wish, NDC Oslo 2014 will feature 2 days of Pre-Conference Workshops where Dominick Baier and Brock Allen (authors of IdentityServer) will teach you everything you want to know.

Membership System for Website and Mobile Apps

I am currently working on a project that will have a website and apps for mobile devices. I am going to need a way to let users login to my site to view certain areas. I know I will need to build a WCF RESTful service but I am stuck on how to proceed with creating the users. I was originally going to use the built in .NET Membership but the more I read about it the worst it sounded if I had a lot of users. I then was thinking of building a new provider which would give me all the functionality of the built in .NET Membership but I would have more control over everything. The last idea was to build a whole membership system, but I was worried I would loose the functionality of the built in .NET Membership system. I am basically just looking for someone to point me in the right direction and explain why.
Right now I am thinking the best way to handle this is going to be to build a whole membership system. I am thinking I am going to have my data access all through a WCF in the backend that my website would call and the RESTful service would call. I am not aware of a way right now that I can authenticate a users username and password through a WCF.
Thanks for all your input.
We do this very thing in several of our projects, here is a summary of how we accomplish it. Keep in mind it's only one method, and we have also had success writing our own membership provider.
We have 3 main projects:
Data.project - class library
WebApp.project - MVC Application
API.project - WCF service
We use the built in .NET membership provider as it exists out of the box. This gives us the basic registration, password changes, role management, and the easy controller based role permission and access control in our MVC and API projects.
The default membership provider will use its own tables to store the user data.
We then create our own User and Profile tables and data structure with a foreign key back to the .NET membershipId of the user. This gives us the flexibility to do all of the application specific things we need to do with a user profile while still giving us access to the default provider.
Authentication is straight forward in the MVC project, you can now use the .NET Membership methods to authenticate by username and password:
if(Membership.ValidateUser(username,password)){
FormsAuthentication.SetAuthCookie(username,password);
}
For the WCF project you do not have the luxury of FormsAuthentication, but you can still use the default membership provider to validate the users credentials.
How you handle authentication after that is up to you and your project, but for basic needs we generally go with an authentication token that is returned by the WCF service after validation. This token is then included with each WCF request to prove they have been validated, usually in the request headers.
For WCF we base 64 encode the username and password when submitting the credentials to the server, then if successful we pass back the auth token:
string decoded = System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(Authmodel));
//convert your string into your authentication model here then
if(Membership.ValidateUser(model.user,model.pass))
{
//return new authentication token
}
We also include additional logic during registration that build out our proprietary user and profile tables at that time, this is handled in the data project so that both the WCF and MVC may access it.
Additionally, the data project handles the linking between our user and profile tables and that of the .NET Membership provider tables so the information can be accessed by both applications.
I realize that is all quite vague, but maybe it can help you think of one option for handling authentication in a unified way. If you have questions about a specific portion let me know and I hope this information is useful for you.

Categories

Resources