Yammer Authentication with HttpWebRequest

I am currently working on a project that requires the use of the Yammer API. The goal is to bypass the browser and use HttpWebRequest to do all of the authentication. It originally worked for me, but now I get a 404 error when I try to call GetResponse ().

For my url, I tried using
https://www.yammer.com/session?client_id= {CLIENT_ID}
and also
https://www.yammer.com/session

using (var stream = webrequest.GetRequestStream())
{
    stream.Write(postdata, 0, postdata.Length);
}

try
{
    webresponse = webrequest.GetResponse() as HttpWebResponse;
}
catch (WebException ex)
{
    webresponse = ex.Response as HttpWebResponse;
}

      

Did they change the url or am I doing something wrong?

+2


source to share


1 answer


Below is the code snippet for yammer authentication. Steve Pesci's article - http://blogs.technet.com/b/speschka/archive/2013/10/05/using-the-yammer-api-in-a-net-client-application.aspx explains how to perform authentication software yammer. I have customized it according to my needs.

public class YammerSession 
{
    #region Variables

    /// <summary>
    /// The client identifier
    /// </summary>
    private readonly string clientId = "XXXXXXXX";

    /// <summary>
    /// client secret
    /// </summary>
    private readonly string clientSecret = "XXXXXXXX";

    /// <summary>
    /// Cookie container that stores yammer authentication information
    /// </summary>
    private CookieContainer cookieContainer = new CookieContainer(2);

    /// <summary>
    /// The user code sent in response to login request
    /// </summary>
    private string userCode;

    /// <summary>
    /// The user email
    /// </summary>
    private string email;

    /// <summary>
    /// The user password
    /// </summary>
    private SecureString password;

    #endregion

    #region Methods

    /// <summary>
    /// Gets the supported yammer version
    /// </summary>
    public static int SupportedVersion
    {
        get
        {
            return 1;
        }
    }

    /// <summary>
    /// Gets the client id.
    /// </summary>
    public string ClientId
    {
        get
        {
            return this.clientId;
        }
    }

    /// <summary>
    /// Gets the authenticity token.
    /// </summary>
    /// <value>
    /// The authenticity token.
    /// </value>
    public string AuthenticityToken { get; private set; }

    /// <summary>
    /// Gets the token.
    /// </summary>
    /// <value>
    /// The token.
    /// </value>
    public string Token { get; private set; }

    /// <summary>
    /// Connects the specified connection.
    /// </summary>
    public override void Connect()
    {
        this.InternalLogin(this.Connection.User, this.Connection.Password);            
    }

    /// <summary>
    /// Disconnects this instance.
    /// </summary>
    public override void Disconnect()
    {            
        // Log out
        this.InternalLogout(this.Connection.Address);            
    }

    /// <summary>
    /// Creates the web request to a service endpoint.
    /// </summary>        
    /// <param name="serviceEndpoint">The service endpoint.</param>
    /// <returns>
    /// A new HTTP web request.
    /// </returns>
    public string GetEndpoint(string serviceEndpoint)
    {            
        // Get the uri
        var requestUri = string.Format("{0}/api/v{1}/{2}", this.Connection.Address, SupportedVersion, serviceEndpoint);

        // return the result
        return requestUri;
    }

    /// <summary>
    /// Connects the specified email.
    /// </summary>
    /// <param name="email">The email.</param>
    /// <param name="password">The password.</param>
    private void InternalLogin(string email, SecureString password)
    {            
        this.email = email;
        this.password = password;

        // Get the user code.
        this.GetUserCode();

        // Now get the bearer token
        this.GetBearerToken(this.userCode);            
    }

