.NET Core Identity Server 4 Authentication VS Identity Authentication - c#

I'm trying to understand the proper way to do authentication in ASP.NET Core. I've looked at several Resource (Most of which are out dated).
Simple-Implementation-Of-Microsoft-Identity
Introduction to Authentication with ASP.Core
MSDNs Introduction to Identity
Some people provide altenative solutions stating to use a cloud based solution such as Azure AD, or to Use IdentityServer4 and host my own Token Server.
In Older version Of .Net one of the simpler forms of authentication would be to create an Custom Iprinciple and store additional authentication user data inside.
public interface ICustomPrincipal : System.Security.Principal.IPrincipal
{
string FirstName { get; set; }
string LastName { get; set; }
}
public class CustomPrincipal : ICustomPrincipal
{
public IIdentity Identity { get; private set; }
public CustomPrincipal(string username)
{
this.Identity = new GenericIdentity(username);
}
public bool IsInRole(string role)
{
return Identity != null && Identity.IsAuthenticated &&
!string.IsNullOrWhiteSpace(role) && Roles.IsUserInRole(Identity.Name, role);
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + " " + LastName; } }
}
public class CustomPrincipalSerializedModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then you would Serialize your data into a cookie and return it back to the client.
public void CreateAuthenticationTicket(string username) {
var authUser = Repository.Find(u => u.Username == username);
CustomPrincipalSerializedModel serializeModel = new CustomPrincipalSerializedModel();
serializeModel.FirstName = authUser.FirstName;
serializeModel.LastName = authUser.LastName;
JavaScriptSerializer serializer = new JavaScriptSerializer();
string userData = serializer.Serialize(serializeModel);
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,username,DateTime.Now,DateTime.Now.AddHours(8),false,userData);
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
Response.Cookies.Add(faCookie);
}
My questions are:
How can I authenticate similar to the way done in previous version's of .Net does the old way still work or is there a newer version.
What are the pros and cons of using your own token server verses creating your own custom principle?
When using a cloud based solution or a separate Token server how would you Integrate that with your current application, would I would still need a users table in my application how would you associate the two?
Being that there are so many different solutions how can I create an enterprise application, to allow Login through Gmail/Facebook while still being able to expand to other SSO's
What are some simple implementations of these technologies?

