使用oauth2进行身份验证来获取

时间:2012-08-08 23:29:19

标签: asp.net c#-4.0 oauth-2.0

我正在尝试从我的c#asp.net应用程序连接到gotowebinar REST服务,这需要oauth2。不幸的是我不能使用dotnetopenauth。有没有人有关于如何对gotowebinar进行身份验证的简单c#代码示例?

我已经看到了其他一些oauth2 API,但大多数似乎都没有记录。

这是gotowebinar's overview of their authentication process

1 个答案:

答案 0 :(得分:4)

我建议使用dotnetopenauth。

遗憾的是,由于项目限制,我无法使用它,所以这里是我工作代码的一个片段。我删除了一些专有代码,试图让它更容易阅读和使用。如果有人有任何疑问,请告诉我,我会看看能否提供帮助。

    /// <summary>
/// Summary description for GoToWebinarProvider
/// </summary>
public class GoToWebinarProvider
{
    #region properties
    private GoToWebinarAccessToken _accessToken;
    private readonly string _apiKey = "apikey";

    /// <summary>
    /// Use for debugging purposes
    /// </summary>
    private const bool EnableCaching = true;

    private const string G2WApiDateTimeFormat = "yyyy-MM-ddTHH:mm:ssZ";
    #endregion properties

    #region token management
    private void OAuthenticate()
    {
        GoToWebinarAccessToken localToken = null;

        //try to get access token from cache
        if (EnableCaching)
        {
            localToken = GetTokenFromDb();

            //cache it here
        }
        else
        {
            _accessToken = GetTokenFromDb();
        }

        //if the token hasn't expired yet, we have an access token, so instantiation is complete
        if (_accessToken != null && _accessToken.ExpirationDate > DateTime.Now)
        {
            return;
        }

        //else get new token
        var responseKey = GetResponseKey();

        if (responseKey != null)
        {
            _accessToken = GetAccessToken(responseKey);

            if (_accessToken != null)
            {
                StoreTokenInDb(_accessToken);
            }
            else
            {
                throw new Exception("Could not acquire access token from GoToWebinar");
            }
        }
        else
        {
            throw new Exception("Could not acquire response key from GoToWebinar");
        }
    }

    private GoToWebinarAccessToken GetAccessToken(string responseKey)
    {
        var url =
            String.Format(
                "https://api.citrixonline.com/oauth/access_token?grant_type=authorization_code&code={0}&client_id={1}",
                responseKey, _apiKey);

        const string applicationJSON = "application/json; charset=UTF-8";

        var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);

        httpWebRequest.ProtocolVersion = HttpVersion.Version11;
        httpWebRequest.Method = "GET";

        httpWebRequest.Accept = applicationJSON;