    /// <summary>
    /// Gets the user code.
    /// </summary>                        
    private void GetUserCode()
    {            
        string yammerAuthUrl = string.Format("https://www.yammer.com/dialog/oauth?client_id={0}", this.clientId);
        string yammerSessionUrl = string.Format("https://www.yammer.com/session?client_id={0}", this.clientId);

        // The authenticity token
        string authenticityToken = string.Empty;

        // Make a get request to Yammer authentication endpoint and get the response
        using (HttpWebResponse webResponse = this.MakeGetRequestToEndPoint(yammerAuthUrl))
        {
            // Set the cookies
            this.SetCookies(webResponse);

            // Look for authenticity token
            authenticityToken = this.GetAuthenticityToken(SessionHelper.ConvertResponseStreamToString(webResponse, Encoding.UTF8));
        }

        if (!string.IsNullOrEmpty(authenticityToken))
        {
            // Construct the post body with user login information
            string postBody = string.Format(
                        "{0}{1}{2}{3}{4}{5}{6}",
                        "utf8=%E2%9C%93&authenticity_token=",
                        HttpUtility.UrlEncode(authenticityToken),
                        "&network_permalink=&login=",
                        HttpUtility.UrlEncode(this.email),
                        "&password=",
                        HttpUtility.UrlEncode(this.password.ConvertToUnsecureString()),
                        "&remember_me=off");

            // Make the first post for User Code
            HttpWebResponse sessionPostWebResponse = this.MakePostRequestToEndPoint(postBody, yammerSessionUrl);
            string postResults = this.GetResponseAsString(sessionPostWebResponse);

            // Get the next auth token that was returned. This will be used for logout purposes
            this.AuthenticityToken = this.GetAuthenticityToken(postResults);

            using (HttpWebResponse webResponse = this.MakeGetRequestToEndPoint(yammerAuthUrl, true))
            {
                // Now look for the query string and set the user code
                this.userCode = webResponse.ResponseUri.Query;

                // Check whether we are in Authorization Page
                if (this.userCode.IndexOf("?client_id") >= 0)
                {
                    // Construct the yammer network name
                    string yammerNetworkName = webResponse.ResponseUri.AbsolutePath.Substring(0, webResponse.ResponseUri.AbsolutePath.ToLower().IndexOf("dialog/"));

                    // Construct the yammer decision url
                    string yammerUserAuthDecisionUrl = string.Format(
                                    "{0}{1}{2}{3}{4}",
                                    "https://www.yammer.com",
                                    yammerNetworkName,
                                    "oauth2/decision?client_id=",
                                    this.clientId,
                                    "&redirect_uri=https%3A%2F%2Fwww.yammer.com&response_type=code");

                    // Construct the Payload for authorization page
                    string payLoad = "utf8=%E2%9C%93&authenticity_token=" + HttpUtility.UrlEncode(this.AuthenticityToken) + "&allow=Allow";

                    // Authorize the app by posting the request 
                    using (HttpWebResponse decisionPostWebResponse = this.MakePostRequestToEndPoint(payLoad, yammerUserAuthDecisionUrl))
                    {
                        // Reset the user Code
                        this.userCode = decisionPostWebResponse.ResponseUri.Query;
                    }
                }

                // App should have been granted access at this point if it did not already have access. 
                // Now check whether the code is present in the query string
                if (this.userCode.IndexOf("?code=") < 0)
                {
                    throw new ArgumentException(Properties.ErrorMessges.UnableToLogin);
                }

                this.userCode = this.userCode.Replace("?code=", string.Empty);
            }
        }            
    }

    /// <summary>
    /// Get Yammer Authenticity Token
    /// </summary>
    /// <param name="rawHtml">The Yammer response that was got after posting to yammer endpoint</param>
    /// <returns>The Yammer authenticity token</returns>
    private string GetAuthenticityToken(string rawHtml)
    {            
        string result = string.Empty;

        int at = rawHtml.IndexOf("<meta name=\"authenticity_token\" id=\"authenticity_token\"");

        if (at > -1)
        {
            // Get the authenticity token string
            int et = rawHtml.IndexOf("/>", at + 1);
            string tokenText = rawHtml.Substring(at, et - at);

            // Get the token value
            int ts = tokenText.IndexOf("content=");
            int es = tokenText.LastIndexOf("\"");

            result = tokenText.Substring(ts + 9, es - ts - 9);
        }

        return result;
    }