TL;DR
IdentityServer = token encryption and validation services via OAuth 2.0/OpenId-Connect
ASP.NET Identity = current Identity Management strategy in ASP.NET
How can I authenticate similar to the way done in previous version's of .Net does the old way still work or is there a newer version.
I see no reason why you couldn't achieve the old way in ASP.NET Core, but in general, that strategy was replaced with ASP.NET Identity, and ASP.NET Identity is alive and well in ASP.NET Core.
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity
ASP.NET Identity uses a backing store like SQL Server to hold user information like username, password (hashed), email, phone and easily be extended to hold FirstName, LastName or whatever else. So, there really no reason to encrypt user information into a cookie and pass it back and forth from client to server. It supports notions like user claims, user tokens, user roles, and external logins. Here are the entities in ASP.NET Identity:
AspNetUsers
AspNetUserRoles
AspNetUserClaims
AspNetUserLogins (for linking external identity providers, like Google, AAD)
AspNetUserTokens (for storing things like access_tokens and refresh_tokens amassed by the user)
What are the pros and cons of using your own token server verses creating your own custom principle?
A token server would be a system that generates a simple data structure containing Authorization and/or Authentication information. Authorization usually takes the for of a token named access_token. This would be the "keys to the house", so to speak, letting you through the doorway and into the residence of a protected resource, usually a web api. For Authentication, the id_token contains a unique identifier for a user/person. While it is common to put such an identifier in the access_token, there is now a dedicated protocol for doing that: OpenID-Connect.
The reason to have your own Security Token Service (STS), would to be to safeguard your information assets, via cryptography, and control which clients (applications) can access those resources. Furthermore, the standards for identity controls now exist in OpenID-Connect specifications. IdentityServer is an example of a OAuth 2.0 Authorization Server combined with an OpenID-Connect Authentication server.
But none of this is necessary if you just want a user table in your application. You don't need a token server- just use ASP.NET Identity. ASP.NET Identity maps your User to a ClaimsIdentity object on the server- no need for a custom IPrincipal class.
When using a cloud based solution or a separate Token server how would you Integrate that with your current application, would I would still need a users table in my application how would you associate the two?
See these tutorials for integrating separate identity solutions with an application:
https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html
https://auth0.com/docs/quickstart/webapp/aspnet-core
At a minimum you would need a two column table mapping the username to the external provider's user identifier. This is what the AspNetUserLogins table does in ASP.NET Identity. The rows in that table however are dependent on the being a User record in AspNetUsers.
ASP.NET Identity supports external providers like Google, Microsoft, Facebook, any OpenID-Connect provider, Azure AD are already there. (Google and Microsoft have already implemented the OpenID-Connect protocol so you don't need their custom integration packages either, like this one, for example). Also, ADFS is not yet available on ASP.NET Core Identity.
See this doc to get started with external providers in ASP.NET Identity:
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/
Being that there are so many different solutions how can I create an enterprise application, to allow Login through Gmail/Facebook while still being able to expand to other SSO's
As explained above, ASP.NET Identity already does this. It's fairly easy to create an "External Providers" table and data drive your external login process. So when a new "SSO" comes along, just add a new row with the properties like the provider's url, the client id and secret they give you. ASP.NET Identity already has the UI built in there Visual Studio templates, but see Social Login for cooler buttons.
Summary
If you just need a users table with password sign in capabilities and a user profile, then ASP.NET Identity is perfect. No need to involve external authorities. But, if have many applications needing to access many apis, then an independent authority to secure and validate identity and access tokens makes sense. IdentityServer is a good fit, or see openiddict-core, or Auth0 for a cloud solution.
My apologies is this isn't hitting the mark or if it is too introductory. Please feel free to interact to get to the bulls-eye you are looking for.
Addendum: Cookie Authentication
To do bare bones authentication with cookies, follow these steps. But, to my knowledge a custom claims principal is not supported. To achieve the same effect, utilize the Claims list of the ClaimPrincipal object.
Create a new ASP.NET Core 1.1 Web Application in Visual Studio 2015/2017 choosing "No Authentication" in the dialog. Then add package:
Microsoft.AspNetCore.Authentication.Cookies
Under the Configure method in Startup.cs place this (before app.UseMvc):
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "MyCookieMiddlewareInstance",
LoginPath = new PathString("/Controller/Login/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
Then build a login ui and post the html Form to an Action Method like this:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(String username, String password, String returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// check user's password hash in database
// retrieve user info
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, username),
new Claim("FirstName", "Alice"),
new Claim("LastName", "Smith")
};
var identity = new ClaimsIdentity(claims, "Password");
var principal = new ClaimsPrincipal(identity);
await HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance", principal);
return RedirectToLocal(returnUrl);
}
ModelState.AddModelError(String.Empty, "Invalid login attempt.");
return View();
}
The HttpContext.User object should have your custom claims and are easily retrievable the List collection of the ClaimPrincipal.
I hope this suffices, as a full Solution/Project seems a bit much for a StackOverflow post.

