【问题标题】:Why is IdentityServer redirecting to http rather than https?为什么 IdentityServer 重定向到 http 而不是 https?
【发布时间】:2018-02-12 14:39:15
【问题描述】:

我有一个非常简单的 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>();
    }
}

这是来自我的 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())
            });
        });
    }
}

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

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
}

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

【问题讨论】:

标签: identityserver3 openid-connect appharbor


【解决方案1】:

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

参考this GitHub issue,我在我的网站应用配置的开头添加了以下内容:

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

这使网站知道传入的请求是通过 https 进行的;这反过来似乎可以确保 IdentityServer3 中间件生成 https uri。

【讨论】:

    【解决方案2】:

    在 Azure 应用服务中运行 identityserver4 时遇到同样的问题。即使强制使用https,在.well-known/openid-configuration 中生成的url 仍然是http://

    使用与其他答案相同的解决方案进行修复,但使用 AspNetCore ForwardedHeadersExtensions

    var forwardOptions = new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
        // Needed because of mixing http and https.
        RequireHeaderSymmetry = false,
    };
    
    // Accept X-Forwarded-* headers from all sources.
    forwardOptions.KnownNetworks.Clear();
    forwardOptions.KnownProxies.Clear();
    
    app.UseForwardedHeaders(forwardOptions);
    

    有关此主题的更多讨论,另请参阅https://github.com/IdentityServer/IdentityServer4/issues/1331

    【讨论】:

      【解决方案3】:

      在您的启动中添加转发的标头

          services.Configure<ForwardedHeadersOptions>(options =>
          {
              options.ForwardedHeaders =
                  ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
          });
      

          app.UseForwardedHeaders(new ForwardedHeadersOptions()
          {
              ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
          });
      

      最后告诉配置它必须在重定向 url 中将 http 替换为 https。我仍在寻找更好的方法来实现这一点。

      在你的 .addopenidconnect() 添加:

       Func<RedirectContext, Task> redirectToIdentityProvider = (ctx) =>
                           {
                               if (!ctx.ProtocolMessage.RedirectUri.StartsWith("https") && !ctx.ProtocolMessage.RedirectUri.Contains("localhost"))
                                   ctx.ProtocolMessage.RedirectUri = ctx.ProtocolMessage.RedirectUri.Replace("http", "https");
                               return Task.FromResult(0);
                           };
                           opt.Events = new OpenIdConnectEvents
                           {
                               OnRedirectToIdentityProvider = redirectToIdentityProvider
                           };
      

      【讨论】:

        猜你喜欢
        • 2020-12-28
        • 2021-12-12
        • 2019-06-24
        • 1970-01-01
        • 2019-08-04
        • 1970-01-01
        • 2018-02-18
        • 2017-08-25
        • 2016-11-15
        相关资源
        最近更新 更多