如何使用DotNetOpenAuth.AspNet在我使用MVC3时提供社交登录

时间:2014-04-22 01:44:50

标签: c# oauth-2.0 openid dotnetopenauth yahoo

我试图在我的网站上使用YahooJapan(Yconnect)作为社交登录,我决定使用DotNetOpenAuth.AspNet。但我无法使其工作(一般来说,访问授权端点的第一步) ,我总是在VerifyAuthentication方法中得到一个空代码。我猜我的AuthorizationForAspNet方法可能有问题(可能步骤的顺序错了)。 请帮助我,谢谢。

以下是控制器:

    public virtual ActionResult ExternalLogin(int providerNo, string returnAction = "Login")
    {
        if (provider == Provider.Yahoo)
        {
            state = OAuth2Provider.AuthorizationForAspNet(provider);
        }
    }

以下是Class OAuth2Provider中的AuthorizationForAspNet方法: (网址" 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);
    }
}

1 个答案:

答案 0 :(得分:0)

这有效。

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