【问题标题】:How do I impersonate SAML/SSO from a computer?如何从计算机模拟 SAML/SSO?
【发布时间】:2021-05-05 19:42:11
【问题描述】:
我有一个需要定期访问的网站。从浏览器它工作正常。该网站给了我一个 15 分钟后过期的 cookie。如果我在一小时后返回服务器,它会将我重定向到 login.microsoft.com,它会将我重定向回服务器。
我需要在无人看管的计算机上做同样的事情。是否有说明我需要从目标服务器和 Microsoft IDP 服务器捕获哪些信息以允许我的计算机在会话 cookie 超时时更新其身份验证的文档?
【问题讨论】:
标签:
azure-active-directory
single-sign-on
saml-2.0
idp
【解决方案1】:
为了使用 Azure AD IDP 进行身份验证,我最终使用了 Puppeteer Sharp(它控制 Chromium 的无头版本)和以下函数(逐步完成它的步骤)进行身份验证。 SSOLogin 的参数如下:
- destination - 是位于 SSO 后面的 REST API
- email - 用于验证的电子邮件地址
- 密码 - 与电子邮件地址关联的密码
- 选择器 - API 中存在的元素选择器
- cookieParams - API 和 IDP 发送的 cookie
最初没有 cookie。但是,SSOLogin 返回当前的 cookie 集。如果 API 的 cookie 没有过期,登录是快速而简单的。如果 IDP cookie 尚未过期,您将被重定向回 API。如果 IDP 上的 cookie 已过期,则您可以使用电子邮件地址和密码登录。
在任何情况下,您都可以从 API 中提取 cookie 并使用它们进行调用。
使用的 Nuget 包:
-
Microsoft.AspNet.WebApi.Client (5.2.7)
-
PuppeteerSharp (5.0.0)
-
System.Net.Http.Json (5.0.0)
public static async Task<CookieParam[]> SSOLogin(CookieParam[] cookieParams, string destination, string email, string password, string selector)
{
var options = new LaunchOptions { Headless = true }; // Set to false to watch browser step through activities
var selectorOption = new WaitForSelectorOptions { Visible = true, Timeout = 10000 };
await new BrowserFetcher().DownloadAsync(); // Only needed the first time through
using var browser = await Puppeteer.LaunchAsync(options);
using var page = await browser.NewPageAsync();
await page.SetCookieAsync(cookieParams);
await page.GoToAsync(destination);
try
{
await page.WaitForSelectorAsync($"{selector}, input[name='loginfmt']", selectorOption);
}
catch (Exception e)
{
Console.WriteLine($"First page error: {e.Message}");
}
var url = page.Url;
if (url.StartsWith("https://login.microsoftonline.com/"))
{
if (await page.QuerySelectorAsync($"div[data-test-id='{email}']") != null)
{
await page.ClickAsync($"div[data-test-id='{email}']");
}
else
{
await page.WaitForSelectorAsync("input[name='loginfmt']:not(.moveOffScreen)", selectorOption);
await page.FocusAsync("input[name='loginfmt']");
await page.Keyboard.TypeAsync(email);
await page.WaitForSelectorAsync("input[type=submit]", selectorOption);
await page.ClickAsync("input[type=submit]");
}
await page.WaitForSelectorAsync("input[type=password]:not(.moveOffScreen)", selectorOption);
await page.FocusAsync("input[type=password]");
await page.Keyboard.TypeAsync(password);
await page.WaitForSelectorAsync("input[type=submit]", selectorOption);
await page.ClickAsync("input[type=submit]");
await page.WaitForSelectorAsync("input[name='DontShowAgain']:not(.moveOffScreen)", selectorOption);
await page.ClickAsync("input[name='DontShowAgain']");
await page.WaitForSelectorAsync("input[type=submit]", selectorOption);
await page.ClickAsync("input[type=submit]");
await page.WaitForSelectorAsync(selector, selectorOption);
}
return await page.GetCookiesAsync("https://login.microsoftonline.com/", destination);
}