我正试图在我的网站中使用YahooJapan(Yconnect)作为socail登录,我决定使用DotNetOpenAuth.AspNet.但是我无法让它工作(实际上,访问授权端点的第一步),我在VerifyAuthentication方法中总是得到一个空代码。我想我的AuthorizationForAspNet方法可能有问题(可能步骤顺序错误)。请帮帮我,谢谢。
以下是控制器:
public virtual ActionResult ExternalLogin(int providerNo, string returnAction = "Login")
{
if (provider == Provider.Yahoo)
{
state = OAuth2Provider.AuthorizationForAspNet(provider);
}
}
以下是类OAuth2Provider中的AuthorizationForAspNet方法:(url"https://***/User/ExternalLogin?providerNo=4"是我在YahooDeveloperConsole中决定的returnURI)**
public static OAuth2State AuthorizationForAspNet(Provider provider)
{
var YahooClient = new YahooClient(
clientId: clients[provider].AppID, clientSecret: clients[provider].AppSecret);
OAuthWebSecurity.RegisterClient(YahooClient);
OAuthWebSecurity.RequestAuthentication("yahoo");
AuthenticationResult result = YahooClient.VerifyAuthentication(new HttpContextWrapper(HttpContext.Current), new System.Uri("https://******/User/ExternalLogin?providerNo=4"));
}
以下是我定制的YahooClient:
public class YahooClient : DotNetOpenAuth.AspNet.Clients.OAuth2Client
{
private static string Escape(string target)
{
return Uri.EscapeDataString(target);
}
private const string AuthorizationEndpoint = "https://auth.login.yahoo.co.jp/yconnect/v1/authorization";
private const string TokenEndpoint = "https://auth.login.yahoo.co.jp/yconnect/v1/token";
private const string UserDetailsEndPoint = "https://userinfo.yahooapis.jp/yconnect/v1/attribute";
private readonly string _clientId;
private readonly string _clientSecret;
public YahooClient(string clientId, string clientSecret): base("yahoo")
{
if (string.IsNullOrWhiteSpace(clientId))
throw new ArgumentNullException("clientId");
if (string.IsNullOrWhiteSpace(clientSecret))
throw new ArgumentNullException("clientSecret");
_clientId = clientId;
_clientSecret = clientSecret;
}
protected override Uri GetServiceLoginUrl(Uri returnUrl)
{
string sid = String.Empty;
if (returnUrl.ToString().Contains("__sid__"))
{
int index = returnUrl.ToString().IndexOf("__sid__") + 8;
int len = returnUrl.ToString().Length;
sid = returnUrl.ToString().Substring(index, len - index - 1);
}
string redirectUri = (returnUrl.ToString().Contains("&"))?(returnUrl.ToString().Substring(0, returnUrl.ToString().IndexOf("&")) ):(returnUrl.ToString());
var builder = new UriBuilder(AuthorizationEndpoint);
builder.Query = string.Join("&",
"response_type=code",
"client_id=" + Escape(_clientId),
"redirect_uri=" + Escape(redirectUri),
"scope=" + Escape("openid profile"),
"state=" + sid);
return builder.Uri;
}
protected override IDictionary<string, string> GetUserData(string accessToken)
{
// UserInfo API
var builder = new UriBuilder(UserDetailsEndPoint);
builder.Query = string.Join("&", "schema=openid");
var request = WebRequest.Create(builder.Uri);
request.Headers.Add("Authorization", "Bearer " + Escape(accessToken));
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK) return null;
var json = response.GetResponseBody();
var userData = JObject.Parse(json);
if (userData == null) return null;
return new Dictionary<string, string>()
.AddIfNotEmpty("id", (string)userData["user_id"])
.AddIfNotEmpty("username", (string)userData["name"]);
}
}
protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
{
var request = WebRequest.Create(TokenEndpoint);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
// Basic
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(_clientId + ":" + _clientSecret));
request.Headers.Add("Authorization", "Basic " + credentials);
var postData = string.Join("&",
"grant_type=authorization_code",
"code=" + Escape(authorizationCode),
"redirect_uri=" + Escape(returnUrl.AbsoluteUri));
request.ContentLength = postData.Length;
using (var stream = request.GetRequestStream())
using (var writer = new StreamWriter(stream))
{
writer.Write(postData);
writer.Flush();
}
using (var response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK) return null;
var json = response.GetResponseBody();
var tokenData = JObject.Parse(json);
if (tokenData == null) return null;
return (string)tokenData["access_token"];
}
}
public override AuthenticationResult VerifyAuthentication(HttpContextBase context, Uri returnPageUrl)
{
string code = context.Request.QueryString["code"];
string u = context.Request.Url.ToString();
if (string.IsNullOrEmpty(code))
return AuthenticationResult.Failed;
string accessToken = this.QueryAccessToken(returnPageUrl, code);
if (accessToken == null)
return AuthenticationResult.Failed;
IDictionary<string, string> userData = this.GetUserData(accessToken);
if (userData == null)
return AuthenticationResult.Failed;
string id = userData["user_id"];
string name = string.Empty;
return new AuthenticationResult(
isSuccessful: true, provider: "yahoo", providerUserId: id, userName: name, extraData: userData);
}
public override void RequestAuthentication(HttpContextBase context, Uri returnUrl)
{
base.RequestAuthentication(context, returnUrl);
}
}
这是有效的。
if (provider == Provider.Yahoo)
{
DotNetOpenAuth.AspNet.AuthenticationResult result;
var YahooClient = new YahooClient(clientId: clients[provider].AppID, clientSecret: clients[provider].AppSecret);
var context = HttpContext.Current;
//the second time
if (!String.IsNullOrEmpty(context.Request.QueryString.ToString()) && (context.Request.QueryString.ToString().Contains("code")))
{
result = YahooClient.VerifyAuthentication(new HttpContextWrapper(context), new Uri(returnUrl));
if (result.IsSuccessful)
{
//Success;
}
}
//the first time
else
{
OAuthWebSecurity.RegisterClient(YahooClient, "yahoo");
OAuthWebSecurity.RequestAuthentication("yahoo");
}
}