Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

Breaking changes in Authentication / Authorization #248

Closed
sandorfr opened this issue May 8, 2015 · 31 comments
Closed

Breaking changes in Authentication / Authorization #248

sandorfr opened this issue May 8, 2015 · 31 comments

Comments

@sandorfr
Copy link

sandorfr commented May 8, 2015

There are a lot of breaking changes in that area. They look amazing but I'm really struggling with them. Is there any design notes about how it works.

Here is some details about what I'm struggling with ( http://forums.asp.net/t/2048628.aspx?Struggling+with+the+beta4+Authentication+Authorization+changes )

Here what I currently have :

  • A Middleware which is overriding CreateHandler and return my custom authentication handler
  • A Custom authentication handler and its options

I'm configuring it that way :

In ConfigureServices

services.AddAuthorization();
services.ConfigureAuthorization(options => options.AddPolicy(JWTAuthenticationDefaults.AuthenticationType,
                new AuthorizationPolicyBuilder().AddAuthenticationSchemes(JWTAuthenticationDefaults.AuthenticationType).Build()));

In Configure

app.UseJWTAuthentication(options => {
                options.MasterKey = Configuration.Get("masterKey");
            }, JWTAuthenticationDefaults.AuthenticationType);

First issue : currently, it successfully steps in my custom handler AuthenticateCoreAsync, I return a valid ticket, but ApplyResponseChallenge is called every time.

Another thing bothers me, If my policy name differs from my authenticationscheme it fails with InvalidOperationException: The following authentication scheme was not accepted: customJWT and I can't figure out why.

And the last strange thing ApplyResponseChallenge is called twice per request.

@HaoK
Copy link
Member

HaoK commented May 8, 2015

Not really any notes, I'll take a look and reply to your post in this issue. Do you want to edit this issue and include the context from your asp.net forum post?

@davidfowl
Copy link
Member

@HaoK can you write up something so we can put it on Announcements?

@blowdart
Copy link
Member

blowdart commented May 8, 2015

@davidfowl How much do you want written? We're overhauled everything. A quick announcement won't do anyone any good, as announcements are a couple of lines. It's going to need proper documentation to expose all the changes we made, especially the authz overhaul. Whilst that's slowly coming along in the shape of a powerpoint, its going to take a good number of days to turn it into proper usable documentation (either Word, or readthedocs) and samples, and getting to that point is weeks away.

@sandorfr
Copy link
Author

sandorfr commented May 8, 2015

Thanks @HaoK, I just updated my post to include my current status on this subject.

On the documentation area let me know if I can be of any help.

@davidfowl
Copy link
Member

@blowdart Anything would suffice at this point. Even if it's to say that there were a ton of breaking changes. That's the entire purpose of that repository.

@blowdart
Copy link
Member

blowdart commented May 8, 2015

Saying a ton is hardly helpful. "We changed authz to use Policy" doesn't say much at all. It's not breaking in that case anyway, it's new.

@HaoK
Copy link
Member

HaoK commented May 8, 2015

@sandorfr I'm assuming you have something like [Authorize(Policy = "JWT")] or something like that?

Can you include your entire startup.cs (or at least the Configure that's includes your middlewares?)

@HaoK
Copy link
Member

HaoK commented May 8, 2015

For your first issue about the policy names / AuthScheme being correlated, that's because of how you setup your policy:

This should work fine.

services.ConfigureAuthorization(options => options.AddPolicy("<PolicyName>",
                new AuthorizationPolicyBuilder().AddAuthenticationSchemes(JWTAuthenticationDefaults.AuthenticationType).Build()));

[Authorize("<PolicyName>")]

@sandorfr
Copy link
Author

sandorfr commented May 8, 2015

Yes I have that :

    [Authorize(JWTAuthenticationDefaults.AuthenticationType)]
    public class ListController : BaseController

Here my UseJWTAuthentication implementation :

public static IApplicationBuilder UseJWTAuthentication(this IApplicationBuilder app, Action<JWTAuthenticationOptions> configureOptions = null, string optionsName = "") {
            return app.UseMiddleware<JWTAuthenticationMiddleware>(
                 new ConfigureOptions<JWTAuthenticationOptions>(configureOptions ?? (o => { })) {
                     Name = optionsName
                 });
        }

@blowdart
Copy link
Member

blowdart commented May 8, 2015

Announcements done. They're not detailed, because they're announcements. Proper documentation will follow in a few weeks.

aspnet/Announcements#20
aspnet/Announcements#21
aspnet/Announcements#22

@sandorfr
Copy link
Author

sandorfr commented May 8, 2015

@HaoK that's fixed for the policy naming part. Thanks. Now I just need to understand why the ApplyResponseChallenge is called despite my AuthenticationTicketbeing set.

@blowdart I think your announcements are helpful, at least they would have helped me save time earlier this week :), so I guess that might help other developers.

@HaoK
Copy link
Member

HaoK commented May 8, 2015

Can you include the rest of your middleware configuration? Do you have cookies or any other auth middlewares involved?

@sandorfr
Copy link
Author

sandorfr commented May 8, 2015

