2015-12-03 12 views
9

Bir üçüncü taraf sağlayıcının Oauth2 tabanlı Yetkilendirme Sunucusu olarak hareket edeceği bir proje üzerinde çalışıyorum. Kullanıcının yetkilendirme sunucusuna kimlik doğrulaması yapmak için (login/password kullanarak) ve auth sunucusunu gönderecek bir Asp.net MVC 5 tabanlı istemci, bir erişim belirtecini MVC istemcisine geri döndürecektir. Kaynak sunuculara (API) yapılan diğer çağrılar erişim belirteci kullanılarak yapılacaktır.OWIN OpenID bağlantı yetkilendirmesi, güvenli denetleyiciyi/eylemleri yetkilendirmede başarısız oluyor

Bunu başarmak için Microsoft.Owin.Security.OpenIdConnect ve UseOpenIdConnectAuthentication uzantısını kullanıyorum. Auth sunucusundan erişim kodunu başarılı bir şekilde yönlendirebilir ve alabilirim ancak istemci bir Kimlik Doğrulama Çerezi oluşturmuyor. Güvenli bir sayfaya her erişmeye çalıştığımda, erişim belirteci olan geri arama sayfasını alırım.

Burada nelerin eksik? Mevcut kodum aşağıda.

güvenli kontrolör eylemi:

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

Başlangıç ​​Sınıfı:

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<object>(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<string, string> 
     //    { 
     //     {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<string>(OpenIdConnectParameterNames.AccessToken))); 
     //   } 
     //  } 
     // } 

     //}); 

    } 
}    

cevap

3

TL; DR: kullanım ResponseType = "id_token token" ve çalışması gerekir. OpenID Connect

, response_type=token yasal değer olarak kabul edilmez: http://openid.net/specs/openid-connect-core-1_0.html#Authentication. Bazen geriye dönük uyumluluk nedenleriyle uygulanan

, response_type=token MSFT tarafından geliştirilen OIDC katman tarafından desteklenmez: hayır id_token (ayrıca geçerli code akışını barındırmayan) OpenID Bağlan sağlayıcı tarafından döndürülen zaman bir istisna her zaman atılır. Bu diğer SO post hakkında daha fazla bilgi bulabilirsiniz.

(not: SecurityTokenValidated yılında, sen OIDC katman n.AuthenticationTicket = new AuthenticationTicket(...) kullanılarak oluşturulan bilet değiştiriyoruz: o önerilen yaklaşım değil ve gerekli iddiaları eksik bir ClaimsIdentity sonuçlanacaktır Yeni ekleyebilir basitçe assignation kaldırmayı düşünün ve olmalıdır. access_token talebi için yaptığınız gibi hak talepleri)

+0

Response_type = "id_token jetonunu" denedim, ancak kullandığım kimlik sunucusuna (WSO2 5.0.0) destek veriyor gibi görünüyor. Bir sonraki sürüm tam openid bağlantı özellikleri için çıkana kadar beklemem gerekecek. Response_type = "code" yanıtını değiştirdiğimde, kimlik doğrulama işleminin ilk bölümünü tamamlar ve URL'de bir kodla döner, ancak erişim belirtecini almak için bir sonraki istek gerçekleşmez ve OWIN hattında hiçbir kimlik oluşturulmaz. – TejSoft

+0

Gerçekten de, desteklenmiyor gibi görünüyor: http://stackoverflow.com/a/29140396/542757. Ne yazık ki, OIDC katman yazılımı desteklemediği için kod akışını kullanamazsınız (utanç verici ve ASP.NET ekibine defalarca söyledim). ASP.NET 5'e geçmek bir seçenek olabilir mi? – Pinpoint

+0

WSO2 henüz hazır değilse, ASP.net 5'e taşınıyor mu? Kimlik sunucusu, bazı mevcut ve bazı yeni (yerleşik) olmak üzere birden fazla siteyi destekleyecektir. Yeni olanlar ASP.net 5'i kullanabilir, ancak eskiler 4.5'tedir. WSO2 bir sonraki sürümü yakında yayınlayacağından birkaç hafta daha bekleyebilirim. Soruyu yaptığım iki yaklaşımla güncelledim. – TejSoft

İlgili konular