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

Adding code only flow for sign in. #258

Closed
wants to merge 19 commits into from

Conversation

tushargupta51
Copy link
Contributor

Also changes for integrating wilson logging to OIDC middleware.

@@ -520,6 +540,14 @@ protected override AuthenticationTicket AuthenticateCore()
}
}

protected virtual IdentityModel.Clients.ActiveDirectory.AuthenticationResult RedeemAuthorizationCode(string authorizationCode)
Copy link
Contributor

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?

https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/vNext/samples/Mvc/Mvc.Client/Startup.cs#L76-L103

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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... 😄

@kevinchalet
Copy link
Contributor

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();
Copy link
Contributor

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. Thanks!

Copy link
Contributor

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?

@tushargupta51
Copy link
Contributor Author

@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?

@kevinchalet
Copy link
Contributor

@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?

@tushargupta51
Copy link
Contributor Author

@PinpointTownes It is there on MyGet. Here: https://www.myget.org/gallery/azureadwebstacknightly

@kevinchalet
Copy link
Contributor

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)

@vibronet
Copy link

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.

@kevinchalet
Copy link
Contributor

@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.

@Tratcher
Copy link
Member

Agreed, OIDC should not take a direct AAD dependency, even temporarily.

@vibronet
Copy link

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

@vibronet
Copy link

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-*"
Copy link
Contributor

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.

Copy link
Contributor

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.

if (properties == null)
{
Logger.LogError(Resources.OIDCH_0005_MessageStateIsInvalid);
return null;
}

var isCodeOnlyFlow = (properties.Items.ContainsKey(OpenIdConnectParameterNames.ResponseType) ?
Copy link
Contributor

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

Copy link
Contributor Author

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,
Copy link
Contributor

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).

@dnfclas
Copy link

dnfclas commented Jun 29, 2015

@tushargupta51, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR.

Thanks, DNFBOT;

@tushargupta51
Copy link
Contributor Author

Closing this, will send another PR later.

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

Successfully merging this pull request may close these issues.

9 participants