如何从OKTA获得SAML响应以进行单元/集成测试

时间:2017-01-13 16:50:06

标签: c# unit-testing integration-testing saml okta

我正在研究他们通过OKTA的SAML进行身份验证的项目。我已经成功地将SAMLResponse(通过POST方法)发送到网站的集成工作。

在真正的TDD方式中,我开始编写一些单元测试。我的单元测试采用SAMLResponse(Base64编码)。但是,我的所有单元测试都有效,因为SAMLResponse只有几分钟的生命周期(到期时间),我的单元测试在几分钟后就会中断。

所以我需要定期登录OKTA,然后使用Chrome开发工具捕获发送到我的开发站点的流量。然后我将SAMLResponse复制并粘贴到我的单元测试中,然后返回通过单元测试。显然这不是一个理想的情况。

所以我的问题是如何以自动方式(最好是在C#中)登录Okta才能获得SAMLResponse?我假设有一些我可以使用用户名和密码POST到的URL并返回SAMLReponse。我所有的小提琴手试图理解所需的沟通都让我感到沮丧。我正在寻找你可能有的任何指导。提前谢谢。

2 个答案:

答案 0 :(得分:4)

我提出了一个有效的解决方案,并希望与社区分享。 我不确定根据其他作者(JoëlFranusic)的有用反馈回答我自己的问题的协议。如果我违反协议,请告诉我。

感谢JoëlFranusic的指示。我实现了他的1.2解决方案(用户代理与Okta客户端)在他的参考资料和Okta网站上的一些其他文档之间,我最终能够拼凑出代码。

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

答案 1 :(得分:2)

有几种方法可以进行您建议的测试,以下是立即想到的内容:

  1. 写一个简单的HTTP&#34;用户代理&#34;在C#中使用RestSharp或类似的库。
  2. 针对外部模拟IdP构建集成测试。
  3. 修改SAMLResponse并使用您自己的密钥重新签名。
  4. 我将在下面详细介绍每种方法。

    编写简单的HTTP&#34;用户代理&#34;

    我建议使用这种方法,我建议采取以下两种方法之一:

    1. 编写将检测并填写用户名和密码表单字段的通用用户代理。我在Python中编写了一个名为&#34; saml-messenger&#34;采用这种方法,核心代码位于名为messenger.py的文件中。
    2. 使用Okta的API获取会话令牌并使用它来获取SAMLResponseokta-aws-cli-assume-role项目采用这种方法。 fetching the session tokenexchanging that session token for a SAMLResponse的代码均可在src/main/java/com/okta/tools/awscli.java文件中找到。
    3. 第一种方法更通用,应该与任何带有用户名和密码字段的IdP一起使用。第二种方法可能是您正在寻找的,但具体针对Okta。

      在任何一种情况下,我建议在Okta中创建一个被锁定并仅用于测试的特殊用户。

      针对模拟IdP构建集成测试

      这种方法可以让您设置一个模拟IdP,在没有身份验证的情况下为您提供SAMLResponse,我之前已使用saml-idp项目执行此操作。

      这种方法的优点是 需要更少的C#供您编写,但代价是承担另一种依赖。

      修改重新签名SAMLResponse

      我真的只是为了完整性而在这里包含这个选项,并且作为警告你不要尝试这种方法的方法。了解SAML会让你面对疯狂和遗憾。我不建议采用这种方法。