aspnet / Security

[Archived] Middleware for security and authorization of web apps. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
1.27k stars 599 forks source link

Cannot get the original request scheme #1830

Closed cycbluesky closed 6 years ago

cycbluesky commented 6 years ago

I have a web site use OpenIdConnect to implement Azure Ad authentication. It's deployed in AWS ECS. User will access this site via https protocol, after it pass ALB, it will be auto turned to http protocol. This cause a problem. When user access via https, after Auzre Ad authenticated, it will redirect back to the site by http protocol. I tried to config OpenIdConnect CallbackPath property to full path as following: https://{hostname}/signin-oidc, but error occurred, it tell me CallbackPath must be start with "/".

I checkout the Microsoft.AspNetCore.Authentication.OpenIdConnect source code, I found that the code detect the protocol by current request context.

protected string BuildRedirectUri(string targetPath) => Request.Scheme + "://" + Request.Host + OriginalPathBase + targetPath;

How can I resolve this problem?

Tratcher commented 6 years ago

https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1

IlBaffo commented 6 years ago

Hi, I'm having the same problem and I'm having trouble finding documentation online. The intention here is not to have any users store, just permit the signin with the oauth account and then have an application cookie to persist the session.

Back with aspnet-core 1.0 I was able to setup a login with Steam and it worked pretty well.

My setup is fairly contrived but I think that setting this up should be pretty easy. This is my setup (domain.com is a placeholder):

Then, when trying to login I am redirected to this url (urlDecoded and stripped of personal info) https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=XXXXXX&scope=https://graph.microsoft.com/user.read&response_type=code&redirect_uri=http://domain.com/signin-microsoft&state=...

The redirect_uri is ignoring the protocol and it seems to be passed by the middleware. Why isn't it just read from the azure app configuration? I already have the secret and the appid, why do I need to supply the rediret_url?

Thanks.

Tratcher commented 6 years ago

Read this doc and follow the troubleshooting instructions. https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1#troubleshoot

IlBaffo commented 6 years ago

Sorry but that didn't help.

Well, I give up, I will revert back to 1.0 until someone will post a complete configuration as I am not able to figure it out myself (even tho I know OAuth per se) and I don't feel confident to put something, related to authentication, that I cannot comprehend in production.

BTW hacking this in the pipeline made the scheme work (at least)

app.Use((context, next) =>
{
    context.Request.Scheme = "https";
    return next();
});

Thanks anyway.

Eilon commented 6 years ago

@cycbluesky can you share any logging output when you tried to run this?

cycbluesky commented 6 years ago

@Eilon I tried the Microsoft.AspNetCore.HttpOverrides middle-ware solution. It does not work now. Step 1. Add app.UseForwardedHeaders();

        {
            //app.Use((context, next) =>
            //{
            //    context.Request.Scheme = "https";
            //    return next();
            //});

            app.UseForwardedHeaders();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

Step 2: Add ForwardedHeadersOptions config

public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            });

Step 3. I write some code to output the header

@($"Request Scheme: {Request.Scheme}{Environment.NewLine}")

<ul>
    @{foreach (var header in Request.Headers)
        {
            <li>@($"{header.Key}: {header.Value}{Environment.NewLine}")</li>
        }
    }
</ul>

The result shows that the X-Forwarded-Proto has been filled as https.

User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36 X-Forwarded-For: 10.128.36.189 X-Forwarded-Proto: https X-Forwarded-Port: 443 X-Amzn-Trace-Id: Root=1-5b63d088-7d72fb980d58e2805c143d44 upgrade-insecure-requests: 1

My project deployed on aws ECS, user use https to access, ALB change it to http, then pass request to container. It seems that the HttpOverrides has not work before the first request redirect to Azure AD authentication path.

Eilon commented 6 years ago

@cycbluesky thanks for the additional info.

@shirhatti - do you have any experience in this area on how to configure this type of setup?

Eilon commented 6 years ago

@shirhatti - ping?

shirhatti commented 6 years ago

@cycbluesky Looks good to me. Maybe try logging context.Request.Scheme to ensure you've correctly configured the forwarded headers middleware?