简体   繁体   English

如何在 C# MVC 中使用 Azure AD 实现注销后

[英]How to implement a post-logout with Azure AD in C# MVC

I'm working on a web app that uses Azure AD for user authentication.我正在开发一个 web 应用程序,该应用程序使用 Azure AD 进行用户身份验证。 However, I am struggling to redirect the user to the home page after they successfully signed out.但是,我很难在用户成功注销后将其重定向到主页。 I've tried following this documentation , but this isn't the solution I am looking for.我已尝试按照此文档进行操作,但这不是我要寻找的解决方案。

In SignOut() in HomeController.cs, is there an alternative way without returning在 HomeController.cs 的SignOut()中,有没有不返回的替代方法

SignOut(new AuthenticationProperties { RedirectUri = callbackUrl }, 
        CookieAuthenticationDefaults.AuthenticationScheme, 
        OpenIdConnectDefaults.AuthenticationScheme)

This is what I have:这就是我所拥有的:

Index.cshtml索引.cshtml

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <p>@ViewBag.test</p>
    @if (User?.Identity?.IsAuthenticated ?? false)
    {
        <h2>User is login</h2>
        <a asp-controller="Home" asp-action="SignOut">Sign out</a>
    }
    else
    {
        <h2>User is not login</h2>
    }
</div>

HomeController.cs家庭控制器.cs

using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Authorization;
using HealthAD.Models;
using HealthAD.Graph;

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;

namespace HealthAD.Controllers;

[Authorize(Policy = "OpenIdConnect")]
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
public class HomeController : Controller
{
    private readonly GraphProfileClient _graphProfileClient;
    private readonly ITokenAcquisition _tokenAcquisition;
    private readonly ILogger<HomeController> _logger;
    public string UserDisplayName { get; private set; } = "";

    public HomeController(
                        ILogger<HomeController> logger,
                        GraphProfileClient graphProfileClient,
                        ITokenAcquisition tokenAcquisition
                        )
    {
        _logger = logger;
        _graphProfileClient = graphProfileClient;
        _tokenAcquisition = tokenAcquisition;
    }

    public async Task<ActionResult<Microsoft.Graph.User?>> Test()
    {
        // await OnGetAsync();
        var test = await _graphProfileClient.GetUserProfile();
        return test;
    }

    [AllowAnonymous]
    public IActionResult Index()
    {
        ViewBag.test = "Test";
        return View();
    }

    [HttpGet]
    public IActionResult SignOut()
    {
        var callbackUrl = Url.Action(nameof(SignedOut), "Home", values: null, protocol: Request.Scheme);
        return SignOut
        (
            new AuthenticationProperties { RedirectUri = callbackUrl },
            CookieAuthenticationDefaults.AuthenticationScheme,
            OpenIdConnectDefaults.AuthenticationScheme
        );
    }

    [HttpGet]
    public IActionResult SignedOut()
    {
        if (User?.Identity?.IsAuthenticated ?? false)
        {
            return RedirectToAction(nameof(HomeController.Index), "Index");
        }
        return RedirectToAction(nameof(HomeController.Index), "Index");
    }

    public async Task<IActionResult> Privacy()
    {
        var test = await _graphProfileClient.GetUserProfile();

        ViewBag.name = test.DisplayName;

        return View();
    }

    public async Task OnGetAsync()
    {
        var user = await _graphProfileClient.GetUserProfile();
        UserDisplayName = user.DisplayName;
    }
}

Program.cs程序.cs

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Identity.Web;
using HealthAD.Graph;

var builder = WebApplication.CreateBuilder(args);

var initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(" ");

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services
    .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
    .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
    .AddInMemoryTokenCaches();

builder.Services.AddAuthorization(configurations =>
{
    configurations.AddPolicy("OpenIdConnect", new AuthorizationPolicyBuilder()
        .AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme)
        .RequireAuthenticatedUser().Build()
    );
});

builder.Services.AddScoped<GraphProfileClient>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();
app.UseAuthentication();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

appsettings.json应用程序设置.json

{
    "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "TenantId": "xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "Domain": "domain.com",
        "CallbackPath": "/signin-oidc",
        "SignedOutCallbackPath ": "/signout-oidc",
        "ClientSecret": "xxxxx~xxxxxx-xxxxxx-xxxxxxxxxxxxxxxxx"
    },
    "DownstreamApi": {
        "BaseUrl": "https://graph.microsoft.com/v1.0",
        "Scopes": "user.read"
    },
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft.AspNetCore": "Warning"
        }
    },
    "AllowedHosts": "*"
}

Please note that the order in the middleware is must be like below which is important.请注意,中间件中的顺序必须如下所示,这一点很重要。

 app.UseAuthentication();
    app.UseAuthorization();

Try to construct a sign out URI in your application so that when the user clicks on the Logout link or button, you redirect your users to that URI.尝试在您的应用程序中构建注销 URI,以便当用户单击注销链接或按钮时,您将用户重定向到该 URI。 The format of a sign out URI is:注销 URI 的格式为:

https://login.microsoftonline.com/{0}/oauth2/logout?post_logout_redirect_uri=

Also note that without session the logout redirect failsi.e;另请注意,如果没有 session,注销重定向会失败; If we would use the request "https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=https%3A%2F%2Flocalhost%2Fmyapp%2Flogout%2F%3F&client_id=;"如果我们使用请求"https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=https%3A%2F%2Flocalhost%2Fmyapp%2Flogout%2F%3F&client_id=;" without a session, it would like take you to the page which shows, "Successfully logged out", but it won't redirect, as AzureAD, won't just redirect without a proper session since that's not a safe practice.如果没有 session,它会带你到显示“成功注销”的页面,但它不会重定向,因为 AzureAD 不会在没有正确的 session 的情况下重定向,因为这不是安全的做法。

  • If required also go to app registration in portal and set the logout url as reply url.如果需要也 go 在门户中注册应用程序并将注销 url设置为回复 url。

Please check AzureAD microsoft authentication library for-js issues请检查AzureAD 微软身份验证库 for-js 问题

  • In AccountController, try to modify the callback redirect url. As a workaround try to build you own AccountController something like below and Redirect the user to: https://login.microsoftonline.com/common/oauth2/logout And then logout redirect back to your app home page.在 AccountController 中,尝试修改回调重定向 url。作为解决方法,尝试构建您自己的 AccountController,如下所示,并将用户重定向到: https:https://login.microsoftonline.com/common/oauth2/logout然后注销重定向回您的应用主页。

     public class AccountController: Controller { [HttpGet] public IActionResult SignIn() {... } [HttpGet] public IActionResult SignOut() { var callbackUrl = Url.Action(nameof(SignedOut), "Account", values: null, protocol: Request.Scheme); return SignOut( new AuthenticationProperties { RedirectUri = callbackUrl }, CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme); } [HttpGet] public IActionResult SignedOut() { if (User.Identity.IsAuthenticated) { // Redirect to home page if the user is authenticated. return RedirectToAction(nameof(HomeController.Index), "Home"); } return RedirectToAction(nameof(HomeController.Index), "pathtoberedirectedto"); }

References:参考:

  1. How to specify custom logout URL when using Azure AD authentication in .NET core - Stack Overflow 在.NET核心中使用Azure AD身份验证时如何指定自定义注销URL - Thinbug
  2. asp.net mvc 4 - Clear session on Logout MVC 4 - Stack Overflow asp.net mvc 4 - 在注销 MVC 4 时清除 session - 堆栈内存溢出

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM