2015-07-13 84 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