OWIN OpenID连接授权无法授权安全控制器/操作

我正在开发一个项目,其中第三方提供商将充当基于Oauth2的授权服务器。 一个基于Asp.net MVC 5的客户端,它将用户发送给授权服务器进行身份validation(使用登录/密码),auth服务器将一个访问令牌返回给MVC客户端。 将使用访问令牌对资源服务器(API)进行任何进一步调用。

为此,我使用的是Microsoft.Owin.Security.OpenIdConnect和UseOpenIdConnectAuthentication扩展。 我能够成功重定向并从auth服务器获取访问令牌,但客户端没有创建身份validationCookie。 每次我尝试访问安全页面时,都会获得带有访问令牌的回调页面。

我在这里想念的是什么? 我目前的代码如下。

安全控制器动作:

namespace MvcWebApp.Controllers { public class SecuredController : Controller { // GET: Secured [Authorize] public ActionResult Index() { return View((User as ClaimsPrincipal).Claims); } } } 

启动类:

 public class Startup { public void Configuration(IAppBuilder app) { app.SetDefaultSignInAsAuthenticationType("ClientCookie"); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, AuthenticationType = "ClientCookie", CookieName = CookieAuthenticationDefaults.CookiePrefix + "ClientCookie", ExpireTimeSpan = TimeSpan.FromMinutes(5) }); // *************************************************************************** // Approach 1 : ResponseType = "id_token token" // *************************************************************************** app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType, SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(), Authority = "https://thirdparty.com.au/oauth2", ClientId = "_Th4GVMa0JSrJ8RKcZrzbcexk5ca", ClientSecret = "a3GVJJbLHkrn9nJRj3IGNvk5eGQa", RedirectUri = "http://mvcwebapp.local/", ResponseType = "id_token token", Scope = "openid", Configuration = new OpenIdConnectConfiguration { AuthorizationEndpoint = "https://thirdparty.com.au/oauth2/authorize", TokenEndpoint = "https://thirdparty.com.au/oauth2/token", UserInfoEndpoint = "https://thirdparty.com.au/oauth2/userinfo", }, Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = n => { var token = n.ProtocolMessage.AccessToken; // persist access token in cookie if (!string.IsNullOrEmpty(token)) { n.AuthenticationTicket.Identity.AddClaim( new Claim("access_token", token)); } return Task.FromResult(0); }, AuthenticationFailed = notification => { if (string.Equals(notification.ProtocolMessage.Error, "access_denied", StringComparison.Ordinal)) { notification.HandleResponse(); notification.Response.Redirect("/"); } return Task.FromResult(null); } } }); // *************************************************************************** // Approach 2 : ResponseType = "code" // *************************************************************************** //app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions //{ // AuthenticationMode = AuthenticationMode.Active, // AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType, // SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(), // Authority = "https://thirdparty.com.au/oauth2", // ClientId = "_Th4GVMa0JSrJ8RKcZrzbcexk5ca", // ClientSecret = "a3GVJJbLHkrn9nJRj3IGNvk5eGQa", // RedirectUri = "http://mvcwebapp.local/", // ResponseType = "code", // Scope = "openid", // Configuration = new OpenIdConnectConfiguration // { // AuthorizationEndpoint = "https://thirdparty.com.au/oauth2/authorize", // TokenEndpoint = "https://thirdparty.com.au/oauth2/token", // UserInfoEndpoint = "https://thirdparty.com.au/oauth2/userinfo", // }, // Notifications = new OpenIdConnectAuthenticationNotifications // { // AuthorizationCodeReceived = async (notification) => // { // using (var client = new HttpClient()) // { // var configuration = await notification.Options.ConfigurationManager.GetConfigurationAsync(notification.Request.CallCancelled); // var request = new HttpRequestMessage(HttpMethod.Get, configuration.TokenEndpoint); // request.Content = new FormUrlEncodedContent(new Dictionary // { // {OpenIdConnectParameterNames.ClientId, notification.Options.ClientId}, // {OpenIdConnectParameterNames.ClientSecret, notification.Options.ClientSecret}, // {OpenIdConnectParameterNames.Code, notification.ProtocolMessage.Code}, // {OpenIdConnectParameterNames.GrantType, "authorization_code"}, // {OpenIdConnectParameterNames.ResponseType, "token"}, // {OpenIdConnectParameterNames.RedirectUri, notification.Options.RedirectUri} // }); // var response = await client.SendAsync(request, notification.Request.CallCancelled); // response.EnsureSuccessStatusCode(); // var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); // // Add the access token to the returned ClaimsIdentity to make it easier to retrieve. // notification.AuthenticationTicket.Identity.AddClaim(new Claim( // type: OpenIdConnectParameterNames.AccessToken, // value: payload.Value(OpenIdConnectParameterNames.AccessToken))); // } // } // } //}); } } 

TL; DR:使用ResponseType = "id_token token"它应该可以工作。

在OpenID Connect中, response_type=token不被视为合法值: http : //openid.net/specs/openid-connect-core-1_0.html#Authentication 。

有时为了向后兼容性而实现,MSFT开发的OIDC中间件不支持response_type=token :当OpenID Connect提供程序没有返回id_token时, id_token抛出exception(这也排除了有效的code流)。 您可以在此其他SOpost中找到更多信息。

(备注:在SecurityTokenValidated ,您正在使用n.AuthenticationTicket = new AuthenticationTicket(...)替换OIDC中间件创建的票证:这不是推荐的方法,并且会导致ClaimsIdentity缺少必要的声明。您应该考虑删除分配并简单地添加新的声明,就像你为access_token声明做的那样)