2015-07-13 86 views
10

我們開發了一組Web API(REST),它們受授權服務器的保護。授權服務器已發佈客戶端ID和客戶端密鑰。這些可用於獲取訪問令牌。隨後調用資源服務器(REST API)時可以使用有效的令牌。如何在Asp.net MVC中編寫OAuth2 Web API客戶端

我想寫一個基於Web的(Asp.net MVC 5)客戶端,將消耗API。是否有我可以下載的nuget包,這將幫助我實現客戶端OAuth2流程?任何人都可以指導我在客戶端實現OAuth2流程(寫在asp.net MVC)上的一個很好的例子嗎?

更新 我能得到訪問使用下面的代碼塊令牌,但我要的是一個「客戶端憑證」的OAuth 2流,其中我沒有進入登錄和密碼。我現在的代碼是:

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) 
     }); 

     app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions 
     { 
      AuthenticationMode = AuthenticationMode.Active, 
      AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType,     
      SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType(), 
      ClientId = ConfigurationManager.AppSettings["AuthServer:ClientId"], 
      ClientSecret = ConfigurationManager.AppSettings["AuthServer:ClientSecret"], 
      RedirectUri = ConfigurationManager.AppSettings["AuthServer:RedirectUrl"], 
      Configuration = new OpenIdConnectConfiguration 
      { 
       AuthorizationEndpoint = "https://identityserver.com/oauth2/authorize", 
       TokenEndpoint = "https://identityserver.com/oauth2/token"           
      }, 

      //ResponseType = "client_credentials", // Doesn't work 
      ResponseType = "token", 

      Notifications = new OpenIdConnectAuthenticationNotifications 
      { 
       AuthenticationFailed = notification => 
       { 
        if (string.Equals(notification.ProtocolMessage.Error, "access_denied", StringComparison.Ordinal)) 
        { 
         notification.HandleResponse(); 

         notification.Response.Redirect("/"); 
        } 

        return Task.FromResult<object>(null); 
       }, 

       AuthorizationCodeReceived = async notification => 
       { 
        using (var client = new HttpClient()) 
        { 
         //var configuration = await notification.Options.ConfigurationManager.GetConfigurationAsync(notification.Request.CallCancelled); 
         String tokenEndPoint = "https://identityserver.com/oauth2/token"; 

         //var request = new HttpRequestMessage(HttpMethod.Post, configuration.TokenEndpoint); 
         var request = new HttpRequestMessage(HttpMethod.Post, 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.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))); 
        } 
       } 
      } 
     }); 


    } 
} 

回答

15

支持客戶端證書授予類型,你最好的選擇可能是直接使用HttpClient

var request = new HttpRequestMessage(HttpMethod.Post, "http://server.com/token"); 
request.Content = new FormUrlEncodedContent(new Dictionary<string, string> { 
    { "client_id", "your client_id" }, 
    { "client_secret", "your client_secret" }, 
    { "grant_type", "client_credentials" } 
}); 

var response = await client.SendAsync(request); 
response.EnsureSuccessStatusCode(); 

var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); 
var token = payload.Value<string>("access_token"); 

對於交互式流量(如授權碼流程),有兩種更好的方法:

+0

我已經取得了一些進展,並能得到令牌身份從服務器返回。但我想要的是一個「客戶端憑證」流程,我不需要輸入任何登錄名和密碼。應根據客戶端ID和客戶端密鑰發佈令牌。不知何故,我無法配置它。我用我現在的代碼更新了這個問題。 – TejSoft

+1

這恐怕是一個不同的問題。您的原始問題(儘管使用不精確的術語)建議您使用授權碼流:「這些可用於獲取授權碼,而授權碼又可用於獲取訪問令牌」。爲Katana 3開發的OIDC中間件不支持資源所有者密碼憑證流或客戶端憑證流等非交互式流程。你必須直接使用'HttpClient'和'grant_type = client_credentials'。你使用哪個授權服務器? – Pinpoint

+0

是的,當我開始實施它時,事情變得更加清晰。我正在使用名爲WS02的基於Java的標識服務器。如果Katana 3不能用於「客戶端憑證」,您是否推薦其他nuget軟件包?任何例子? – TejSoft