-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Introduce SignInResult/SignOutResult and SignIn/SignOut #4259
Conversation
Hi @PinpointTownes, 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; |
|
||
if (authenticationSchemes.Count == 0) | ||
{ | ||
// TODO: move the exception message to the resources file. |
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.
Question: what's the recommended way to add new messages to the resources file? The resx
KoreBuild target?
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.
Yup - build resx
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.
Sadly, it doesn't work on my machine:
& : The module '.build' could not be loaded. For more information, run
'Import-Module .build'.
At C:\Users\Chalet Kévin\Documents\GitHub\Forks\Mvc\.build\KoreBuild.ps1:64
char:2
+ &"$koreBuildFolder\Sake\0.2.2\tools\Sake.exe" -I $koreBuildFolder\sha ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (.build\Sake\0.2.2\tools\Sake.ex
e:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CouldNotAutoLoadModule
I guess it's related to aspnet/Security#688 (comment), since I'm also using Windows 7.
/cc @Eilon
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.
You might need to delete the .build directory. We made a bunch of changes to how we procure and layout the build scripts.
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.
Nope, no luck 😢
I ended up manually adding the property/method in the designer file.
Meh, not sure its worth an extension method to do a foreach SignOut. |
/// <param name="principal">The <see cref="ClaimsPrincipal"/> containing the user claims.</param> | ||
/// <returns>The created <see cref="SignInResult"/> for the response.</returns> | ||
[NonAction] | ||
public virtual SignInResult SignIn(IList<string> authenticationSchemes, ClaimsPrincipal principal) |
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.
Not sure this really makes sense, would you really expect someone to sign the same principal into multiple schemes? I would expect different principals would get signed into each scheme in general
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.
FYI, some ASOS users are doing that to create a cookie and a token with the same principal.
That said, you're probably right, it's surely not a common case.
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 I think things look much cleaner with a single scheme for sign in / sign out. You only need multiple schemes for challenge.
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.
Okay for SignIn
but for SignOut
, see #4259 (comment).
Thank you for the PR! However, this needs to wait until post 1.0.0. We aren't taking additional features into the current release. |
@danroth27 alright. That said, it's not really a new feature stricto sensu, as it's mainly a copy/paste of existing code, which is itself a tiny wrapper around the authentication APIs. |
@danroth27 @Eilon this is such a small change. Do we like the API? If so can we merge it? It feels like polish since we have ChallengeResult, SignInResult and SIgnOut result can clean up some of the template code as well. |
/// <param name="properties"><see cref="AuthenticationProperties"/> used to perform the sign-in operation.</param> | ||
public SignInResult(string authenticationScheme, ClaimsPrincipal principal, AuthenticationProperties properties) | ||
{ | ||
if (authenticationScheme == 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.
Question: should we keep the null guards even if the properties are publicly settable?
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.
Either keep the null guards and make the properties read-only, or remove the null guards.
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.
Actually, I wonder if we shouldn't simply move these guards to the ExecuteAsync
method, prior to calling the authentication manager.
Anyway, I need to fix all the aspnet-contrib projects before going back to this PR. Everything stopped compiling/working and I can't find a workaround...
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.
IMO better to validate on the parameters + properties. Generally ExecuteAsync
won't be called in unit tests, so it be easy to use the result the wrong way.
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 fine with dual properties + parameters validation, but we'll still have to move the "as at least one element" check of SignOutResult.AuthenticationSchemes
elsewhere, since we could validate that for a constructor parameter, but not for a property.
Another approach might be to remove all the public setters and update SignOutResult.AuthenticationSchemes
to expose a read-only list. TBH, I have no personal preference, as long as it's consistent everywhere.
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 generally want all the action results to have get/set properties. It's really handy to be able to modify things in filters. Speaking of, we should probably make a defensive copy of whatever list the user passes in.
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've added a tiny check in both SignInResult.ExecuteAsync
and SignOutResult.ExecuteAsync
to ensure the AuthenticationScheme(s)
property is not left is an incoherent state (null or empty, basically).
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.
@rynowak do you strongly feel we should do some ToArray
/ToList
here? Authentication-related actions are probably not critical paths, so I guess the extra allocations are fine.
Fine, fine, we can take this 😄 |
var authentication = context.HttpContext.Authentication; | ||
await authentication.SignInAsync(AuthenticationScheme, Principal, Properties); | ||
|
||
logger.SignInResultExecuting(AuthenticationScheme, Principal); |
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.
Ideally this line would take place before the call to SignInAsync
. This way if the 'actual' operation throws, we've already logged what we were trying to do.
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, I'll update that and fix the existing results.
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.
Done.
⌚ from me for a few small things @HaoK - any more feedback on this? |
Any opinion? |
Looks fine to me |
@PinpointTownes - any updates?
I wouldn't block this PR on that item, if you want to, go ahead and file that on the appropriate repo? |
Sadly no. Fixing all the aspnet-contrib/OpenIddict stuff to make DNX and CLI happy with the recent changes in corefx and NuGet took me much more time than I had expected (and that's an euphemism). The fact MVC itself no longer compiles with DNX/VS is also extremely annoying, specially since CLI no longer works on Windows 7: https://github.com/dotnet/cli/issues/1966 TBH, I don't feel super comfortable not being able to run the unit tests before pushing new commits. But since you haven't updated MVC to include the frameworkAssemblies workaround that would make DNX happy and since CI builds always fail before running the tests, that's pretty much my only option. I'll try some yolodev tonight and fix all the reviewed points. By authentication helpers, I meant the SignOut/Challenge/Forbid methods exposed by ControllerBase, that all take IList. We could update them to take array params without having to update AuthenticationManager.
|
Yeah I think that would be a fine change Sorry for all the difficulties 😢 if you don't manage to get to this I'm happy to fix up the remaining stuff and make sure sure it's included for RC2. |
var authentication = context.HttpContext.Authentication; | ||
if (AuthenticationSchemes.Count > 0) | ||
if (AuthenticationSchemes != null && AuthenticationSchemes.Count > 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.
I've added a null check here, since AuthenticationSchemes
can be null (there's no null guard in the constructor).
📅 PR updated 😄 |
Alright, I've updated the
No worries. Thanks for the offer: actually, it would be great if you could run the tests for me 😄 |
if (authenticationSchemes.Count == 0) | ||
{ | ||
// TODO: move the exception message to the resources file. | ||
throw new ArgumentException("At least one scheme must be specified", nameof(authenticationSchemes)); |
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'll take a look at fixing 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.
Hum, are you commenting on an old commit? I'm pretty sure I've fixed that (by manually adding the resource entry )
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 that was an oopsie on my part
- looks good to me. I'm going to squash and run tests for you |
I can squash it if you want, it will be easier for you if you want to cherry-pick it. |
go for it then 👍 |
Done 👏 |
Will merge as soon as I'm able to.... (restore issues). #ThanksPranav |
Still waiting on package/build issues, will update once I've been able to merge. |
Thanks! Yeah, it's super messy ATM, the reversioning of the new |
Pushed as f9d24a8 Thanks 👍 |
Thanks @rynowak 👏 👏 |
Fixes #4258.
(FWIW, that would be great if the authentication helpers had overloads accepting a
params string[]
argument forauthenticationSchemes
)./cc @rynowak @HaoK @pranavkm