asp.net-mvc-4 – OAuth2和DotNetOpenAuth – 实现Google自定义客户端

前端之家收集整理的这篇文章主要介绍了asp.net-mvc-4 – OAuth2和DotNetOpenAuth – 实现Google自定义客户端前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在使用DotNetOpenAuth和MVC4实现自定义OAuth2Client for google的问题.

我已经到了这一点,我可以成功地向google终端发出授权请求
https://accounts.google.com/o/oauth2/auth

并且Google询问用户是否允许我的应用访问其帐户.到目前为止都不错当用户点击“确定”后,Google会按预期的方式调用回调URL.

问题是当我在OAuthWebSecurity类(Microsoft.Web.WebPages.OAuth)上调用VerifyAuthentication方法时,

  1. var authenticationResult = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback",new { ReturnUrl = returnUrl }));

它总是返回一个AuthenticationResult与IsSuccessful = false和Provider =“”

我已经查看了这个代码,OAuthWebSecurity类尝试从中获取提供者名称

  1. Request.QueryString["__provider__"]

但是Google并没有在查询字符串中发送此信息.我已经实施的另一个提供商(LinkedIn)正在发送提供商名称,它一切正常.

我不知道我可以做什么,除了放弃Microsoft.Web.WebPages.OAuth类,只是使用DotNetOpenAuth没有他们,但我希望有人可能有另一个解决方案,我可以尝试…

我已经广泛搜索,但似乎找不到任何帮助…我发现真的很难,只是找到人做同样的事情的例子,这真的让我感到惊讶.

任何帮助非常感谢!

解决方法

更新:正如Matt Johnson提到的,他已经打包了一个可以从GitHub: https://github.com/mj1856/DotNetOpenAuth.GoogleOAuth2获得的解决方

他说:
针对ASP.Net MVC 4的DNOA和OAuthWebSecurity仅提供给Google的OpenId提供程序.这是一个您可以使用的OAuth2客户端.

重要 – 如果您使用ASP.Net MVC 5,此包不适用.您应该使用Microsoft.Owin.Security.Google. (它也附带VS 2013中的MVC 5启动器模板)

最后我得到了这个结果,通过捕获请求进来,并做我自己的检查,看看它是哪个提供者. Google允许您将参数发送到名为“state”的OAuth请求,当它们进行回调时,它们将直接传递给您,因此我使用此参数传递google的提供程序名称,并且我检查没有“__provider__”.

这样的:

  1. public String GetProviderNameFromQueryString(NameValueCollection queryString)
  2. {
  3. var result = queryString["__provider__"];
  4.  
  5. if (String.IsNullOrWhiteSpace(result))
  6. {
  7. result = queryString["state"];
  8. }
  9.  
  10. return result;
  11. }

然后,我为Google实现了一个自定义的OAuth2Client,我自己手动调用VerifyAuthentication方法,绕过了Microsoft的包装器.

  1. if (provider is GoogleCustomClient)
  2. {
  3. authenticationResult = ((GoogleCustomClient)provider).VerifyAuthentication(context,new Uri(String.Format("{0}/oauth/ExternalLoginCallback",context.Request.Url.GetLeftPart(UriPartial.Authority).ToString())));
  4. }
  5. else
  6. {
  7. authenticationResult = OAuthWebSecurity.VerifyAuthentication(returnUrl);
  8. }

这使我能够保留我已经为其他提供商使用Microsoft包装器的东西.