    /// <summary>
    /// Perform a get request to an endpoint and return the Http response
    /// </summary>
    /// <param name="endPoint">The endpoint to make the request</param>
    /// <param name="addCookies">Should cookies be added to the request</param>
    /// <returns>The Http Web Response</returns>
    private HttpWebResponse MakeGetRequestToEndPoint(string endPoint, bool addCookies = false)
    {            
        HttpWebRequest webRequest = WebRequest.CreateHttp(endPoint);

        webRequest.Method = "GET";
        if (addCookies)
        {
            webRequest.CookieContainer = this.cookieContainer;
        }

        return (HttpWebResponse)webRequest.GetResponse();
    }

    /// <summary>
    /// Read the cookies from the web response object and store it in the cookie container instance variable
    /// </summary>
    /// <param name="webResponse">The Web Response object</param>
    private void SetCookies(HttpWebResponse webResponse)
    {            
        const string YAMTRAK_COOKIE = "yamtrak_id";
        const string SESSION_COOKIE = "_workfeed_session_id";
        const string LOGIN_CSRF_TOKEN_COOKIE = "login_csrf_token";

        string cookies = webResponse.Headers["Set-Cookie"];
        if (string.IsNullOrEmpty(cookies))
        {
            this.cookieContainer = new CookieContainer();
        }
        else
        {
            // Split the cookie based on , and ;
            string[] sepChar = new string[2];
            sepChar[0] = ",";
            sepChar[1] = ";";
            string[] cookieArray = cookies.Split(sepChar, StringSplitOptions.None);

            // Declare variables to hold the different types of cookies
            string login_csrf_token = string.Empty;
            string yammerTrakToken = string.Empty;
            string sessionToken = string.Empty;

            // Parse the cookie array and store the cookies in the array
            for (int i = 0; i < cookieArray.Length; i++)
            {
                if (cookieArray[i].IndexOf(YAMTRAK_COOKIE) >= 0)
                {
                    yammerTrakToken = cookieArray[i];
                }
                if (cookieArray[i].IndexOf(SESSION_COOKIE) >= 0)
                {
                    sessionToken = cookieArray[i];
                }
                if (cookieArray[i].IndexOf(LOGIN_CSRF_TOKEN_COOKIE) >= 0)
                {
                    login_csrf_token = cookieArray[i];
                }
            }

            // Create the cookie container
            this.cookieContainer = new CookieContainer();

            // Get the value for each of the cookie and add it to the cookie container                
            if (!string.IsNullOrWhiteSpace(yammerTrakToken))
            {
                yammerTrakToken = yammerTrakToken.Substring(YAMTRAK_COOKIE.Length + 1);
                this.cookieContainer.Add(new Cookie(YAMTRAK_COOKIE, yammerTrakToken, "/", "www.yammer.com"));
            }
            if (!string.IsNullOrWhiteSpace(sessionToken))
            {
                sessionToken = sessionToken.Substring(SESSION_COOKIE.Length + 1);
                this.cookieContainer.Add(new Cookie(SESSION_COOKIE, sessionToken, "/", "www.yammer.com"));
            }
            if (!string.IsNullOrWhiteSpace(login_csrf_token))
            {
                login_csrf_token = login_csrf_token.Substring(LOGIN_CSRF_TOKEN_COOKIE.Length + 1);
                this.cookieContainer.Add(new Cookie(LOGIN_CSRF_TOKEN_COOKIE, login_csrf_token, "/", "www.yammer.com"));
            }
        }            
    }

