4

Related questions

Problem

I have a service running under a specific path on a domain, e.g. https://www.example.com/myservice. The myservice path is dedicated to my service and other services have other paths at the same domain. It is setup like this in startup configure:

app.Map("/myservice", builder =>
{
    builder.UseStaticFiles();
    builder.UseMvcWithDefaultRoute();
});

I am using a library that implements a custom RemoteAuthenticationHandler. By default, the callback path routes to /x-callback which results in the browser trying to access https://www.example.com/x-callback.

Since my service does not process url's without the /myservice prefix I get a 404. Changing the URL in the browser to /myservice/x-callback manually loads the callback and all is fine.

I can set the callback path for the handler in startup options as expected in startup configure services.

services.AddSomething(options =>
{
    options.AddThingX((o) =>
    {
        o.CallbackPath = new PathString($"/myservice{o.CallbackPath}");
    });
});

When I set the callback path like that the browser tries to load /myservice/x-callback. But, this URL now returns a 404. It seems the handler for the callback also has its URL changed. Changing the URL in the browser to /myservice/myservice/x-callback loads the callback as expected.

The RemoteAuthenticationHandler

This is the code in the handler that handles the challenge and uses the callback path. It sets the callback path as a query parameter to the login url.

protected override Task HandleChallengeAsync(AuthenticationProperties properties)
{
    // Add options etc
    // ...
    // ...

    // This defines the login url, with a query parameter for the CallbackPath
    var loginUrl = GetLoginUrl(loginOptions);
    Response.Redirect(loginUrl);

    return Task.CompletedTask;
}

private string GetLoginUrl(MyServiceLoginOptions loginOptions)
{
    // This is where the return url is set. The return url
    // is used after login credentials are verified.
    return $"{Options.LoginPath}" +
            $"?returnUrl={UrlEncoder.Encode(Options.CallbackPath)}" +
            $"&loginOptions={UrlEncoder.Encode(_loginOptionsProtector.Protect(loginOptions))}";
}

The login controller

This is where the user can provide the credentials and have them verified. After verification, the user is redirected to the callback path.

private async Task<ActionResult> ChallengeComplete(LoginStatusRequest request, ChallengeResponse challengeResponse)
{
    // auth logic
    // ...
    // All is fine, the users credentials have been verified. Now
    // we can redirect to the CallbackPath.
    return Ok(Response.Finished(returnUri));
}

Note I could do a URL rewrite but if possible, I would like to use the "correct" /myservice path to avoid confusion and perhaps causing issues for other services (though very unlikely).

Question

How can I prefix the callback path with /myservice so my application can process it without also adding the duplicate prefix?

10
  • Where's your call to UseAuthentication? It's not shown inside Map, so is it on the root IApplicationBuilder? Commented Oct 8, 2019 at 11:51
  • @KirkLarkin I'm using IdentityServer and it is inside Configure as you assume: app.UseIdentityServer();. Commented Oct 8, 2019 at 18:45
  • Disregarding the question and going right for a solution: would o.CallbackPath = new PathString(o.CallBackPath); work? Commented Oct 8, 2019 at 19:42
  • @LosManos Nice try! Unfortunately no work :P. It redirects to /x-callback and not /myservice/x-callback. Commented Oct 8, 2019 at 19:56
  • Is it new PathString that fools you then? Commented Oct 8, 2019 at 19:59

1 Answer 1

5
+100

MapMiddleware is adding the matched path to the Request.PathBase, so you can use it when creating the return url

string returnUrl = Context.Request.PathBase + Options.CallbackPath;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.