No I don't have any other auth middleware atm (I plan to do so but this is not a priority).

            // Configure the HTTP request pipeline.
            // Add the console logger.
            loggerfactory.AddConsole();
            loggerfactory.AddProvider(new AzureLoggerProvider(configuration, (LogLevel)Enum.Parse(typeof(LogLevel), configuration.Get("azure_log_level"))));
           // loggerfactory.AddProvider(new CustomLoggerProvider(connectionManager));

            if (configuration.ShouldMeasurePerformance) {
                app.UseMiddleware<MeasureMiddleware>();
            }

            app.UseMiddleware<CorrelationIdMiddleware>();
            app.UseMiddleware<CorsMiddleware>();
            app.UseJWTAuthentication(options => {
                options.MasterKey = Configuration.Get("masterKey");
            }, JWTAuthenticationDefaults.AuthenticationType);

            // Add the following to the request pipeline only in development environment.
            if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase)) {
                //app.UseBrowserLink();
                app.UseErrorPage(ErrorPageOptions.ShowAll);
                app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
            } else if (string.Equals(Configuration.Get("ShowDebugTraces"), "true", StringComparison.OrdinalIgnoreCase)) {
                app.UseErrorPage(ErrorPageOptions.ShowAll);
                app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
            } else {
                // Add Error handling middleware which catches all application specific errors and
                // send the request to the following path or controller action.
                app.UseErrorHandler("/Home/Error");
            }

            // Add static files to the request pipeline.
            app.UseStaticFiles();

            // Add MVC to the request pipeline.
            app.UseMvc(routes => {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });
                // Uncomment the following line to add a route for porting Web API 2 controllers.
                // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
            });

@sandorfr
Copy link
Author

sandorfr commented May 8, 2015

there is one thing I'm not sure of. should my authentication middleware use or not use AutomaticAuthentication and why.

@HaoK
Copy link
Member

HaoK commented May 8, 2015

Automatic is intended for your current scenario where there's only one primary auth middleware, try turning this on, and removing the authentication scheme from the policy. The HttpContext.User should automatically be the principal from your middleware on the request after sign in.

@sandorfr
Copy link
Author

sandorfr commented May 8, 2015

Ok, thanks I'm going to do some test following that path and triple check everything again :). I'll keep you updated.

@HaoK
Copy link
Member

HaoK commented May 8, 2015

Thanks for trying this out, definitely feel free to share any thoughts/feedback you have as most of this has changed recently and we are trying to tweak things to be more intuitive...

@sandorfr
Copy link
Author

sandorfr commented May 8, 2015

Does not work either :(. I must be missing something obvious...
Is there any prerequisites over the principal/claims I return in my ticket?
One good thing which might actually ease those troubleshooting would be an easy way to get the reason of the 401.

@sandorfr
Copy link
Author

sandorfr commented May 9, 2015

Eureka ! It looks like a policy without any requirement will never authorize the request. I had to add RequireAuthenticatedUser() to get it to work. It also work if I add any RequireClaim.

@HaoK
Copy link
Member

HaoK commented May 9, 2015

Ah yes, that funky edge case... @blowdart what do you think about removing this weirdness? We could just throw whenever we register a policy with no requirements on startup... Instead of either always failing or always succeeding an empty policy...?

@sandorfr
Copy link
Author

sandorfr commented May 9, 2015

My personal opinion is that the exception is the right way, the developer will see it early and fix it quickly. The always failing does not have any sense to me (and it will drive others than me completely crazy) but the always succeeding might lead to the same issue :), plus a potential security breach.

@blowdart
Copy link
Member

blowdart commented May 9, 2015

Exception it is. This caught me too :)

@sandorfr
Copy link
Author

Do you have any idea why the ApplyResponseChallenge is called twice?

@HaoK
Copy link
Member

HaoK commented May 26, 2015

I think the exception behavior was the main issue for this, please file a new issue if you are still seeing issues with ApplyResponseChallenge

@HaoK HaoK closed this as completed May 26, 2015
@sandorfr
Copy link
Author

I'm going to double check but last time I checked this point I had the issue. I'll open an issue if needed.

-----Message d'origine-----
De : "Hao Kung" notifications@github.com
Envoyé : ‎26/‎05/‎2015 01:09
À : "aspnet/Security" Security@noreply.github.com
Cc : "Sandor" cyprien.autexier@gmail.com
Objet : Re: [Security] Breaking changes in Authentication / Authorization(#248)

I think the exception behavior was the main issue for this, please file a new issue if you are still seeing issues with ApplyResponseChallenge

Reply to this email directly or view it on GitHub.

@marcosph
Copy link

I'm doing some test with MVC 6 ("Microsoft.AspNet.Mvc": "6.0.0-beta4").
I made a Roles Manager (CRUD), however, when I remove a related roles with a User, it is still accessing the Controller, which in this case has [Authorize (Roles = "Admin")]. Removed the role of User he still had access to the controller that had [Authorize (Roles = "Admin")].

@blowdart
Copy link
Member

@marcosph - this is a long closed issue. Unless you are seeing something related to the original issue (and it doesn't appear you are) you would be better served opening a new issue and actually providing some of your code to help us diagnose the problem

@georgiosd
Copy link

How does one have multiple auth schemes? I've added the default OAuth policy (beta7) plus my own ApiKey policy but I get the System.InvalidOperationException: The following authentication scheme was not accepted problem.

Any ideas?

Code:

services.ConfigureAuthorization(auth =>
            {
                auth.AddPolicy("ApiKey", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes("ApiKey")
                    .RequireAuthenticatedUser().Build());

                auth.DefaultPolicy = new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(OAuthBearerAuthenticationDefaults.AuthenticationScheme)
                    .RequireAuthenticatedUser().Build();
            });
[Route("/api/alerts")]
    public class AlertsController : Controller
    {

        [Authorize("ApiKey"), HttpPost, Route("")]
        public async Task<IActionResult> Post()
        {

        }

        [Authorize, HttpGet, Route("")]
        public Task<IList<TradeAlert>> GetLastAlerts()
        {

        }
}

@georgiosd
Copy link

(I want one method to use the ApiKey policy and the rest to use the default)

@HaoK
Copy link
Member

HaoK commented Sep 29, 2015

Do you have any auth middleware configured with AuthenticationScheme ApiKey?

@georgiosd
Copy link

I think the problem was I wasn't setting the AuthenticationScheme property for the middleware options

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants