2

I am using openIdDict's sample MVC application to implement the authorization code flow. However, I have an angular 6 app that I'm using for the landing page the user uses to authorize the request. I've got all the angular stuff working but when I submit my request to "connect/authorize" it is generating a 302. The 302 is being caught by the browser and the redirect is occurring, but I do not want that. I want the request to come as a 200 and then the angular app can control the redirect from there.

Reasons I want to do this: 1. The system I'm integrating with requires additional query string parameters to be populated in the redirect (state * others). I want my angular app to populate those and NOT connect/authorize. 2. The angular app will give the user additional instructions/information after they allow the authorization but before the redirect occurs.

My questions are this: 1. Is it possible to change the response code being generated by openiddict? 2. Am I way off track here and making this harder than it should be?

Startup.cs config

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

            });
Mike Becatti
  • 2,052
  • 1
  • 16
  • 32

2 Answers2

1

I decided to write my own middleware that would intercept the 302 request being generated by Identity and replace it with a 200 request with a JSON body. I'm sure this can be simplified and maybe I'm just missing something big and I'm way off course. The bottom line is this solution allows someone to implement the authorization code flow using ajax.

Startup.cs

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

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 This is my own class. You can make the response look however you want.

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

    public string RedirectUri { get; set; }
}
Mike Becatti
  • 2,052
  • 1
  • 16
  • 32
0

There's only one case where OpenIddict will transparently do that: it's when you explicitly enable request caching:

services.AddOpenIddict()
    .AddCore(options =>
    {
        // ...
    })

    .AddServer(options =>
    {
        // ...
        options.EnableRequestCaching();
    });

When enabled, this feature stores the authorization request in IDistributedCache and replaces the authorization request parameters by a single request_id parameter, that is used to represent the request. For that, it indeed uses a 302 redirect.

If you don't like this behavior, simply don't call options.EnableRequestCaching() in the OpenIddict server options.

Kévin Chalet
  • 39,509
  • 7
  • 121
  • 131
  • I'm not currently calling EnableRequestCaching. I've updated my question with my startup.cs config. – Mike Becatti Aug 06 '18 at 18:12
  • 1
    Then it's not related to OpenIddict. You're most likely using cookies authentication (e.g via ASP.NET Core Identity), and the default behavior is to redirect you to the login page when you're not already authenticated (using a 302 status code). – Kévin Chalet Aug 06 '18 at 18:19
  • Yes that was correct after I reviewed what was happening. Now the redirect is trying to take me to the redirect URL I specify when calling connect/authorize. Is there a way to disable that? – Mike Becatti Aug 07 '18 at 21:13
  • Basically I'm trying to do the same thing as this question: https://stackoverflow.com/questions/36688035/google-oauth-400-response-no-access-control-allow-origin-header-is-present-on – Mike Becatti Aug 07 '18 at 22:23
  • The fact you're trying to query the authorization endpoint using XHR makes me think you're doing crazy things OAuth2/OpenID Connect were not made for :D – Kévin Chalet Aug 08 '18 at 17:30
  • Well that may be very likely. :) How else do I let the user land on an angular page that allows the user to authorize an application to talk to my web api? – Mike Becatti Aug 08 '18 at 17:37
  • I'm sure I'm missing something fundamental here but what? – Mike Becatti Aug 08 '18 at 17:39