TL;DR
I would really like to Show A Full posting on how to properly implement IdentityServer4 but I tried to fit All of the Text in but it was beyond the limit of what StackOverflow Accepts so instead I will right some tips and things I've learned.
What are the Benefits of using a Token Server Vs ASP Identity?
A token server, has a lot of benefit's but it isn't right for everyone. If you are implementing an enterprise like solution, where you want multiple client to be able to login, Token server is your best bet, but if you just making a simple website that want to support External Logins, You can get Away With ASP Identity and some Middleware.
Identity Server 4 Tips
Identity server 4 is pretty well documented compared to a lot of other frameworks I've seen but it's hard to start from scratch and see the whole picture.
My first mistak was trying to use OAuth as authentication, Yes, there are ways to do so but OAuth is for Authorization not authentication, if you want to Authenticate use OpenIdConnect (OIDC)
In my case I wanted to create A javascript client, who connects to a web api.
I looked at a lot of the solutions, but initially I tried to use the the webapi to call the Authenticate against Identity Server and was just going to have that token persist because it was verified against the server. That flow potentially can work but It has a lot of flaws.
Finally the proper flow when I found the Javascript Client sample I got the right flow. You Client logs in, and sets a token. Then you have your web api consume the OIdc Client, which will verify your access token against IdentityServer.
Connecting to Stores and Migrations
I had a lot of a few misconceptions with migrations at first. I was under the impression that running a migration Generated the SQL from the dll internally, instead of using you're configured Context to figure out how to create the SQL.
There are two syntaxes for Migrations knowing which one your computer uses is important:
dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext
Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext
I think the parameter after the Migration is the name, why you need a name I'm not sure, the ApplicationDbContext is a Code-First DbContext in which you want to create.
Migrations use some auto-magic to find you're Connection string from how your start up is configured, I just assumed it used a connection from the Server Explorer.
If you have multiple projects make sure you have the project with the ApplicationDbContext set as your start up.
There is a lot of moving parts when Implementing Authorization and Authentication, Hopefully, this post helps someone. The easiest way to full understand authentications is to pick apart their examples to piece everything together and make sure your read the documentation

ASP.NET Identity - this is the build in a way to authenticate your application whether it is Bearer or Basic Authentication, It gives us the readymade code to perform User registration, login, change the password and all.
Now consider we have 10 different applications and it is not feasible to do the same thing in all 10 apps. that very fragile and very bad practice.
to resolve this issue what we can able to do is centralize our Authentication and authorization so whenever any change with this will not affect all our 10 apps.
The identity server provides you the capability to do the same. we can create one sample web app which just used as Identity service and it will validate your user and provide s some JWT access token.

