-
Notifications
You must be signed in to change notification settings - Fork 598
Add RemoteAuthenticationHandler base (support for error handling) #495
Conversation
Hi @HaoK, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution! The agreement was validated by .NET Foundation and real humans are currently evaluating your PR. TTYL, DNFBOT; |
Not sure where best to integrate this with ODIC yet. Also still need to see if this makes sense in Cookies anywhere |
/// The request path within the application's base path where the user-agent will be returned | ||
/// when a failure occurs. | ||
/// </summary> | ||
public PathString ErrorHandlerPath { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this property is general enough to put in the base AuthenticationOptions
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where else could it live if we want the common error handler logic in the base handler?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is: do we want to have that in the base handler? This error handling is only applicable to authentication handlers implementing InvokeAsync
(since you can't control the flow elsewhere) and I'm not sure all middleware will implement it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah well the other option is to introduce a base class for all of the Invoke style middlewares (not cookie/bearer) basically. I've been leaning towards that anyways, I'm not opposed to taking a stab at that and moving this error handling into the new common base. We need to rename InvokeAsync anyways, that name is terrible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps RedirectingAuthenticationMiddleware as the name of the new shared base class for OAuth/OIDC/Twitter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean exactly by "common flows"? It sounds like a crazy idea 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah you and @Tratcher both think I'm crazy :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@PinpointTownes see new RemoteAuthenticationHandler shared base class, @Tratcher has grudgingly come around to its value... standardizes Invoke path for OAuth/Twitter/OIDC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't needed anymore, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep nuking
Updated with major changes:
|
Updated with a stab at moving InvokeReplyPath to a new RemoteAuthenticationHandler base for OAuth and Twitter, I also sucked some of the common options into here as well like (BackChannel/CallbackPath). I also moved SigningIn to this base class/options, but I'm not even sure we really need this event anymore... |
a0df401
to
bfa245c
Compare
} | ||
|
||
if (authenticationFailedContext.Skipped) | ||
{ | ||
return null; | ||
return new AuthenticateResult(); | ||
} | ||
|
||
throw; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not opposed to re-throwing exceptions by default at this stage. But they MUST be caught somewhere: we can't afford returning a 500 response for a simple invalid/expired token.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure we don't forget about this. Once the higher level changes are agreed on, the fun process of going through each of the specific error/exception paths needs to be reviewed :/
New iteration changes: HandleErrorAsync is a no-op in the base AuthHandler, and overridden in RemoteHandler to invoke the Error event on RemoteOptions.RemoteEvents. |
Update:
TBD: Renaming OIDC events, and adding control flow to cookies to see if BaseContext can be merged with BaseControlContext |
Nice 😄
Actually, it doesn't look that bad but... 😄
Outch, it's a horrible pattern that will kill hundreds of poor kittens 😢
Curious: what's the benefit? 😮
Oh yeah, it's much nicer 👍 That said, I know wonder why we need this class at all, since it simply exposes the ticket and an exception... why not simply returning the ticket and throwing exceptions? 😄 |
@@ -33,6 +33,8 @@ public class CookieSignedInContext : BaseContext<CookieAuthenticationOptions> | |||
Properties = properties; | |||
} | |||
|
|||
public new CookieAuthenticationOptions Options { get { return (CookieAuthenticationOptions)base.Options; } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover turds from previous iterations, nuking thanks :)
So the other option which I had previously was keeping the base remote events in a separate IRemoteEvents property on the base options so they don't interfere with the actual provider events. options.RemoteEvents = new RemoteEvents() { OnError = ... }; (note I've come around fully to @Tratcher's view that the events should just be simple delegates without methods/interface) |
Updated: AuthenticationResult.Sucess to throw if a null ticket is provided, so the only time Ticket should be null is via the Failed method |
} | ||
} | ||
|
||
// REVIEW: this maybe return an error instead? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
Introduced new protected virtual HandleRemoteAuthenticateAsync to RemoteAuthenticationHandler and moved all the Invoke path logic there (old HandleAuthenticate method now returns a failed authenticated result). We should consider if its more appropriate to use a no-op successful empty ticket like before |
@Tratcher Updated with new iteration based on what we decided on: Put events back into the base Event property and use it as a new base |
/// <summary> | ||
/// </summary> | ||
/// <param name="context"></param> | ||
/// <returns>True if no other handlers should be called</returns> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove empty docs, doesn't return anything.
Updated with the new iteration:
|
@@ -29,7 +29,7 @@ public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) | |||
|
|||
app.UseCookieAuthentication(options => | |||
{ | |||
options.AutomaticAuthentication = true; | |||
options.AutomaticAuthenticate = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one should also use AutomaticChallenge. See https://github.com/aspnet/Security/blob/haok9-25/errors/samples/SocialSample/Startup.cs#L225
Almost done ⌚ |
|
||
namespace Microsoft.AspNet.Authentication.Cookies | ||
{ | ||
public class BaseCookieContext : BaseContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious: why do you need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We nuked Options/Generics off of the base contexts, and just added them all back in the specific OAuth/Cookies/Facebook contexts themselves.
public CookieAuthenticationOptions Options { get; }
Updated, any last requests? I'll push this tomorrow in the afternoon, MVC/Identity changes look to be fairly small surprisingly :) |
409b502 will address any remaining issues in next iteration/PR |
return false; | ||
} | ||
|
||
if (context.Principal != null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still trying to understand how you would get to this point without a principal or ReturnUri. I would expect all of those cases to be error conditions handled above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The event can simply null out the principal or return uri, its settable on the context today
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would mean you're using the context property values as a form of flow control. Since we have real flow control now I don't think we should support the old hacky approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the context properties read only for Ticket/Principal then? I'm fine with that :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we still want to allow people to replace it, but I don't think we should support null values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is we allow AuthenticationTickets with null principals. So we can't easily block this unless we change that.
Hi All, Before posting a new issue I wanted to see if perhaps this issue was about or related to an issue I'm having. I'm on RC1, When a user selects to authenticate w/Facebook, and they put in their user name and password correctly, but clicks the Cancel button on the "this is what the app is requesting" confirmation, then the user's browser is redirected to Control doesn't seem to be flowing back to my ASP.NET web application (I never get back anything in any /Account/xxx account controller method. Wanted to report as an issue if it isn't one yet, but didn't want to add a new issue if this has already been fixed. Thanks, |
@eriksendc hey, There's actually a ticket tracking that: #710. |
Thx! |
cc @Tratcher