        try
        {
            var response = httpWebRequest.GetResponse();
            //will throw error if not 200 response

            using (var dataStream = response.GetResponseStream())
            {
                var responseText = dataStream != null ? new StreamReader(dataStream).ReadToEnd() : String.Empty;

                var jsSerializer = new JavaScriptSerializer();

                var accessToken = jsSerializer.Deserialize(responseText, typeof(GoToWebinarAccessToken)) as GoToWebinarAccessToken;

                //pad it by a minute.  took time to calculate it, and each request will have latency in getting to gotowebinar
                accessToken.ExpirationDate = DateTime.Now.AddSeconds(Convert.ToDouble(accessToken.Expires_In)).AddMinutes(-1);

                return accessToken;
            }
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    private string GetResponseKey()
    {
        var redirectURL = HttpContext.Current.Server.UrlEncode("http://mysite.net/Welcome.aspx");

        var requestURL =
            String.Format("https://api.citrixonline.com/oauth/authorize?client_id={0}&amp;redirect_uri={1}", _apiKey,
                          redirectURL);
        var request = CreateWebRequest(requestURL, "GET");

        try
        {
            //first request
            var response = request.GetResponse();
            //will throw error if not 200 response

            using (var dataStream = response.GetResponseStream())
            {

                var responseText = dataStream != null ? new StreamReader(dataStream).ReadToEnd() : String.Empty;

                return Login(redirectURL);
            }
        }
        catch (Exception ex)
        {
            return null;
        }
    }

    /// <summary>
    /// Should only be called by GetResponseKey
    /// </summary>
    /// <param name="urlEncodedRedirect"></param>
    private string Login(string urlEncodedRedirect)
    {
        var elp = new EventLogProvider();

        var userName = HttpContext.Current.Server.UrlEncode(SettingsKeyProvider.GetSettingsKeyInfo("GoToWebinarUserEmail").KeyValue);
        var password = HttpContext.Current.Server.UrlEncode(SettingsKeyProvider.GetSettingsKeyInfo("GoToWebinarUserPassword").KeyValue);
        var postData = String.Format(
                "emailAddress={0}&password={1}&client_id={2}&access_type=G2W&app_name=MyApp&redirect_url={3}&submitted=form_submitted&submit=Log+In",
                userName, password, _apiKey, urlEncodedRedirect);

        var request = CreateWebRequest("https://developer.citrixonline.com/oauth/g2w/authorize.php", "POST",
                                       postData, "application/x-www-form-urlencoded");
        request.AllowAutoRedirect = false;

        var response = request.GetResponse();

        using (var dataStream = response.GetResponseStream())
        {
            var responseText = dataStream != null ? new StreamReader(dataStream).ReadToEnd() : String.Empty;

            const string locationHeader = "location";

            if (!String.IsNullOrWhiteSpace(response.Headers.Get(locationHeader)))
            {
                //get redirect to login page
                var locationRedirect = response.Headers.Get(locationHeader);

                elp.LogEvent("I", DateTime.Now, GetType().Name, "GoToWebinar",
                             HttpContext.Current.Request.Url.ToString(), locationRedirect);

                const string comparator = "code=";
                var index = locationRedirect.IndexOf(comparator, StringComparison.OrdinalIgnoreCase);

                if (index != -1)
                {
                    return locationRedirect.Substring(index + comparator.Length);
                }

                throw new Exception("Could not parse response code: " + locationRedirect);
            }


            throw new Exception("Did not receive redirect: ", new Exception(responseText));
        }
    }

    private static GoToWebinarAccessToken GetTokenFromDb()
    {
        //return token
    }

    private static void StoreTokenInDb(GoToWebinarAccessToken accessToken)
    {
        //store token
    }
    #endregion token management

    #region api calls

    public IList<GoToWebinarWebinar> GetWebinars()
    {
        if (_accessToken == null || _accessToken.ExpirationDate < DateTime.Now)
        {
            OAuthenticate();
        }

        var serviceEndPoint = String.Format("https://api.citrixonline.com/G2W/rest/organizers/{0}/webinars", _accessToken.Organizer_Key);

        try
        {
            var httpWebRequest = CreateJSONRequest(serviceEndPoint, "GET", null);

            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            using (var httpResponseStream = httpResponse.GetResponseStream())
            {
                if (httpResponseStream != null)
                {
                    using (var streamReader = new StreamReader(httpResponseStream))
                    {
                        var responseText = streamReader.ReadToEnd();

                        var jsSerializer = new JavaScriptSerializer();
                        var gotoWebinarList = jsSerializer.Deserialize<IList<GoToWebinarWebinar>>(responseText);

                        return gotoWebinarList;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            //log it
        }

        return null;
    }

    #endregion api calls

    #region web requests
    private HttpWebRequest CreateJSONRequest(string serviceEndPoint, string httpMethod, string postData)
    {
        const string applicationJSON = "application/json";

        var httpWebRequest = (HttpWebRequest)WebRequest.Create(serviceEndPoint);

        httpWebRequest.ProtocolVersion = HttpVersion.Version11;
        httpWebRequest.Method = httpMethod;

        httpWebRequest.Accept = String.Format("{0}, application/vnd.citrix.g2wapi-v1.1+json", applicationJSON);

        httpWebRequest.ContentType = applicationJSON;
        httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, _accessToken.Access_Token);

        if (httpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
        {
            var encoding = new ASCIIEncoding();

            var body = encoding.GetBytes(postData);
            httpWebRequest.ContentLength = body.Length;

            using (var newStream = httpWebRequest.GetRequestStream())
            {
                newStream.Write(body, 0, body.Length);
                newStream.Close();
            }
        }

        return httpWebRequest;
    }

    private static HttpWebRequest CreateWebRequest(string serviceEndPoint, string httpMethod)
    {
        //const string applicationJSON = "application/json";

        var httpWebRequest = (HttpWebRequest)WebRequest.Create(serviceEndPoint);

        httpWebRequest.ProtocolVersion = HttpVersion.Version11;
        httpWebRequest.Method = httpMethod;

        //httpWebRequest.Accept = String.Format("{0}, application/vnd.citrix.g2wapi-v1.1+json", applicationJSON);

        //httpWebRequest.ContentType = applicationJSON;
        //httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, _accessToken);

        return httpWebRequest;
    }

    private static HttpWebRequest CreateWebRequest(string serviceEndPoint, string httpMethod, string postData, string contentType)
    {
        var httpWebRequest = (HttpWebRequest)WebRequest.Create(serviceEndPoint);

        httpWebRequest.ProtocolVersion = HttpVersion.Version11;
        httpWebRequest.Method = httpMethod;

        if (contentType != null)
        {
            httpWebRequest.ContentType = contentType;
        }

        if (httpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
        {
            var encoding = new ASCIIEncoding();

            var body = encoding.GetBytes(postData);
            httpWebRequest.ContentLength = body.Length;

            using (var newStream = httpWebRequest.GetRequestStream())
            {
                newStream.Write(body, 0, body.Length);
                newStream.Close();
            }
        }

        return httpWebRequest;
    }

    #endregion web requests

    private void LogRequest(string methodName, string dataToLog)
    {
        //log it
    }

    /// <summary>
    /// Syntax matches JSON response
    /// </summary>
    private class GoToWebinarAccessToken
    {
        public string Access_Token;
        public string Refresh_Token;
        public string Organizer_Key;
        public string Account_Key;

        public double? Expires_In;

        public DateTime ExpirationDate;
    }
}