How to get SAML response from OKTA for unit / integration testing

I am working on a project where they authenticate through SAML from OKTA. I successfully got the integration where SAMLResponse is sent (via the POST method) to the website.

In true TDD style, I started by writing some unit tests. My unit tests use SAMLResponse (which is Base64 encoded). However, all my unit tests work because SAMLResponse only has a lifetime (expires) for several minutes, my unit tests are interrupted after a few minutes.

So, I need to log into OKTA periodically, and then using Chrome dev tools I can track the traffic sent to my dev site. Then I copy and paste SAMLResponse into my unit tests and return to the unit tests. Obviously, this is not a desirable situation.

So my question is: how can I enter Okta in an automatic way (preferably in C #) to get SAMLResponse? I assume that there is some kind of URL with which I can send a POST message with username and password and return SAMLReponse. All my Fiddler’s attempts to understand what is required for communication left me disappointed. I am looking for any guidance you may have. Thanks in advance.

+4
source share
2 answers

I came up with a working solution and wanted to share it with the community. I am not sure of the protocol for answering my question, based on helpful reviews from other authors (Joël Franusic). If I break the protocol, let me know.

Thanks to Joël Franusic for pointers. I implemented its solution 1.2 (User Agent with Okta client). Between his links and several other documents on the Okta website, I managed to eventually combine the working code.

private static async Task<string> GetTestSamlResponse()
    {
        try
        {
            // settings specific to my Okta instance
            string username = "USERNAME GOES HERE";
            string password = "PASSWORD GOES HERE";
            var apiToken = "API TOKEN GOES HERE";

            // this is the unique domain issued to your account.  
            // If you setup a dev account you'll have a domain in the form https://dev-<AccountNumber>.oktapreview.com.
            // account number is a unique number issues by Okta when you sign up for the account
            var baseUrl = "YOUR BASE URL GOES HERE";

            // In Okta Admin UI, click "Applications" in main menu, choose your app, click "Sign On" tab.  Under Sign On Methods, then under SAML 2.0, click "View Setup Instructions"
            // Get the url called "Identity Provider Single Sign-On URL", paste it in th below line
            var ssoUrl = "YOUR SSO URL GOES HERE";

            // construct an Okta settings object
            var settings = new Okta.Core.OktaSettings
            {
                ApiToken = apiToken,
                BaseUri = new Uri(baseUrl)
            };

            // get session token from Okta
            var authClient = new Okta.Core.Clients.AuthClient(settings);
            var authResponse = authClient.Authenticate(username, password);
            var sessionToken = authResponse.SessionToken;

            // start session and get a cookie token
            var sessionsClient = new Okta.Core.Clients.SessionsClient(settings);
            var session = sessionsClient.CreateSession(sessionToken);
            var cookieToken = session.CookieToken;

            // using the cookie token, get the SAMLResponse from Okta via a HTTP GET.
            var httpClient = new System.Net.Http.HttpClient();

            // add User-Agent header, because apparently Okta is expecting this information.  
            // If you don't pass something, the Okta site will return a 500 - Internal Server error
            httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "UnitTest");

            // add the cookie token to the URL query string
            string url = string.Format("{0}?onetimetoken={1}", ssoUrl, cookieToken);

            // do the HTTP GET
            using (var response = await httpClient.GetAsync(url))
            {
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    // read the HTML returned
                    string html = await response.Content.ReadAsStringAsync();

                    // parse the HTML to get the SAMLResponse (using HtmlAgilityPack from NuGet)
                    HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
                    htmlDoc.LoadHtml(html);
                    // from the input field called SAMLResponse, get the "value" attribute
                    string samlResponse = htmlDoc.DocumentNode.SelectSingleNode("//input[@name='SAMLResponse']").Attributes["value"].Value;
                    return samlResponse;
                }
                else
                    throw new Exception(string.Format("Error getting SAML Response {0}", response.StatusCode));
            }
        }
        catch (Exception ex)
        {
            throw;
        }
    }
+4
source

There are several ways to do what you offer, which immediately comes to mind:

  • Write a simple "User Agent" HTTP Agent in C # using a library like RestSharp or similar.
  • Build an integration test with an external false IdP.
  • SAMLResponse .

.

HTTP-

, :

IdP . , , , , Okta.

Okta, .

IdP

mock IdP, SAMLResponse , saml-idp, .

, #, .

SAMLResponse

, . SAML . .

+2

Source: https://habr.com/ru/post/1666737/


All Articles