I have always used the built in ASP.NET Identity (and previously Membership) authorisation/authentication, I have implemented Auth0 recently (https://auth0.com) and recommend this as something else to try.

Social logins are not hard to implement with Identity, but there is some initial setup involved and sometimes the steps you find online in the docs are not identical, usually you can find help for that under the developers section of the platform you are trying to setup the social logins for. Identity is the replacement of the old membership functionality found in legacy versions of the .net framework.What I have found surprising is that edge use cases, like passing a jwt token you already have to a web api are not covered anywhere in the examples online even on pluralsight, I am sure you don't need your own token authority to do this but I have not found a single example on how to pass data in a get or post that isn't dealing with a self-hosted server.

Related

Application and User Authentication using ASP.NET Core

Can anyone point me to some good documentation or provide good information on the best way to implement authentication and authorisation for an ASP.NET Core REST API.I need to authenticating and authorising the app first and then authenticate and authorise the user.
Ideally I want to be able restrict the controller method that an authenticated app and/or user can access.
I am thinking of using AspNet.Security.OpenIdConnect.Serverenter for the App authentication but I am not sure then how best to perform the user authentication. Maybe reuse the OpenIdConnect authentication on a different endpoint for users with a different header to contain the user token.
Once authenticated I am thinking of just using roles base security to restrict which controllers methods can be accessed.
Is this the correct route to solving this problem?
This is actually a tougher question that that it may seem because the type of clients (software clients) that are using the api seem to drive what kind of auth* is needed. For example, in a web application, where the web application needs auth*, then Asp.Net Identity would work with either a token or a cookie. However, if other clients are going to consume the provided services (mobile apps, WUP apps, then it may be easier to implement using token authentication . When I had this problem, I ran into the issue that I had a knowledge gap because I didn't really understand OAuth. I had to get back to basics.
https://alexbilbie.com/guide-to-oauth-2-grants/
https://www.pluralsight.com/courses/oauth2-json-web-tokens-openid-connect-introduction
Most of the tutorials around Asp.Net Identity "Seem" to be geared towards web clients. Although it is possible to find those that are not. With the introduction of asp.net core, the syntax has changed and many of the old tutorials that show combining cookie and token authentication are no longer applicable. Additionally, Web Api is not longer a separated from other project types in Visual Studio making the change even more pronounced. Here are some older tutorials.
http://satvasolutions.com/combine-asp-net-identity-web-api-and-mvc-best-in-a-single-web-app/
http://blog.iteedee.com/2014/03/asp-net-identity-2-0-cookie-token-authentication/
Combine the use of authentication both for MVC pages and for Web API pages?
IdentityServer is a completely valid solution, works with both client credential and Resource owner credentials grant (user,password) and Brock Allen has usually been very responsive in SO under the tag
https://stackoverflow.com/questions/tagged/identityserver4
or on the github site under issues labeled as questions
https://github.com/IdentityServer/IdentityServer4/issues
With identity server, Once again, I had to go back to basics and work through the tutorials to get an understanding of how this would work in my project.
https://identityserver4.readthedocs.io/en/release/intro/big_picture.html
As Brock quickly pointed out to me in another post, asp.net ef identity is a user store and good to use with the resource owner credentials workflow.
For authentication you can use ASP.NET Core Identity that will use the Microsoft.AspNetCore.Identity.EntityFrameworkCore package, which will persist the identity data and schema to SQL Server using Entity Framework Core.
For authorization you can use Role Based Authorization that uses the Microsoft.AspNetCore.Authorization package.
You can also checkout this video for an overview on ASP.NET Core Authorization
I couldn't find any good documentation on this, however I had to achieve the same thing so I coded the rest api myself by modifying the actions in the standard ASP.NET authentication template to REST API equivalents.
For example here is how I worked the login action:
// POST: /Account/Login
[HttpPost("[action]")]
[AllowAnonymous]
public async Task<ReturnValue<ApplicationUser>> Login([FromBody] loginModel login)
{
if (ModelState.IsValid)
{
ApplicationUser user = await _userManager.FindByEmailAsync(login.email);
if (user == null)
{
return new ReturnValue<ApplicationUser>(false, "Login failed, check username and password.", null);
}
// else if (user.EmailConfirmed == false)
// {
// return new ReturnValue<ApplicationUser>(true, "Confirm email address.", null, user);
// }
else
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(user, login.password, (bool)login.rememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return new ReturnValue<ApplicationUser>(true, user);
}
//if (result.RequiresTwoFactor)
//{
// return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
//}
if (result.IsLockedOut)
{
return new ReturnValue<ApplicationUser>(false, "The account is locked out.", null);
}
}
}
else
{
string message = string.Join("; ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));
return new ReturnValue<ApplicationUser>(false, "Invalid login attempt: " + message, null);
}
// If we got this far, something failed in the model.
return new ReturnValue<ApplicationUser>(false, "Login failed.", null);
}
If you call the API from a javascript within a browser the cookies will be loaded and you should be able to make further authorised calls to the API, if you're calling from another type of client, you will want to ensure the CookieContainer is retained for authorized calls.
From this point you can authorize your REST API controllers using [Authorize] decorator through the standard Microsoft libraries: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity
Good luck.
Here it is:
A workshop for moving through the various new pieces in ASP.NET Core Authorization:
https://blogs.msdn.microsoft.com/webdev/2016/03/15/get-started-with-asp-net-core-authorization-part-1-of-2/
https://github.com/blowdart/AspNetAuthorizationWorkshop
Please refer following links.
For Asp.net Core
https://stormpath.com/blog/token-authentication-asp-net-core
For API
https://stormpath.com/blog/rest-api-mobile-dotnet-core

How to use ASP.net 5 Identity in web API application? User authentication based on tokens. Mobile apps

Assuming that I currently have a newly created project based on Visual Studio 2015 "WebApp" template with Individual Accounts authentication, I use Microsoft.AspNet.Authentication package and I can't always rely on cookies, because my web API should also target mobile apps:
How can I add authentication to my web API? I'm especially interested in token based authentication.
You can use basic http authentication or implement a similar one with a token or ticket passed through http headers.
Implement custom AuthorizeAttribute in your web api project. In IsAuthorized(HttpActionContext actionContext) overload you can check the authorization scheme and authorization header and then you can connect to your sessions provider and check if the user has an active session.
You must pass the login token in the authorization header, so if the token is missing that means there is no active user.
So when you login you must create and encrypt the token on successful login. Then pass this token with each request to the server.
This blog contains more information about using AuthorizeAttribute: http://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-customizing-authentication-and-authorization-the-right-way
You can make separate table in db for storing authentication detail (AuthKey, UserID, CreatedDate, ExpiredDate, IsExpired) and make functions like CheckAuthorizationKey(string authKey), ExtendAuthorization(string authKey), ExpireAuthorization(string authKey){}
and call that functions for checking the authorization as below sample code.
public ServiceResult<LoginModel> Login(string auth_key)
{
var service = new ServiceResult<LoginModel>();
LoginModel user = new LoginModel();
if (AuthKey.CheckAuthorizationKey(auth_key) == false)
{
service.message = TemplateCodes.GetMessage(TemplateCodes.UnAuthorize, null, db);
service.status = ServiceStatus.authorization_failed;
return service;
}

Using Windows Domain accounts AND application-managed accounts

It's easy to create an ASP.NET MVC application that authenticates based on windows domain user. It's also easy to create one that uses individual accounts stored using Entity Framework. In fact, there are project templates for both.
But I want to utilize BOTH kinds of authentication in the same application. I tried to combine the code from both project templates. I have a problem in Startup.Auth.cs.
// from "Individual Accounts" template
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
The existence of cookie authentication owin middleware seems to cause domain identities to become un-authenticated. If I take this line out, the domain authentication works. But without it, I can't seem to support individual user accounts.
I've downloaded the katana project source code and examined CookieAuthenticationHandler.cs, but I don't quite understand how it works in the context of an OWIN pipeline.
How can I use the ASP.net identity framework to allow my application to authenticate users from the windows domain OR an application-specific user store?
The simplest approach is to have 2 different presentation Projects only for Authentication/Authorization.
This has the advantage of leaning on existing framework and standard configuration.
From there, you decide to either
create an AD user for every internet user, or
create a DB/Internet user for every AD user.
Creating an Identity user for each AD user is easier to implement further. Then the same cookies and filters can exist in the entire app.
In that case you can either
use subdomain(s) for your app
AD Authentiction Project can have the singular purpose of Authentication / Authorization, then the Web App can represent the rest of your app.
Alternatively, If you want a truly Unified Solution, use MohammadYounes/Owin-MixedAuth
MohammadYounes/Owin-MixedAuth
Install-Package OWIN-MixedAuth
In Web.config
<location path="MixedAuth">
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
In in Startup.Auth.cs
app.UseMixedAuth(cookieOptions);
:
:
How it works:
The handler uses ApplyResponseChallengeAsync to confirm the request is a 401 challenge. If so, it redirects to the callback path to request authentication from IIS which is configured to query the AD.
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(
Options.AuthenticationType, Options.AuthenticationMode);
A 401 challenge is caused by an unauthorized users attempting to use a resource that requires Authentication
The handler uses InvokeAsync to check if a request is coming from a callback path (IIS) and then calls AuthenticateCoreAsync
protected async override System.Threading.Tasks.Task<AuthenticationTicket>
AuthenticateCoreAsync()
{
AuthenticationProperties properties = UnpackStateParameter(Request.Query);
if (properties != null)
{
var logonUserIdentity = Options.Provider.GetLogonUserIdentity(Context);
if (logonUserIdentity.AuthenticationType != Options.CookieOptions.AuthenticationType
&& logonUserIdentity.IsAuthenticated)
{
AddCookieBackIfExists();
ClaimsIdentity claimsIdentity = new ClaimsIdentity(
logonUserIdentity.Claims, Options.SignInAsAuthenticationType);
// ExternalLoginInfo GetExternalLoginInfo(AuthenticateResult result)
claimsIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier,
logonUserIdentity.User.Value, null, Options.AuthenticationType));
//could grab email from AD and add it to the claims list.
var ticket = new AuthenticationTicket(claimsIdentity, properties);
var context = new MixedAuthAuthenticatedContext(
Context,
claimsIdentity,
properties,
Options.AccessTokenFormat.Protect(ticket));
await Options.Provider.Authenticated(context);
return ticket;
}
}
return new AuthenticationTicket(null, properties);
}
AuthenticateCoreAsync uses AddCookieBackIfExists to read the claims cookie created by AD and creates it's own Claims based.
AD users are provided a Claims based Cookie identical to Web Users. AD is now like any other 3rd party authenticator (Google, FB, LinkedIN)
It's for this reason that I haven't been able to use pre-baked solutions for authentication. In our project, the passing years (and agile approach) have left us with 4 different ways to authenticate which is annoying, but we support all legacy versions of apps in the field so we have to preserve it all (at least for now).
I ended up creating a factory that figures out the authentication mechanism (through any of several means such as token format, presence of some other thing) and then returns a wrapper that carries the logic for validating that authentication method and setting the principal.
This gets kicked off in a custom HTTP module so that the principal is built and authenticated before the request gets to the controller. In your case, windows Auth would be the final fallback, I think. In our Web API application, we took the same approach but through a delegating handler instead of HTTP module. It's a type of local token federation, you could say. The current implementation allows us to add or modify any validation procedure, or add any other token format; in the end, the user ends up with a proper identity or gets denied. Only took a few days to implement.
It seems to me the best answer to this question is to use an authentication and authorization framework. There are plenty to choose from (both commercial and free). You could, of course, write your own but I would discourage it. Lots of very smart people get this wrong.
I would take a look at IdentityServer3. It's certainly not the only solution but its a pretty good authentication and authorization framework. It's open source and pretty easy to get up and running in a hurry. Your use case is a common one and you will find some very useful information at the link above. Clean separation between authorization and authentication, social authentication options, easy to work with json web tokens that encapsulate user claims, etc.
How it can help you
IdentityServer3 allows you to configure Identity Providers to handle authentication and there are plenty of extension points that will allow you to implement a chain of responsibility that can handle both of your scenarios. From the docs:
IdentityServer supports authentication using external identity providers. The external authentication mechanism must be encapsulated in a Katana authentication middleware.
Katana itself ships with middleware for Google, Facebook, Twitter, Microsoft Accounts, WS-Federation and OpenID Connect - but there are also community developed middlewares (including Yahoo, LinkedIn, and SAML2p).
To configure the middleware for the external providers, add a method to your project that accepts an IAppBuilder and a string as parameters.
IdentityServer3 supports AD as an identity providor via a browser login window and will support a more programmatic implementation via a custom grant. You can also take a look here for some more information on IdentityServer3 and AD authentication.
It will support windows authentication as well and you can take a look at here for information and examples on implementing that.
There is a pretty good getting started example here as well.
With the right configuration IdentityServer3 can handle your requirements. You will need to implement your own authentication providers and plug them into the framework but there isn't much more to it than that. As for authorization goes, there are plenty of options there as well.

ASP.NET MVC 3 with service client as database access layer

I am writing an MVC 3 application, which doens't use the classic approach of accesing the database using the Entity Framework. Instead I have another application combined of WCF Services, which are used to manage the database access. Now I want to used those services in my MVC application, as the database access. This part is simple. The point where it gets harder is managing authentication and authorization in this scenario.
For authentication and authorization, I have created custom membership and role providers. I have implemented the necessary methods, but here I have ran into the problem. My services require username and password, to get the list of user roles.
I am wondering how can I store the username and password provided by user on logon, somewhere in the backed of my application, to make sure it is save, and to have the possability to use it in my role provider?
Is session the right choice for this? If so, how can I access user's session in my role provider?
You should never use passwords, use password hashes instead (properly salted, of course). So, now you can pass username and password hash to your role provider which in turn will pass that to your wcf which will grant or not grant the necessary roles.
Update
IsUserInRole method should look like so:
public class WcfRoleProvider: RoleProvider
{
public bool IsUserInRole(string username, roleName)
{
bool result = false;
using(WcfRoleService roleService = new WcfRoleService())
{
result = roleService.IsUserInRole(username, roleName);
}
return result;
}
}

Adding a WIF STS service to existing projects

We have several websites that are set up in the following fashion:
Site1.Web - ASP.NET Web Project (.NET 4.0, WebForms)
Common.Core - Class Library Project (all db interaction)
The web project appears once for each site while the Common.Core project is shared among all sites. We have a login form in the web project that, in order to authenticate, calls into the class library. It would call off a code similar to below:
Common.Core.Authenticate auth = new Common.Core.Authenticate(conStr);
bool validLogin = auth.ValidateUser(userName, password);
if(validLogin)
{
Common.Core.User = auth.GetCurrentUser();
}
The higher ups are pushing for a middle layer service/app tier and want to use a more elegant solution to handle single sign on. Therefore, the decision has been made to use a WIF service to handle the login and validation. Furthermore, we want to try to minimize the code that has to change in each web project, i.e. try to keep as many changes as possible in Common.Core.
I have seen a few samples that show how to add an STS reference to a web project. This would work well in a scenario where the user validation isn't factored into another project like Core.Common. However, in our scenario, how could we handle validation while still going through the common class library?
Ideally, I would like to add an STS reference to the Core.Common class library and replace the direct db logic (auth.ValidateUser above) with a call to an STS service. However, is it even possible to do that? Does the request have to initiate in the web project? If so, is the STS reference required in both places?
Any tutorials or resources which follow the same web project -> class library -> STS service path would be greatly appreciated.
I would also recommend using WIF :-)
In a claims based scenario the authentication process is "reversed". Your app will not call anyone, it will receive the needed information from a trusted source (the STS).
The "STS Reference" is not a library reference. It's a logical connection between your app and the trusted source of security tokens. A token is the artifact your app will use to decide what to do with the user request.
I'd agree with #nzpcmad that it is likely you could entirely remove the calls to you Common.Core library. It might be useful to see what else can you do with it. What does the Common.Core.User object give you?
If it is just properties of a user (e.g. name, e-mail, roles, etc) it is very likely you could just create a new version that simply wraps the IPrincipal supplied byt WIF (a ClaimsPrincipal).
For example (approx. no error handling, pseudo-code):
public User CurrentUser()
{
var user = new User();
var cu = HttpContext.Current.User as IClaimsPrincipal;
user.Name = cu.Name;
user.eMail = (cu.Identity as IClaimsIdentity).Claims.First( c=> c.ClaimType = "eMail" ).Value;
return user;
}
As #nzpcmad says, you can use ADFS or some other STS. Your apps would not care.
One way to achieve this is to FedUtil the ASP.NET project with an instance of ADFS. Essentially, authentication is now "outsourced" and you can simply remove the call to the core library from your app. ADFS is then setup to return whatever attributes the program needs for authorisation as claims. You may need to transform these claims attributes to whatever attributes are passed back to the common core in subsequent calls.
Or you could make the common core "claims aware" in the sense that it now recognizes "claims attributes" as opposed to "common core" attributes. This involves using different .NET classes - no hookup to ADFS is required.
Word of warning - your authentication seems to be all DB related. ADFS cannot authenticate against a DB. It can only authenticate against an instance of AD in the domain that ADFS is installed in (or other AD if trust relationship between AD).
If you want to authenticate against a DB you need a custom STS which is then federated with ADFS. See here: Identity Server.

Categories