Skip to content
This repository has been archived by the owner on Jan 24, 2021. It is now read-only.

Replacing current "user" objects with ClaimsPrincipal/ClaimsIdentity #1820

Merged
merged 24 commits into from
Mar 20, 2015
Merged

Replacing current "user" objects with ClaimsPrincipal/ClaimsIdentity #1820

merged 24 commits into from
Mar 20, 2015

Conversation

damianh
Copy link
Member

@damianh damianh commented Feb 19, 2015

PR to fix #1800

Mandatory:

  • Remove IUserIdentity
  • Replace UserIdentityExtensions with a version that has the same (as much as possible - will need to be updated for the new, correct, structure of a claim) API but uses ClaimsPrincipal
  • Update SecurityHooks to use the new extensions and claim structure
  • Update ModuleSecurity to use the new extensions and claim structure
  • Update NancyContext to use ClaimsIdentiy/Principal
  • Allow the principal to "flow" from hosting
  • Update OWIN to automatically flow the identity
  • Update tests

Preferred:

  • Update Forms Auth to use the new extensions and claim structure
  • Update Stateless Auth to use the new extensions and claim structure
  • Update Token Auth to use the new extensions and claim structure Remove Token Auth 🔥
  • Update Basic Auth to use the new extensions and claim structure

Additional

  • Don't use bootstrapper static location in NancyOptions. It WILL cause conflicts and composition problems in an OWIN pipeline.

@damianh
Copy link
Member Author

damianh commented Feb 19, 2015

@NancyFx/owners @NancyFx/most-valued-minions Right lads, bit of a big fish landing here. Going to need your careful attention. I'd like to get feedback before going any further.

At this point everything other that Nancy.Authentication.Token and Nancy.Authentication.Token.Tests compiles. Tests pass in all of the remaining projects, though I did delete a couple of tests that may be contentions. I'll highlight those.

To review, best start by looking at changes to ClaimsPrincipalExtensions, ModuleSecurity and SecurityHook.

@damianh
Copy link
Member Author

damianh commented Feb 19, 2015

What should we do with Nancy.Authentication.Token ? There is already a standard for this, OAuth, that uses JWT

@jchannon
Copy link
Member

https://github.com/jchannon/Owin.StatelessAuth

On Thursday, 19 February 2015, Damian Hickey [email protected]
wrote:

What should we do with Nancy.Authentication.Token ? There is already a
standard for this, OAuth, that uses JWT

Reply to this email directly or view it on GitHub
#1820 (comment).

@@ -286,84 +207,15 @@ public void Should_return_null_with_RequiresAnyClaim_and_any_claim_met()
}

[Fact]
public void Should_return_forbidden_response_with_RequiresValidatedClaims_enabled_but_claims_missing()
Copy link
Member Author

Choose a reason for hiding this comment

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

Any tests around RequiresValidatedClaims were removed. HasClaim(s) performs that function.

@khellang khellang mentioned this pull request Feb 20, 2015
@@ -19,21 +17,14 @@ public PerRouteAuthModule()

Get["/requiresclaims"] = _ =>
{
this.RequiresClaims(new[] { "test", "test2" });
this.RequiresClaims(c => c.Type == "test", c => c.Type == "test2");
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we could have an overload of RequireClaims that takes a params string[] claim. The overload would iterate over the params and compare them against the Type of each claim. It would give us a nicer syntax. Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

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

It would have to be called 'RequiredClaimTypes'.

Regardless, its not particularly useful as you generally need to inspect
at least 2 attributes of a claim - the Type and the Value. See HasClaim
https://msdn.microsoft.com/en-us/library/hh194432%28v=vs.110%29.aspx and
the predicate overload
https://msdn.microsoft.com/en-us/library/hh159713(v=vs.110).aspx
On 26 Feb 2015 23:01, "Andreas Håkansson" [email protected] wrote:

In src/Nancy.Tests.Functional/Modules/PerRouteAuthModule.cs
#1820 (comment):

@@ -19,21 +17,14 @@ public PerRouteAuthModule()

         Get["/requiresclaims"] = _ =>
         {
  •            this.RequiresClaims(new[] { "test", "test2" });
    
  •            this.RequiresClaims(c => c.Type == "test", c => c.Type == "test2");
    

Perhaps we could have an overload of RequireClaims that takes a params
string[] claim. The overload would iterate over the params and compare
them against the Type of each claim. It would give us a nicer syntax.
Thoughts?


Reply to this email directly or view it on GitHub
https://github.com/NancyFx/Nancy/pull/1820/files#r25469286.

@thecodejunkie
Copy link
Member

I think the changes so far looks alright 😄 👍

@thecodejunkie
Copy link
Member

Why is Nancy.Authentication.Token an issue here? I get it that there are other, existing, things for this but could we leave it as is for now so we don't get stuck on that? I know it makes use of IUserIdentity, are you seeing issues with making it compatible with the new stuff?

@grumpydev
Copy link
Member

Might be nice to loop in @leastprivilege and @brockallen - be nice to get some identityserver integration/samples/lovin' alongside this.

@leastprivilege
Copy link

And with "we" I really mean "you" ;) I am currently busy with working on the PR on my family repo ;)

