Использование ASP. NET Core w /. NET Core 3.1.
OID C поток аутентификации, обработанный Microsoft.AspNetCore.Authentication.OpenIdConnect
.
После того, как я начал получать ошибку, я фактически включил вышеуказанное пространство имен в моем проекте, так что я могу устанавливать точки останова и легко проверять данные.
Согласно этому документу: https://developer.microsoft.com/en-us/office/blogs/authentication-in-microsoft-teams-apps-tabs/ то, что я пытаюсь достичь, должно быть возможным.
Допустим, мы настроили вкладку в командах Microsoft, которая размещается в нашем ASP. NET Core MVC приложении на https://localhost:60151
(не через IIS Express, но самостоятельно). Приложение MS Teams может получить доступ к нашему приложению с помощью ngrok , которое запускается с помощью командной строки:
./ngrok http https://localhost:60151
В этом приложении TabController определен следующим образом:
public class TabController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize]
public IActionResult TabAuthStart()
{
return RedirectToAction(nameof(TabAuthEnd), new { serializedClaims = string.Join("; ", User.Claims.Select(x => $"{x.Type}: {x.Value}")) });
}
// for simplicity, let's assume no one navigates to this action
// except when redirected from TabAuthStart after the authentication flow completes
public IActionResult TabAuthEnd(string serializedClaims)
{
return View(model: serializedClaims);
}
}
Пусть представление индекса будет определено следующим образом:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>MS Teams Tab</title>
<script src="https://statics.teams.microsoft.com/sdk/v1.4.2/js/MicrosoftTeams.min.js" crossorigin="anonymous"></script>
<script>
// Call the initialize API first
microsoftTeams.initialize();
function authenticate() {
microsoftTeams.authentication.authenticate({
url: window.location.origin + "/tab/tabauthstart",
successCallback: function (result) {
// do something on success
},
failureCallback: function (reason) {
// do something on failure
}
});
}
</script>
</head>
<body>
@if (!User.Identity.IsAuthenticated)
{
<button onclick="authenticate()">authenticate</button>
}
else
{
<p>Hello, @User.Identity.Name</p>
}
</body>
</html>
При перенаправлении в / tab / tabauthstart атрибут [Authorize]
гарантирует, что обработчик вызова OID C примет запрос и перенаправит его. на настроенную страницу авторизации IdentityServer.
Если говорить об обработчике OID C, он настроен в Startup.cs следующим образом:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
options.Cookie.Name = "mvchybridautorefresh";
})
.AddOpenIdConnect(options =>
{
options.Authority = "https://localhost:44333/"; // The local IdentityServer instance
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.ClientId = "msteams";
options.ResponseType = "code id_token"; // Hybrid flow
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
options.ClaimActions.MapAllExcept("iss", "nbf", "exp", "aud", "nonce", "iat", "c_hash");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
// The following were added in despair. However, they don't have any effect on the process.
options.CorrelationCookie.Path = null;
options.CorrelationCookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
options.CorrelationCookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
options.CorrelationCookie.HttpOnly = false;
});
, а затем у нас есть метод Configure
, например это:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
});
}
В IdentityServer предположим, что клиент настроен правильно.
Итак, когда мы запускаем наше приложение и go на вкладке в приложении Microsoft Teams, мы видим кнопку с надписью «аутентифицировать» , Нажатие этой кнопки запускает обработчик запроса OID C, который подготавливает свойства аутентификации, записывает одноразовые и корреляционные файлы cookie в коллекцию Response.Cookies.
После генерации Id корреляции у нас есть следующие параметры запроса:
- Схема: https
- Хост: [назначенный поддомен] .ngrok.io
- Путь: / tab / tabauthstart
Заголовок ответа Set-Cookie
содержит следующее:
.AspNetCore.OpenIdConnect.Nonce.blabla; expires=Tue, 21 Jan 2020 20:54:28 GMT; path=/signin-oidc; secure; samesite=none; httponly,
.AspNetCore.Correlation.OpenIdConnect.blabla; expires=Tue, 21 Jan 2020 20:58:57 GMT; path=/signin-oidc; secure; samesite=none
После этого мы перенаправлены на страницу входа IdSrv .
Там мы вводим наш знак в деталях и завершаем sh процесс входа в систему, что возвращает нас к нашему обработчику OID C, который затем проверяет наличие корреляции cook ie. Однако средство корреляции ie не существует и, следовательно, генерируется исключение, говорящее «Корреляция не удалась».
Это параметры запроса перед проверкой корреляции:
- Схема: https
- Хост: [назначенный поддомен] .ngrok.io
- Путь: / signin-oid c
Коллекция файлов cookie пуста. Почему?
Чтобы сделать вещи еще более интересными, при открытии браузера перейдите к https: // [назначенный поддомен] .ngrok.io / tab / index и запустите аутентификацию, нажав кнопку, процесс завершится успешно, и мы, наконец, перенаправлены на / tab / tabAuthEnd , чье представление, кстати, выглядит так:
@model string
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Authentication successful</title>
<script src="https://statics.teams.microsoft.com/sdk/v1.4.2/js/MicrosoftTeams.min.js" crossorigin="anonymous"></script>
<script>
// Call the initialize API first
microsoftTeams.initialize();
microsoftTeams.authentication.notifySuccess(@Model);
</script>
</head>
<body>
<p>Redirecting back..</p>
</body>
</html>
Итак ... есть какая-нибудь подсказка, почему файлы cookie OID C не сохраняются при перенаправлении на страницу входа в IdSrv?