-
Notifications
You must be signed in to change notification settings - Fork 597
Conversation
@@ -520,6 +540,14 @@ protected override AuthenticationTicket AuthenticateCore() | |||
} | |||
} | |||
|
|||
protected virtual IdentityModel.Clients.ActiveDirectory.AuthenticationResult RedeemAuthorizationCode(string authorizationCode) |
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.
Oh please no, no dependency on AAD stuff... specially for such a simple thing.
Why not simply using a good old HttpClient
?
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 We want to use ADAL for redeeming code for tokens instead of doing a direct httpClient call. That is why we have adal for 😄 We have plans to extend this to authorization servers beyond AAD but that will be the second step.
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.
Then rename this middleware to ActiveDirectoryAuthenticationMiddleware
and let the community offer a real provider-agnostic OpenID Connect middleware 😄
Out of curiosity, what's the advantage of using ADAL here?
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.
Caching. That's one major advantage of using ADAL. I understand we need to be provider agnostic and that is the plan we have for GA. Adding @vibronet if he has anything to add here.
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.
God no, not this mess. You can't even imagine how many people lost their hair on the #owin channel because of token caching 😄
And why would you use caching here? New code, new token. Absolutely no need for caching.
@vibronet hey, it's been a long time... 😄
I have absolutely no idea what you're doing with the git history, but it's a real mess... you should really use fast forward merging or proper rebasing 😄 |
{ | ||
AuthenticationContext authContext = new AuthenticationContext(Options.Authority, false); | ||
ClientCredential credential = new ClientCredential(Options.ClientId, Options.ClientSecret); | ||
var tokens = authContext.AcquireTokenByAuthorizationCodeAsync(authorizationCode, new Uri(Options.RedirectUri), credential).GetAwaiter().GetResult(); |
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? Why using a blocking .GetAwaiter().GetResult()
when you can make the method fully async?
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.
👍
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.
And BTW, given that Options.RedirectUri
is not a mandatory setting (thought it should probably be, given that redirect_uri
is required for OIDC authorization requests), Uri
's constructor will throw an exception if you don't set 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.
Nice catch. Thanks!
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.
Same remark for Options.Authority
. Can AuthenticationContext
live with it if it's null?
@PinpointTownes Regarding the git history, are you referring to the merges because all other commits are relevant to the logging and code only flow changes? |
@tushargupta51 sure, my remark was only about the merge commits. I'd like to play with the bits offered by this PR but the static ADAL version you specified doesn't seem to exist. Could you please upload it on the MyGet nightly build repository? |
@PinpointTownes It is there on MyGet. Here: https://www.myget.org/gallery/azureadwebstacknightly |
Hum, I see, it failed because the Azure AD has been removed from NuGet.Config when the JWT security token handler bits have been published to aspnetvnext. You should add it again if you plan to take a dependency on ADAL, or upload it to the aspnetvnext repository. (BTW, that's why the build failed on AppVeyor: https://ci.appveyor.com/project/aspnetci/security/build/1.0.107) |
for the pure sign in flow, the plan is to move to HttpClient. When we'll look after improving the access token acquisition experience we will be using ADAL - mostly for its caching benefits. |
@vibronet I still don't understand why you would integrate ADAL directly in the OIDC client middleware instead of simply using the notifications hooks to store the access tokens exactly where you want to. |
Agreed, OIDC should not take a direct AAD dependency, even temporarily. |
let me restate - for the sign in flow we won't have a dependency on ADAL. For the access token flow the notifications route is already available today, but requires far too much code and is prone to mistakes. We need a more integrated solution. I am not saying that such solution will show up in the OIDC middleware, though it is a possibility given that the code request and redemption machinery is largely the same |
also note, "store the access token" is a very simplistic way of describing what happens. It's not enough to provide a storage, you need a model to come with it. Token caching is a combination of caching access token, refresh tokens, and context (source, client app, resource, user and many others). When at a later time a new token is requested, there is very sophisticated logic that infers whether there is an access token and/or a refresh token and/or a multi resource refresh token and so on. All those rules can get very complicated and have a strong dependency on the provider. Generic classes that work across the board can't ingest this level of sophistication and surface the details to the developer. Conversely, ADAL's assumptions allow it to take care of all that logic without bothering the developer. Once again, I am not saying that this will end up in the OIDC middleware. But when it comes to clients and token management strategies, there is no such thing as a provider-agnostic approach AND a viable programming model. I am just back from BUILD and Ignite, during which I heard over and over again from customers how useless they find generic purpose libraries for OAuth2 (again, not OIDC). |
"Microsoft.Framework.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" }, | ||
"Microsoft.IdentityModel.Protocol.Extensions": "2.0.0-beta4-*" | ||
"Microsoft.AspNet.Authentication.OAuth": "1.0.0-*" |
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.
Why taking a dependency on Microsoft.AspNet.Authentication.OAuth
?
IMHO, you should use the super-cool OpenIdConnectMessage
primitive instead of the more limited TokenResponse
we created for the OAuth2 client middleware.
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 @tushargupta51 I think it helps in crafting the message url and avoiding missssspellings, since the properties like 'ClientId' avoid that category of error.
…point and some cleanup
7a67300
to
334e66f
Compare
if (properties == null) | ||
{ | ||
Logger.LogError(Resources.OIDCH_0005_MessageStateIsInvalid); | ||
return null; | ||
} | ||
|
||
var isCodeOnlyFlow = (properties.Items.ContainsKey(OpenIdConnectParameterNames.ResponseType) ? |
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 not sure it's the most appropriate way to determine whether an OIDC callback really corresponds to a "code only" flow: nothing prevents a server from ignoring your response_type
and returning an id_token
or a token
.
IMHO, making sure there's no id_token
or token
in the message would be far more robust: https://github.com/aspnet/Security/pull/279/files#diff-5ba88763cd4e76f8ecfcccff1ca9984aR266
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 do check for a null id_token in the incoming message along with this boolean before the code is used to redeem tokens. This boolean is an indication to take an action when a null id_token is received. If this boolean is not set and the id_token is null, we go directly to processing the code.
var openIdMessage = new OpenIdConnectMessage() | ||
{ | ||
ClientId = Options.ClientId, | ||
ClientSecret = Options.ClientSecret, |
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 can start with ClientSecret, but we will need an issue for: Certs and SignedJwt (AssertionCredentials).
@tushargupta51, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR. |
Closing this, will send another PR later. |
Also changes for integrating wilson logging to OIDC middleware.