-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OAuth - Creating event for ExchangeCode #9448
Conversation
Sync to upstream
/// <summary> | ||
/// Gets or sets the delegate that is invoked when the ExchangeCode method is invoked. | ||
/// </summary> | ||
public Func<OAuthExchangeCodeContext, Task<OAuthTokenResponse>> OnExchangeCode { get; set; } = async context => |
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 is more code than is appropriate for events. Deriving from OAuthHandler is more appropriate once you need to replace this much.
Is there a more specific event that would still be useful? Like adding an event on line 45 that passed the parameters dictionary so it could be augmented? The default implementation would no-op. Would that be enough for your PKCE example?
@@ -159,42 +159,10 @@ protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync | |||
} | |||
} | |||
|
|||
protected virtual async Task<OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri) | |||
protected virtual async Task<OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri, AuthenticationProperties properties) |
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 there a non-breaking way to add this new parameter? E.g. with a new overload?
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.
@Tratcher hi, I was trying to make this non-breaking but I really don't see how... An overload won't work because now it is called from HandleRemoteAuthenticateAsync
with the properties
parameter. So to make, it non breakable I would need the new method to call the old one. And that is not possible because I would need to pass the tokenRequestParameters
setted in the new method to the old one... I couldn't think of anything else, do you see a way out of this? How bad is this breaking change? n_n'
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.
https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/search?q=ExchangeCodeAsync&unscoped_q=ExchangeCodeAsync
It would break at least 9 providers, which is enough to try to mitigate. Let's think about it while we deal with the other issue.
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.
Ok, the first one about simply augmenting the Dictionary, I totally agree with you and I already changed it.
Will be giving some thought about how to not break it... But I don't see now how to make it without some smelly artifact...
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.
@Tratcher is it possible to add a new API ExchangeCodeAsnyc(ExchangeCodeContext context)?
This would future proof us a bit. We have used this in other places.
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.
@brentschmaltz yes, that's plausible. Either way it's a breaking change for many providers. If we added PKCE support directly we might be able to avoid this break. #9448 (comment)
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.
Better, I added some cleanup comments. I'll follow up on the API break.
{ "client_id", Options.ClientId }, | ||
{ "redirect_uri", redirectUri }, | ||
{ "client_secret", Options.ClientSecret }, | ||
{ "code", code }, |
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.
revert?
HttpContext context, | ||
AuthenticationScheme scheme, | ||
OAuthOptions options, | ||
Dictionary<string, string> tokenRequestParameters) |
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.
Dictionary<string, string> tokenRequestParameters) | |
IDictionary<string, string> tokenRequestParameters) |
/// <summary> | ||
/// Gets the code returned by the authentication provider after user authenticates | ||
/// </summary> | ||
public Dictionary<string, string> TokenRequestParameters { get; } |
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.
public Dictionary<string, string> TokenRequestParameters { get; } | |
public IDictionary<string, string> TokenRequestParameters { get; } |
} | ||
|
||
/// <summary> | ||
/// Gets the code returned by the authentication provider after user authenticates |
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.
Wrong comment?
namespace Microsoft.AspNetCore.Authentication.OAuth | ||
{ | ||
/// <summary> | ||
/// Contains information about the exchanging code for the access token context. |
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.
/// Contains information about the exchanging code for the access token context. | |
/// Contains information about exchanging code for the access token context. |
/// </summary> | ||
/// <param name="context">Contains the code returned, the redirect URI and the <see cref="AuthenticationProperties"/>.</param> | ||
/// <returns></returns> | ||
public virtual Task ExchangeCode(OAuthExchangeCodeContext context) => OnExchangeCode(context); |
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.
PrepareCodeExchange?
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 think BeforeExchangeCode is better, what you think?
@PinpointTownes So I looked at the 9 known providers that override ExchangeCode to see why. Summary: I'd be more willing to take the break API if I thought they could take advantage of the change and the new event. The Visual Studio provider looks like the only one that could remove it's overload and use the event instead to remap parameters. That tells me the event might not be general enough. We also might need to add first class support for some of these other scenarios. A full half of the providers made the same customization (reddit-like), moving the client id and secret to the auth header. If we made that a first class option then they could remove their overrides. The other providers are unique enough and mess with both the request and response so neither first classing their behavior nor the new event seem helpful. |
@Tratcher supporting basic authentication in both the OAuth2 and OIDC handlers would be an excellent idea, since it's a common source of pain and could help cut some code in the aspnet-contrib providers. I wonder if this event should also allow handling the code redeeming dance manually, pretty much like the OIDC handler with its |
/cc @poke @martincostello |
FYI we're considering first class PKCE support that would make this unnecessary. #7734 |
I don't know how neccissary this will be after #10928. |
Please rebase on #10928 and we can see what's left. |
Closing this for now due to the unresolved merge conflict and design questions. We can revisit in the future. |
Summary of the changes
OnExchangeCode
with default implementation it had beforeOAuthExchangeCodeContext
to hold properties necessary for developer to customize their ownExchangeCode
instead of overriding the wholeOAuthHandler
.Addresses #9092 (Use case described on the issue)