根据@ 1010100 1001010的要求,这里是我自定义的OAuth2Client for Google(注意:需要一些TIDYING!我没有办法处理代码上升,它的工作虽然):

  1. public class GoogleCustomClient : OAuth2Client
  2. {
  3. ILogger _logger;
  4.  
  5. #region Constants and Fields
  6.  
  7. /// <summary>
  8. /// The authorization endpoint.
  9. /// </summary>
  10. private const string AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/auth";
  11.  
  12. /// <summary>
  13. /// The token endpoint.
  14. /// </summary>
  15. private const string TokenEndpoint = "https://accounts.google.com/o/oauth2/token";
  16.  
  17. /// <summary>
  18. /// The _app id.
  19. /// </summary>
  20. private readonly string _clientId;
  21.  
  22. /// <summary>
  23. /// The _app secret.
  24. /// </summary>
  25. private readonly string _clientSecret;
  26.  
  27. #endregion
  28.  
  29.  
  30. public GoogleCustomClient(string clientId,string clientSecret)
  31. : base("Google")
  32. {
  33. if (string.IsNullOrWhiteSpace(clientId)) throw new ArgumentNullException("clientId");
  34. if (string.IsNullOrWhiteSpace(clientSecret)) throw new ArgumentNullException("clientSecret");
  35.  
  36. _logger = ObjectFactory.GetInstance<ILogger>();
  37.  
  38. this._clientId = clientId;
  39. this._clientSecret = clientSecret;
  40. }
  41.  
  42. protected override Uri GetServiceLoginUrl(Uri returnUrl)
  43. {
  44. StringBuilder serviceUrl = new StringBuilder();
  45.  
  46. serviceUrl.AppendFormat("{0}?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile",AuthorizationEndpoint);
  47. serviceUrl.Append("&state=google");
  48. serviceUrl.AppendFormat("&redirect_uri={0}",returnUrl.ToString());
  49. serviceUrl.Append("&response_type=code");
  50. serviceUrl.AppendFormat("&client_id={0}",_clientId);
  51.  
  52. return new Uri(serviceUrl.ToString());
  53.  
  54. }
  55.  
  56. protected override IDictionary<string,string> GetUserData(string accessToken)
  57. {
  58. RestClient client = new RestClient("https://www.googleapis.com");
  59. var request = new RestRequest(String.Format("/oauth2/v1/userinfo?access_token={0}",accessToken),Method.GET);
  60. IDictionary<String,String> extraData = new Dictionary<String,String>();
  61.  
  62. var response = client.Execute(request);
  63. if (null != response.ErrorException)
  64. {
  65. return null;
  66. }
  67. else
  68. {
  69. try
  70. {
  71. var json = JObject.Parse(response.Content);
  72.  
  73. string firstName = (string)json["given_name"];
  74. string lastName = (string)json["family_name"];
  75. string emailAddress = (string)json["email"];
  76. string id = (string)json["id"];
  77.  
  78. extraData = new Dictionary<String,String>
  79. {
  80. {"accesstoken",accessToken},{"name",String.Format("{0} {1}",firstName,lastName)},{"firstname",firstName},{"lastname",lastName},{"email",emailAddress},{"id",id}
  81. };
  82. }
  83. catch(Exception ex)
  84. {
  85. _logger.Error("Error requesting OAuth user data from Google",ex);
  86. return null;
  87. }
  88. return extraData;
  89. }
  90.  
  91. }
  92.  
  93. protected override string QueryAccessToken(Uri returnUrl,string authorizationCode)
  94. {
  95. StringBuilder postData = new StringBuilder();
  96. postData.AppendFormat("client_id={0}",this._clientId);
  97. postData.AppendFormat("&redirect_uri={0}",HttpUtility.UrlEncode(returnUrl.ToString()));
  98. postData.AppendFormat("&client_secret={0}",this._clientSecret);
  99. postData.AppendFormat("&grant_type={0}","authorization_code");
  100. postData.AppendFormat("&code={0}",authorizationCode);
  101.  
  102.  
  103. string response = "";
  104. string accessToken = "";
  105.  
  106. var webRequest = (HttpWebRequest)WebRequest.Create(TokenEndpoint);
  107.  
  108. webRequest.Method = "POST";
  109. webRequest.ContentType = "application/x-www-form-urlencoded";
  110.  
  111. try
  112. {
  113.  
  114. using (Stream s = webRequest.GetRequestStream())
  115. {
  116. using (StreamWriter sw = new StreamWriter(s))
  117. sw.Write(postData.ToString());
  118. }
  119.  
  120. using (WebResponse webResponse = webRequest.GetResponse())
  121. {
  122. using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
  123. {
  124. response = reader.ReadToEnd();
  125. }
  126. }
  127.  
  128. var json = JObject.Parse(response);
  129. accessToken = (string)json["access_token"];
  130. }
  131. catch(Exception ex)
  132. {
  133. _logger.Error("Error requesting OAuth access token from Google",ex);
  134. return null;
  135. }
  136.  
  137. return accessToken;
  138.  
  139. }
  140.  
  141. public override AuthenticationResult VerifyAuthentication(HttpContextBase context,Uri returnPageUrl)
  142. {
  143.  
  144. string code = context.Request.QueryString["code"];
  145. if (string.IsNullOrEmpty(code))
  146. {
  147. return AuthenticationResult.Failed;
  148. }
  149.  
  150. string accessToken = this.QueryAccessToken(returnPageUrl,code);
  151. if (accessToken == null)
  152. {
  153. return AuthenticationResult.Failed;
  154. }
  155.  
  156. IDictionary<string,string> userData = this.GetUserData(accessToken);
  157. if (userData == null)
  158. {
  159. return AuthenticationResult.Failed;
  160. }
  161.  
  162. string id = userData["id"];
  163. string name;
  164.  
  165. // Some oAuth providers do not return value for the 'username' attribute.
  166. // In that case,try the 'name' attribute. If it's still unavailable,fall back to 'id'
  167. if (!userData.TryGetValue("username",out name) && !userData.TryGetValue("name",out name))
  168. {
  169. name = id;
  170. }
  171.  
  172. // add the access token to the user data dictionary just in case page developers want to use it
  173. userData["accesstoken"] = accessToken;
  174.  
  175. return new AuthenticationResult(
  176. isSuccessful: true,provider: this.ProviderName,providerUserId: id,userName: name,extraData: userData);
  177. }

猜你在找的asp.Net相关文章