    /// <summary>
    /// Make a post request to an endpoint and return the result
    /// </summary>
    /// <param name="postBody">The post request payload</param>
    /// <param name="endPoint">The endpoint</param>
    /// <returns>The response got from the server</returns>
    private HttpWebResponse MakePostRequestToEndPoint(string postBody, string endPoint)
    {            
        string responseString = string.Empty;

        HttpWebRequest webRequest = WebRequest.CreateHttp(endPoint);
        webRequest.Method = "POST";
        webRequest.CookieContainer = this.cookieContainer;
        webRequest.ContentType = "application/x-www-form-urlencoded";
        SessionHelper.WritePayLoadToWebRequest(webRequest, postBody);
        HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();

        return webResponse;
    }

    /// <summary>
    /// Get Response as string
    /// </summary>
    /// <param name="webResponse">The http web response object</param>
    /// <returns>The web response string</returns>
    /// <remarks>The Http Response object would be disposed after use</remarks>
    private string GetResponseAsString(HttpWebResponse webResponse)
    {            
        string responseString = string.Empty;

        using (webResponse)
        {
            responseString = SessionHelper.ConvertResponseStreamToString(webResponse, Encoding.UTF8);
        }

        return responseString;
    }

    /// <summary>
    /// Gets the user code.
    /// </summary>
    /// <param name="userCode">The user code.</param>
    /// <exception cref="System.TimeoutException">Waiting for login page load.
    /// or
    /// Waiting for post login page load.</exception>
    private void GetBearerToken(string userCode)
    {            
        string formatUri = string.Format("https://www.yammer.com/oauth2/access_token.json?client_id={0}&client_secret={1}&code={2}", this.clientId, this.clientSecret, userCode);

        Uri yammerUri = new Uri(formatUri);

        WebRequest webRequest = WebRequest.Create(yammerUri);
        webRequest.Method = "GET";

        using (WebResponse response = webRequest.GetResponse())
        {
            using (Stream responseStream = response.GetResponseStream())
            {
                DataContractJsonSerializer seralizer = new DataContractJsonSerializer(typeof(Model.JSON.Yammer.AccessTokenResponse));
                Model.JSON.Yammer.AccessTokenResponse accessTokenResponse = (Model.JSON.Yammer.AccessTokenResponse)seralizer.ReadObject(responseStream);

                if (string.IsNullOrWhiteSpace(accessTokenResponse.access_token.token))
                {
                    throw new InvalidOperationException("Unable to extract Yammer.com authorization bearer token.");
                }

                // Set the bearer token
                this.Token = accessTokenResponse.access_token.token;
            }
        }            
    }

    /// <summary>
    /// Internal logout.
    /// </summary>
    /// <param name="address">The address.</param>
    private void InternalLogout(string address)
    {            
        string formatUri = string.Format("{0}/logout?from=nav", address);

        Uri yammerUri = new Uri(formatUri);

        // Create request
        var request = HttpWebRequest.CreateHttp(yammerUri);

        // POST
        request.Method = "POST";

        // Set the cookie container
        request.CookieContainer = this.cookieContainer;

        // Sent the request body            
        request.ContentType = "application/x-www-form-urlencoded";
        string requestBody = string.Format(
            "authenticity_token={0}&_method=delete",
            HttpUtility.UrlEncode(this.AuthenticityToken));
        byte[] requestBodyUTF8 = Encoding.UTF8.GetBytes(requestBody);

        // Set the length before writing the request steam.
        request.ContentLength = requestBody.Length;

        // Write the request stream
        using (var requestStream = request.GetRequestStream())
        {
            using (StreamWriter streamWrite = new StreamWriter(requestStream))
            {
                streamWrite.Write(requestBody);
            }
        }

        // Make the request
        using (var response = request.GetResponse())
        {
            // Always read the response
            using (Stream responseStream = response.GetResponseStream())
            {
            }
        }
    }

    #endregion
}

      



In the above code, replace the Client ID, Client Secret, Email and Password. Then you can use the connect method to get the bearer token and disconnect to exit the yammer. Recently yammer changed the number of cookies that were passed back and forth and I fixed the problem

+2


source







All Articles