10

I'm writing my own OWIN middleware for OpenID Connect authorization code flow, based on other examples in the Katana Project.

As part of this I have to construct a couple of URIs, eg a Redirect URI and a Return URL.

Other examples in Katana do this by concatenating parts from the current request, for example in CookieAuthenticationHandler

loginUri =
    Request.Scheme +
    Uri.SchemeDelimiter +
    Request.Host +
    Request.PathBase +
    Options.LoginPath +
    new QueryString(Options.ReturnUrlParameter, currentUri);

My question is what rules govern what ends up in the two path properties:

OwinContext.Request.Path
OwinContext.Request.PathBase

I've tried inspecting these properties as the request passes through different handlers in the pipeline below, for the request:

"https://localhost/Client/login" // Where Client is a virtual directory in IIS

The result:

  • In the mapped handler for /login, the PathBase = "/Client/Login".
  • But when the request gets to the ApplyResponseChallengeAsync method in my QuillCodeFlowHandler on the way back out for the same request, PathBase = "/Client" and Path = "/Login".

So without knowing the "rules" for how these values are populated, then later changed, it is hard to construct URIs using them. If anyone can explain, will be much appreciated.

An extract of my config is:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
    LoginPath = new PathString("/Login")
});

app.UseQuillCodeFlowAuthentication(new QuillCodeFlowOptions());

app.Map("/login", map =>
{
   map.Run(async ctx =>
   {
     if (ctx.Authentication.User == null ||
     !ctx.Authentication.User.Identity.IsAuthenticated)
     {                        
       var authenticationProperties = new AuthenticationProperties();
       [...]
       ctx.Authentication.Challenge(authenticationProperties,
                                    QuillCodeFlowDefaults.AuthenticationType);  

The OWIN specification gives some explanation and Microsoft.Owin.Host.HttpListener.GetPathAndQuery method seems to be where the path variables are set initially.

4

1 回答 1

5

使用构造时

app.Map("/login", map => [...]

这使用

Owin.MapExtensions.Map

它构造了一个实例

Microsoft.Owin.Mapping.MapMiddleware

对于需要运行的代码。

我看到的行为在这个中间件的 Invoke 方法中有解释:

public async Task Invoke(IDictionary<string, object> environment)
{
    IOwinContext context = new OwinContext(environment);

    PathString path = context.Request.Path;

    PathString remainingPath;
    if (path.StartsWithSegments(_options.PathMatch, out remainingPath))
    {
        // Update the path
        PathString pathBase = context.Request.PathBase;
        context.Request.PathBase = pathBase + _options.PathMatch;
        context.Request.Path = remainingPath;

        await _options.Branch(environment);

        context.Request.PathBase = pathBase;
        context.Request.Path = path;
    }
    else
    {
        await _next(environment);
    }
}

基本上,代码在运行委托之前会更改 Path 和 PathBase(等待 _options.Branch(environment) ),然后在执行完成后将它们设置回原始值。

因此,我所看到的行为得到了解释。

于 2014-09-04T10:29:49.957 回答