@khellang
Copy link
Member

We should loop in @jeffdoolittle as well, he was talking about JWT etc. over at #1550.

@damianh
Copy link
Member Author

damianh commented Mar 8, 2015

We can't carry Nancy.Authentication.Token forward with just swapping ClaimsPrincipal for IUserIdentity

It currently does two things:

  1. Serializes IUserIdentity into a token (hashing it etc).
  2. Deserializes it in the request pipeline.

Serializing the ClaimsPrincipal in a similar way is going to a lot heavier in terms of token size. In anycase, it's also questionable if that is even a reasonable idea considering JWTs (which are not necessarily trivial - https://tools.ietf.org/html/draft-ietf-oauth-json-web-token and https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/ ). JWTs, because they're standard, means the authorization header is verifiable in other middleware / frameworks etc. Even if serialization of ClaimsPrincipal worked, do we really want a Nancy specific token auth scheme?

I suggest we delete Nancy.Authentication.Token and open a separate issue for JWT support (if we want that in nancy).

@damianh
Copy link
Member Author

damianh commented Mar 8, 2015

I've also looked into Owin.StatelessAuth ( @jchannon correct me if I'm wrong ), it appears it just checks for the existence of the header and offloads the token verification to the user and it doesn't assist in generating the tokens.

@khellang
Copy link
Member

This will break A LOT of app.UseNancy() cases 😞

@damianh
Copy link
Member Author

damianh commented Mar 12, 2015

Yes it will. Allowing this is pit-of-fail. User does app.UserNancy() twice in a pipeline and stuff breaks. Remember, middleware can contain middleware, and it may come from other places, so it may not be obvious to them in their wireups.

Nancy must no longer assume it's the only framework in an application.

Fwiw, there is no such thing as app.UseWebApi(). It explicitly requires a configuration parameter for the same reasons too.

@grumpydev
Copy link
Member

I disagree, we still need our happy path - the 99% use case is Nancy on its own, or potentially nancy with some auth middleware - anyone using complex middleware setups should already be aware of how to set it up.

@damianh
Copy link
Member Author

damianh commented Mar 12, 2015

I knew you would :)

@grumpydev
Copy link
Member

And WebApi as an example on how to do things? You'll be suggesting sharepoint next :)

@damianh
Copy link
Member Author

damianh commented Mar 12, 2015

One data point a projection does not make :)

@damianh
Copy link
Member Author

damianh commented Mar 12, 2015

Will happy-path users still be coming via OWIN(\whatever) pipelines though? hmm

@grumpydev
Copy link
Member

We could take a similar approach to the one I suggested for the razor config wrecking problem - have two "levels" of nuget, our normal ones with happy paths, then a .core that is just bare bones.

In razor's case .core would be everything but the config transforms, razor main package would have a dependency on that, and add in the transforms.

For the owin stuff perhaps it could be that the happy path stuff isn't in core, but is included as a dependency in Nancy.hosting.aspnet (just thinking out loud to give an idea)

@damianh
Copy link
Member Author

damianh commented Mar 12, 2015

Could Nancy.Hosting.AspNet could do the bootstrapper static location?

