ASP.NET MVC 5 Authentication Breakdown
In my previous post, "ASP.NET MVC 5 Authentication Breakdown", I broke down all the parts of the new ASP.NET MVC authentication scheme. That's great, but I didn't have a working example that you, a curious developer, could download and play around with. So I set out today to figure out what the bare minimum code needed was. Fiddling around, I was able to get OWIN powered authentication into an ASP.NET MVC app. Follow this guid to get it into your application as well.
No fluff, just the real stuff
TL;DR go to https://github.com/khalidabuhakmeh/SimplestAuthMvc5 to clone the code.
NuGet Packages
You will need the following packages from NuGet in your presumably empty ASP.NET MVC project.
- Microsoft.AspNet.Identity.Core
- Microsoft.AspNet.Identity.Owin
- ASP.NET MVC 5
- Microsoft.Owin.Host.SystemWeb
- Microsoft.Owin.Security
- Microsoft.Owin.Security.Cookies
- Microsoft.Owin.Security.OAuth
- Owin
Notice how the majority of them center around Owin.
Start Up Classes
OWIN follows of a convention of needing a class called StartUp in your application. I followed the standard pattern of using a partial class found in the default ASP.NET MVC 5 bloated template.
Here is the main code file:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(SimplestAuth.Startup))]
namespace SimplestAuth
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuthentication(app);
}
}
}
Followed by the implementation of the ConfigureAuthentication method:
public partial class Startup
{
public void ConfigureAuthentication(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Login")
});
}
}
Web.Config settings
OWIN doesn't use the standard forms authentication that I've grown to love, it implements something completely different. For that reason, I have to remember this snippet of config.
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<modules>
<remove name="FormsAuthenticationModule" />
</modules>
</system.webServer>
The FormsAuthenticationModule is removed, and additionally the authentication mode is set to None. Although, I know the site will have authentication; that authentication will be handled by OWIN.
Authentication Controller
Now it's business time! Now we just need a controller to authentication and create the cookie for authentication. We'll also implement log out, because sometimes our users want to leave (not sure why though :P).
Note: I'm using AttributeRouting here. Giving it a try, but I love Restful Routing.
public class AuthenticationController : Controller
{
IAuthenticationManager Authentication
{
get { return HttpContext.GetOwinContext().Authentication; }
}
[GET("login")]
public ActionResult Show()
{
return View();
}
[POST("login")]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel input)
{
if (ModelState.IsValid)
{
if (input.HasValidUsernameAndPassword)
{
var identity = new ClaimsIdentity(new [] {
new Claim(ClaimTypes.Name, input.Username),
},
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name, ClaimTypes.Role);
// if you want roles, just add as many as you want here (for loop maybe?)
identity.AddClaim(new Claim(ClaimTypes.Role, "guest"));
// tell OWIN the identity provider, optional
// identity.AddClaim(new Claim(IdentityProvider, "Simplest Auth"));
Authentication.SignIn(new AuthenticationProperties
{
IsPersistent = input.RememberMe
}, identity);
return RedirectToAction("index", "home");
}
}
return View("show", input);
}
[GET("logout")]
public ActionResult Logout()
{
Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return RedirectToAction("login");
}
}
I'll leave out the implementation of the views, because it is pretty standard Razor syntax. The thing to take note in the code above is the creation of a ClaimsIdentity. All yourcode needs to do is generate this class, and it doesn't matter from where: Database, Active Directory, Web Service, etc. The rest of the code above is really just boilerplate. You'll just need to use the AuthenticationManager from the OWIN context to SignInand SignOut.
Conclusion
There you have it. A basic breakdown of what you need to do to get OWIN authentication in your ASP.NET MVC applications without the craziness that comes standard in the Visual Studio templates. The standard templates in Visual Studio force you to use Entity Framework and has a lot of ceremony for what is essentially a really simple solution. So do yourself a favor and dump that mess and just implement something that makes more sense for you and your team.
Update
A reader ran into a nasty redirect issue in his production environment after deploying. This was a simple IIS Setup issue. If you are experiencing the same issue, please do the following in your IIS environment:
- Disable Windows Authentication Module
- Disable Forms Authentication Module (should have already)
- Enable Anonymous Authentication Module
Having multiple authentication methods on can lead to very strange behaviors. Good luck and I'd love to hear how your projects are going. I also recommend you read one of my later posts on securely storing passwords.
- 在Windows上运行单节点的Cassandra
- Mono技术规格
- 如何站在使用者的角度来设计SDK-微信公众号开发SDK(消息处理)设计之抛砖引玉
- 机器学习(三)——k-近邻算法基础
- 利用Windows性能计数器(PerformanceCounter)监控
- zepto 基础知识(1)
- [C#7] 1.Tuples(元组)
- 防止“rm-rf/”误删除的5种方法
- 基于DotNetOpenAuth实现OpenID 服务提供者
- .NET 和Java 对象 XML序列化 库WOX
- jquery mobile 移动web(6)
- IIS6 间歇性的发生500错误的解决方法
- 产品之上的世界观
- 使用Windows 7中的库
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 第十六章 分布式爬虫--准备工作
- go 搭建并行处理管道
- 新一代基于大数据的管理信息系统(MIS)报表需求开发
- 3. docker-compose实战--ghost app
- 2.1 Kubernetes--Pod
- 3. Kubernetes集群安装
- macOS VirtualBox 桥接模式 设置静态ip 且能和联网
- 重新初始化k8s master节点
- 5.k8s基本命令汇总
- 6. k8s + jenkins 实现持续集成(完)
- 7. 复制k8s Node节点 并重新初始化k8s-nodes2节点 (k8s连载)
- 8.k8s连载--重新生成k8s token(kubeadm join报错及解决)
- 3. dcoker容器的命令
- 4. 镜像的原理
- 5.docker容器数据卷