为什么 IdentityServer 重定向到 http 而不是 https?

Sim*_*n P 3 appharbor openid-connect identityserver3

我有一个非常简单的 MVC5 网站,我正在尝试使用 IdentityServer3 来保护它。

我的网站和我的 IdentityServer 实例都作为单独的站点托管在 AppHarbor 中。两者都在 https 后面。

当我访问网站中受[Authorize]属性(例如/Home/About)保护的资源时,我成功重定向到 IdentityServer,并且可以成功进行身份验证。

当 IdentityServer 将其响应 POST 回网站(通过app.FormPostResponse.js)时,网站以 302 重定向响应所请求的资源 - 正如预期的那样。但是,此重定向是指向http,而不是 https (请参阅下面的网络跟踪)。

我确定这只是我的 IdentityServer 配置有问题,但我很感激任何关于我有什么问题的指示。

(AppHarbor 在 IIS 前面使用反向代理(我相信是 nginx),SSL 终止的地方 - 所以我有RequireSsl = false这个场景,根据 IdentityServer 文档。)

这是我的网站 Startup.cs

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies"
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            Authority = "https://<my-idsrv3>.apphb.com/identity",

            ClientId = "<my-client-id>",
            Scope = "openid profile roles email",
            RedirectUri = "https://<my-website>.apphb.com",
            ResponseType = "id_token",

            SignInAsAuthenticationType = "Cookies",

            UseTokenLifetime = false
        });

        JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是来自我的 IdentityServer3 实例的 Startup.cs:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Map("/identity", idsrvApp =>
        {
            idsrvApp.UseIdentityServer(new IdentityServerOptions
            {
                SiteName = "My Identity Server",
                SigningCertificate = Certificates.LoadSigningCertificate(),
                RequireSsl = false,
                PublicOrigin = "https://<my-idsrv3>.apphb.com",

                Factory = new IdentityServerServiceFactory()
                    .UseInMemoryUsers(Users.Get())
                    .UseInMemoryClients(Clients.Get())
                    .UseInMemoryScopes(Scopes.Get())
            });
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的网站客户端的定义:

new Client
{
    Enabled = true,
    ClientName = "My Website Client",
    ClientId = "<my-client-id>",
    Flow = Flows.Implicit,

    RedirectUris = new List<string>
    {
        "https://<my-website>.apphb.com"
    },

    AllowAccessToAllScopes = true
}
Run Code Online (Sandbox Code Playgroud)

这是来自 Chrome 的跟踪,在 IdentityServer 同意屏幕上单击“是,允许”后:

Chrome 网络跟踪

Sim*_*n P 5

所以看起来这个问题是由我的客户端网站在 SSL 终止的 nginx 前端后面引起的。

参考这个 GitHub 问题,我在我网站的应用程序配置的开头添加了以下内容:

app.Use(async (ctx, next) =>
{
    string proto = ctx.Request.Headers.Get("X-Forwarded-Proto");
    if (!string.IsNullOrEmpty(proto))
    {
        ctx.Request.Scheme = proto;
    }
    await next();
});
Run Code Online (Sandbox Code Playgroud)

这使网站意识到传入请求是通过 https 传输的;这反过来似乎确保 IdentityServer3 中间件生成 https uri。