首页 > 解决方案 > OpenIdDict - 禁用 XHR 请求的“连接/授权”重定向

问题描述

我正在使用 openIdDict 的示例 MVC 应用程序来实现授权代码流。但是,我有一个 Angular 6 应用程序,用于用户用于授权请求的登录页面。我已经让所有有角度的东西都在工作,但是当我提交我的“连接/授权”请求时,它正在生成一个 302。302 被浏览器捕获并且正在发生重定向,但我不希望那样。我希望请求以 200 的形式出现,然后角度应用程序可以从那里控制重定向。

我想这样做的原因: 1. 我正在集成的系统需要在重定向中填充额外的查询字符串参数(状态 * 其他)。我希望我的 Angular 应用程序填充这些而不是连接/授权。2. Angular 应用程序将在用户允许授权后但在重定向发生之前向用户提供额外的说明/信息。

我的问题是: 1. 是否可以更改 openiddict 生成的响应代码?2. 我是不是偏离了轨道,让事情变得比应该做的更难?

Startup.cs 配置

            services.AddOpenIddict()
            .AddCore(coreOptions =>
            {
                coreOptions.UseEntityFrameworkCore().UseDbContext<ApplicationDbContext>();
            })
            .AddServer(serverOptions =>
            {
                serverOptions.UseMvc();

                serverOptions.EnableAuthorizationEndpoint(oauthOptions.AuthorizePath)
                .EnableTokenEndpoint(oauthOptions.TokenPath)
                       .EnableLogoutEndpoint(oauthOptions.LogoutPath);

                serverOptions.AllowAuthorizationCodeFlow()
                       .AllowPasswordFlow()
                       .AllowRefreshTokenFlow();

                serverOptions.SetAccessTokenLifetime(new TimeSpan(0, oauthOptions.AccessTokenLifetimeMinutes, 0));
                serverOptions.SetRefreshTokenLifetime(new TimeSpan(0, oauthOptions.RefreshTokenLifetimeMinutes, 0));

                if (!oauthOptions.RequireSSL)
                {
                    serverOptions.DisableHttpsRequirement();
                }

            });

标签: google-oauthopeniddict

解决方案


我决定编写自己的中间件来拦截 Identity 生成的 302 请求,并将其替换为带有 JSON 正文的 200 请求。我敢肯定这可以简化,也许我只是错过了一些大事,而且我偏离了方向。底线是这个解决方案允许某人使用 ajax 实现授权代码流。

启动.cs

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        //put this before any other middleware runs
        app.UseMiddleware<AuthorizeRequestMiddleware>();
        ...
    }

授权请求中间件

public class AuthorizeRequestMiddleware
{
    private readonly RequestDelegate _next;

    public AuthorizeRequestMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        context.Response.OnStarting(AuthorizeStartingHandler, state: context);

        // Let the middleware pipeline run
        await _next(context);
    }

    private Task AuthorizeStartingHandler(object context)
    {

        HttpContext httpContext = (HttpContext)context;
        if (httpContext.Request.Path.HasValue && httpContext.Request.Path.Value == "/connect/authorize")
        {
            httpContext.Response.StatusCode = (int)HttpStatusCode.OK;
            AuthorizationCodeResponse responseBody = new AuthorizationCodeResponse(httpContext.Response.Headers["Location"][0]);
            httpContext.Response.WriteAsync(JsonConvert.SerializeObject(responseBody));
        }

        return Task.CompletedTask;
    }
}

AuthorizationCodeResponse 这是我自己的课程。您可以使响应看起来像您想要的那样。

public class AuthorizationCodeResponse
{
    public AuthorizationCodeResponse(string redirectUri)
    {
        this.RedirectUri = redirectUri;
    }

    public string RedirectUri { get; set; }
}

推荐阅读