@grumpydev
Copy link
Member

That's what it does currently, but not sure how it will work if we shift it to owin.. Maybe the "hosting" packages that use katana will bring in a startup.cs

@grumpydev
Copy link
Member

Regardless of the outcome of the wireup discussion, I don't think it has any relevance to the scope of this issue/PR, so if you could roll it back that'd be awesome.

@damianh
Copy link
Member Author

damianh commented Mar 13, 2015 via email

@grumpydev
Copy link
Member

Sorry @damianh I missed your question.. yeah, those tests are a bit broken I think.. something like this makes more sense:

namespace Nancy.Owin.Tests
{
    using Nancy.Bootstrapper;
    using Nancy.Tests;

    using Xunit;

    public class NancyOptionsFixture
    {
        private readonly NancyOptions nancyOptions;

        public NancyOptionsFixture()
        {
            this.nancyOptions = new NancyOptions();
        }

        [Fact]
        public void Bootstrapper_should_use_locator_if_not_specified()
        {
            // Given
            var bootstrapper = new DefaultNancyBootstrapper();
            NancyBootstrapperLocator.Bootstrapper = bootstrapper;

            //When
            //Then
            this.nancyOptions.Bootstrapper.ShouldNotBeNull();
            this.nancyOptions.Bootstrapper.ShouldBeSameAs(bootstrapper);
        }

        [Fact]
        public void Bootstrapper_should_use_chosen_bootstrapper_if_specified()
        {
            // Given
            var bootstrapper = new DefaultNancyBootstrapper();
            var specificBootstrapper = new DefaultNancyBootstrapper();
            NancyBootstrapperLocator.Bootstrapper = bootstrapper;

            //When
            this.nancyOptions.Bootstrapper = specificBootstrapper;

            //Then
            this.nancyOptions.Bootstrapper.ShouldNotBeNull();
            this.nancyOptions.Bootstrapper.ShouldBeSameAs(specificBootstrapper);
        }

        [Fact]
        public void PerformPassThrough_should_not_be_null()
        {
            this.nancyOptions.PerformPassThrough.ShouldNotBeNull();
        }

        [Fact]
        public void PerformPassThrough_delegate_should_return_false()
        {
            this.nancyOptions.PerformPassThrough(new NancyContext()).ShouldBeFalse();
        }
    }
}

… all sort of problems if there is more than one Nancy instance / bootstrapper in a owin pipeline. (reverted from commit e8ae7c4)
@damianh
Copy link
Member Author

damianh commented Mar 20, 2015

@grumpydev only problem with these tests is they can't be run in parallel (static mutable state being the enemy of parallel testing). May or not be a concern for @NancyFx/owners .

@damianh
Copy link
Member Author

damianh commented Mar 20, 2015

Test fixed. I guess a rebase is required. @NancyFx/owners Could one of you rebase the 2.0 branch (if deemed necessary)?

@grumpydev
Copy link
Member

I thought about that @damianh, but I couldn't think of anywhere else that used that property - I suppose it could be refactored so NancyOptions has:

public Func BootstrapperLocator { get; set; }

ctor() {
this.BootstrapperLocator = () => NancyBootstrapperLocator.Bootstrapper;
}

Then that can be swapped out to whatever you like.. quite possibly overkill though :)

@damianh
Copy link
Member Author

damianh commented Mar 20, 2015

Yeah, think it's a bit of overkill right now. Lets move on and address it separately as you've suggested.

grumpydev added a commit that referenced this pull request Mar 20, 2015
Replacing current "user" objects with ClaimsPrincipal/ClaimsIdentity
@grumpydev grumpydev merged commit 65914a5 into NancyFx:v2 Mar 20, 2015
@damianh damianh deleted the v2-claims branch March 20, 2015 14:17
@xt0rted
Copy link
Contributor

xt0rted commented Mar 20, 2015

Is there a CI feed for the v2 branch so I can try this out?

@grumpydev
Copy link
Member

@xt0rted : not yet, we will put a beta out after 1.2 in the next week.

@khellang
Copy link
Member

@xt0rted You can grab the bits from here 😄

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

Successfully merging this pull request may close these issues.

9 participants