基于本教程
http://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server,我创建了一个授权服务器,一个资源服务器和一个MVC客户端.
MVC客户端具有从资源服务器获取一些数据的控制器.资源服务器需要身份验证. MVC客户端从授权服务器获取授权码,并将用户重定向到授权服务器进行身份验证.最后,MVC客户端交换访问令牌的授权码以访问资源服务器.这是OAuth 2协议所述的授权码流程.这工作正常
MVC客户端具有从资源服务器获取一些数据的控制器.资源服务器需要身份验证. MVC客户端从授权服务器获取授权码,并将用户重定向到授权服务器进行身份验证.最后,MVC客户端交换访问令牌的授权码以访问资源服务器.这是OAuth 2协议所述的授权码流程.这工作正常
现在,我要求使MVC客户端的控制器本身需要验证.我找不到这个教程.
我补充说
app.USEOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
到我的Startup.Auth.cs.
我假设,我需要设置重定向到授权服务器的选项.我也可以在选项上设置提供者:
app.USEOAuthBearerAuthentication(new Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationOptions() { Provider = new OAuthBearerAuthenticationProvider() });
但我也坚持执行提供商的事件.
任何人可以指导我正确的方向吗?还是有任何可能帮助我的教程?
解决方法
我结束了一个基于Brock Allen这两篇文章的解决方案:
> http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/
> http://brockallen.com/2014/01/09/a-primer-on-external-login-providers-social-logins-with-owinkatana-authentication-middleware/
基本思路是注册两个认证中间件.活动的Cookie验证和被动OAuthBearer-Authentication.在Startup.Auth.cs中,它们是这样添加的:
app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,LoginPath = new PathString("/ExternalLogin/Login"),}); app.USEOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions() { AuthenticationType = DefaultAuthenticationTypes.ExternalBearer,AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,});
您还可以添加一个ExternalLogin-Controller.其登录方法必须将用户重定向到授权服务器的登录页面以获取授权码.您必须提供一个回调函数,您将在其中处理授权码.
public async Task<ActionResult> Login(string returnUrl) { if (string.IsNullOrEmpty(returnUrl) && Request.UrlReferrer != null) returnUrl = Server.UrlEncode(Request.UrlReferrer.PathAndQuery); if (Url.IsLocalUrl(returnUrl) && !string.IsNullOrEmpty(returnUrl)) _returnUrl = returnUrl; //callback function _redirectUrl = Url.Action("AuthorizationCodeCallback","ExternalLogin",null,Request.Url.Scheme); Dictionary<string,string> authorizeArgs = null; authorizeArgs = new Dictionary<string,string> { {"client_id","0123456789"},{"response_type","code"},{"scope","read"},{"redirect_uri",_redirectUrl} // optional: state }; var content = new FormUrlEncodedContent(authorizeArgs); var contentAsString = await content.ReadAsStringAsync(); return Redirect("http://localhost:64426/oauth/authorize?" + contentAsString); }
在您的回调功能中,交换访问令牌(加刷新令牌)的授权代码会挑战您的被动OAuthBearer身份验证中间件,并使用Access令牌作为Cookie登录.
public async Task<ActionResult> AuthorizationCodeCallback() { // received authorization code from authorization server string[] codes = Request.Params.GetValues("code"); var authorizationCode = ""; if (codes.Length > 0) authorizationCode = codes[0]; // exchange authorization code at authorization server for an access and refresh token Dictionary<string,string> post = null; post = new Dictionary<string,{"client_secret","ClientSecret"},{"grant_type","authorization_code"},{"code",authorizationCode},_redirectUrl} }; var client = new HttpClient(); var postContent = new FormUrlEncodedContent(post); var response = await client.PostAsync("http://localhost:64426/token",postContent); var content = await response.Content.ReadAsStringAsync(); // received tokens from authorization server var json = JObject.Parse(content); _accessToken = json["access_token"].ToString(); _authorizationScheme = json["token_type"].ToString(); _expiresIn = json["expires_in"].ToString(); if (json["refresh_token"] != null) _refreshToken = json["refresh_token"].ToString(); //SignIn with Token,SignOut and create new identity for SignIn Request.Headers.Add("Authorization",_authorizationScheme + " " + _accessToken); var ctx = Request.GetOwinContext(); var authenticateResult = await ctx.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer); ctx.Authentication.SignOut(DefaultAuthenticationTypes.ExternalBearer); var applicationCookieIdentity = new ClaimsIdentity(authenticateResult.Identity.Claims,DefaultAuthenticationTypes.ApplicationCookie); ctx.Authentication.SignIn(applicationCookieIdentity); var ctxUser = ctx.Authentication.User; var user = Request.RequestContext.HttpContext.User; //redirect back to the view which required authentication string decodedUrl = ""; if (!string.IsNullOrEmpty(_returnUrl)) decodedUrl = Server.UrlDecode(_returnUrl); if (Url.IsLocalUrl(decodedUrl)) return Redirect(decodedUrl); else return RedirectToAction("Index","Home"); }
我希望这对于在他的MVC 5应用程序中实现OAuth授权代码流的人是有用的.