Permalink
Browse files

Improvements in the Authentication, extend the context with CurrentUs…

…er property
  • Loading branch information...
1 parent 5cb7a87 commit 925f93506c81a519d8dee0146a96ff5b8cecfd9a @sloncho sloncho committed Aug 17, 2011
Showing with 268 additions and 207 deletions.
  1. +7 −6 src/Nancy.Authentication.Basic.Tests/BasicAuthenticationFixture.cs
  2. +4 −2 src/Nancy.Authentication.Basic/BasicAuthentication.cs
  3. +2 −1 src/Nancy.Authentication.Basic/IUserValidator.cs
  4. +2 −2 src/Nancy.Authentication.Forms.Tests/FormsAuthenticationConfigurationFixture.cs
  5. +40 −28 src/Nancy.Authentication.Forms.Tests/FormsAuthenticationFixture.cs
  6. +3 −5 src/Nancy.Authentication.Forms/FormsAuthentication.cs
  7. +2 −2 src/Nancy.Authentication.Forms/FormsAuthenticationConfiguration.cs
  8. +5 −3 src/Nancy.Authentication.Forms/IUsernameMapper.cs
  9. +12 −0 src/Nancy.Demo.Authentication.Basic/DemoUserIdentity.cs
  10. +1 −0 src/Nancy.Demo.Authentication.Basic/Nancy.Demo.Authentication.Basic.csproj
  11. +1 −1 src/Nancy.Demo.Authentication.Basic/SecureModule.cs
  12. +3 −2 src/Nancy.Demo.Authentication.Basic/UserValidator.cs
  13. +15 −0 src/Nancy.Demo.Authentication.Forms/DemoUserIdentity.cs
  14. +1 −1 src/Nancy.Demo.Authentication.Forms/FormsAuthBootstrapper.cs
  15. +1 −0 src/Nancy.Demo.Authentication.Forms/Nancy.Demo.Authentication.Forms.csproj
  16. +1 −1 src/Nancy.Demo.Authentication.Forms/SecureModule.cs
  17. +7 −8 src/Nancy.Demo.Authentication.Forms/UserDatabase.cs
  18. +1 −1 src/Nancy.Demo.Authentication/AnotherVerySecureModule.cs
  19. +5 −2 src/Nancy.Demo.Authentication/AuthenticationBootstrapper.cs
  20. +15 −0 src/Nancy.Demo.Authentication/DemoUserIdentity.cs
  21. +3 −2 src/Nancy.Demo.Authentication/Nancy.Demo.Authentication.csproj
  22. +1 −1 src/Nancy.Demo.Authentication/SecureModule.cs
  23. +1 −1 src/Nancy.Demo.Authentication/VerySecureModule.cs
  24. +15 −13 src/Nancy.Demo.Hosting.Aspnet/Web.config
  25. +65 −33 src/Nancy.Tests/Unit/Security/ModuleSecurityFixture.cs
  26. +4 −4 src/Nancy.ViewEngines.NDjango/Nancy.ViewEngines.NDjango.csproj
  27. +4 −0 src/Nancy.ViewEngines.NDjango/packages.config
  28. +1 −1 src/Nancy/Nancy.csproj
  29. +7 −0 src/Nancy/NancyContext.cs
  30. +13 −0 src/Nancy/Security/IUserIdentity.cs
  31. +26 −37 src/Nancy/Security/ModuleSecurity.cs
  32. +0 −50 src/Nancy/Security/SecurityConventions.cs
@@ -83,7 +83,7 @@ public void Pre_request_hook_should_not_set_auth_details_with_no_auth_headers()
// Then
result.ShouldBeNull();
- context.Items.ContainsKey(SecurityConventions.AuthenticatedUsernameKey).ShouldBeFalse();
+ context.CurrentUser.ShouldBeNull();
}
[Fact]
@@ -121,7 +121,7 @@ public void Pre_request_hook_should_not_set_auth_details_when_invalid_scheme_in_
// Then
result.ShouldBeNull();
- context.Items.ContainsKey(SecurityConventions.AuthenticatedUsernameKey).ShouldBeFalse();
+ context.CurrentUser.ShouldBeNull();
}
[Fact]
@@ -136,7 +136,7 @@ public void Pre_request_hook_should_not_authenticate_when_invalid_encoded_userna
// Then
result.ShouldBeNull();
- context.Items.ContainsKey(SecurityConventions.AuthenticatedUsernameKey).ShouldBeFalse();
+ context.CurrentUser.ShouldBeNull();
}
[Fact]
@@ -154,13 +154,14 @@ public void Pre_request_hook_should_call_user_validator_with_username_in_auth_he
}
[Fact]
- public void Should_set_username_in_context_with_valid_username_in_auth_header()
+ public void Should_set_user_in_context_with_valid_username_in_auth_header()
{
// Given
var fakePipelines = new FakeApplicationPipelines();
var validator = A.Fake<IUserValidator>();
- A.CallTo(() => validator.Validate("foo", "bar")).Returns(true);
+ var fakeUser = A.Fake<IUserIdentity>();
+ A.CallTo(() => validator.Validate("foo", "bar")).Returns(fakeUser);
var cfg = new BasicAuthenticationConfiguration(validator, "realm");
@@ -173,7 +174,7 @@ public void Should_set_username_in_context_with_valid_username_in_auth_header()
fakePipelines.BeforeRequest.Invoke(context);
// Then
- context.Items[SecurityConventions.AuthenticatedUsernameKey].ShouldEqual("foo");
+ context.CurrentUser.ShouldBeSameAs(fakeUser);
}
private static NancyContext CreateContextWithHeader(string name, IEnumerable<string> values)
@@ -94,9 +94,11 @@ private static void RetrieveCredentials(NancyContext context, BasicAuthenticatio
if (credentials != null && credentials.Length == 2)
{
- if (configuration.UserValidator.Validate(credentials[0], credentials[1]))
+ var user = configuration.UserValidator.Validate(credentials[0], credentials[1]);
+
+ if (user != null)
{
- context.Items[SecurityConventions.AuthenticatedUsernameKey] = credentials[0];
+ context.CurrentUser = user;
}
}
}
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using Nancy.Security;
namespace Nancy.Authentication.Basic
{
@@ -16,6 +17,6 @@ public interface IUserValidator
/// <param name="username">Username</param>
/// <param name="password">Password</param>
/// <returns>A value indicating whether the user was authenticated or not</returns>
- bool Validate(string username, string password);
+ IUserIdentity Validate(string username, string password);
}
}
@@ -20,7 +20,7 @@ public FormsAuthenticationConfigurationFixture()
{
CryptographyConfiguration = cryptographyConfiguration,
RedirectUrl = "/login",
- UsernameMapper = A.Fake<IUsernameMapper>(),
+ UserMapper = A.Fake<IUserMapper>(),
};
}
@@ -45,7 +45,7 @@ public void Should_not_be_valid_with_empty_redirect_url()
[Fact]
public void Should_not_be_valid_with_null_username_mapper()
{
- config.UsernameMapper = null;
+ config.UserMapper = null;
var result = config.IsValid;
@@ -1,3 +1,5 @@
+using Nancy.Security;
+
namespace Nancy.Authentication.Forms.Tests
{
using System;
@@ -43,7 +45,7 @@ public FormsAuthenticationFixture()
{
CryptographyConfiguration = this.cryptographyConfiguration,
RedirectUrl = "/login",
- UsernameMapper = A.Fake<IUsernameMapper>(),
+ UserMapper = A.Fake<IUserMapper>(),
};
this.context = new NancyContext()
@@ -205,90 +207,100 @@ public void Should_have_expired_empty_authentication_cookie_in_logout_response()
public void Should_get_username_from_mapping_service_with_valid_cookie()
{
var fakePipelines = new FakeApplicationPipelines();
- var mockMapper = A.Fake<IUsernameMapper>();
- this.config.UsernameMapper = mockMapper;
+ var mockMapper = A.Fake<IUserMapper>();
+ this.config.UserMapper = mockMapper;
FormsAuthentication.Enable(fakePipelines, this.config);
this.context.Request.Cookies.Add(FormsAuthentication.FormsAuthenticationCookieName, this.validCookieValue);
fakePipelines.BeforeRequest.Invoke(this.context);
- A.CallTo(() => mockMapper.GetUsernameFromIdentifier(this.userGuid))
+ A.CallTo(() => mockMapper.GetUserFromIdentifier(this.userGuid))
.MustHaveHappened(Repeated.Exactly.Once);
}
[Fact]
- public void Should_set_username_in_context_with_valid_cookie()
+ public void Should_set_user_in_context_with_valid_cookie()
{
var fakePipelines = new FakeApplicationPipelines();
- var fakeMapper = A.Fake<IUsernameMapper>();
- A.CallTo(() => fakeMapper.GetUsernameFromIdentifier(this.userGuid)).Returns("Bob");
- this.config.UsernameMapper = fakeMapper;
+ var fakeMapper = A.Fake<IUserMapper>();
+ var fakeUser = A.Fake<IUserIdentity>();
+ fakeUser.UserName = "Bob";
+ A.CallTo(() => fakeMapper.GetUserFromIdentifier(this.userGuid)).Returns(fakeUser);
+ this.config.UserMapper = fakeMapper;
FormsAuthentication.Enable(fakePipelines, this.config);
this.context.Request.Cookies.Add(FormsAuthentication.FormsAuthenticationCookieName, this.validCookieValue);
var result = fakePipelines.BeforeRequest.Invoke(this.context);
- context.Items[Security.SecurityConventions.AuthenticatedUsernameKey].ShouldEqual("Bob");
+ context.CurrentUser.ShouldBeSameAs(fakeUser);
}
[Fact]
- public void Should_not_set_username_in_context_with_invalid_hmac()
+ public void Should_not_set_user_in_context_with_invalid_hmac()
{
var fakePipelines = new FakeApplicationPipelines();
- var fakeMapper = A.Fake<IUsernameMapper>();
- A.CallTo(() => fakeMapper.GetUsernameFromIdentifier(this.userGuid)).Returns("Bob");
- this.config.UsernameMapper = fakeMapper;
+ var fakeMapper = A.Fake<IUserMapper>();
+ var fakeUser = A.Fake<IUserIdentity>();
+ fakeUser.UserName = "Bob";
+ A.CallTo(() => fakeMapper.GetUserFromIdentifier(this.userGuid)).Returns(fakeUser);
+ this.config.UserMapper = fakeMapper;
FormsAuthentication.Enable(fakePipelines, this.config);
this.context.Request.Cookies.Add(FormsAuthentication.FormsAuthenticationCookieName, this.cookieWithInvalidHmac);
var result = fakePipelines.BeforeRequest.Invoke(this.context);
- context.Items.ContainsKey(Security.SecurityConventions.AuthenticatedUsernameKey).ShouldBeFalse();
+ context.CurrentUser.ShouldBeNull();
}
[Fact]
- public void Should_not_set_username_in_context_with_empty_hmac()
+ public void Should_not_set_user_in_context_with_empty_hmac()
{
var fakePipelines = new FakeApplicationPipelines();
- var fakeMapper = A.Fake<IUsernameMapper>();
- A.CallTo(() => fakeMapper.GetUsernameFromIdentifier(this.userGuid)).Returns("Bob");
- this.config.UsernameMapper = fakeMapper;
+ var fakeMapper = A.Fake<IUserMapper>();
+ var fakeUser = A.Fake<IUserIdentity>();
+ fakeUser.UserName = "Bob";
+ A.CallTo(() => fakeMapper.GetUserFromIdentifier(this.userGuid)).Returns(fakeUser);
+ this.config.UserMapper = fakeMapper;
FormsAuthentication.Enable(fakePipelines, this.config);
this.context.Request.Cookies.Add(FormsAuthentication.FormsAuthenticationCookieName, this.cookieWithEmptyHmac);
var result = fakePipelines.BeforeRequest.Invoke(this.context);
- context.Items.ContainsKey(Security.SecurityConventions.AuthenticatedUsernameKey).ShouldBeFalse();
+ context.CurrentUser.ShouldBeNull();
}
[Fact]
- public void Should_not_set_username_in_context_with_no_hmac()
+ public void Should_not_set_user_in_context_with_no_hmac()
{
var fakePipelines = new FakeApplicationPipelines();
- var fakeMapper = A.Fake<IUsernameMapper>();
- A.CallTo(() => fakeMapper.GetUsernameFromIdentifier(this.userGuid)).Returns("Bob");
- this.config.UsernameMapper = fakeMapper;
+ var fakeMapper = A.Fake<IUserMapper>();
+ var fakeUser = A.Fake<IUserIdentity>();
+ fakeUser.UserName = "Bob";
+ A.CallTo(() => fakeMapper.GetUserFromIdentifier(this.userGuid)).Returns(fakeUser);
+ this.config.UserMapper = fakeMapper;
FormsAuthentication.Enable(fakePipelines, this.config);
this.context.Request.Cookies.Add(FormsAuthentication.FormsAuthenticationCookieName, this.cookieWithNoHmac);
var result = fakePipelines.BeforeRequest.Invoke(this.context);
- context.Items.ContainsKey(Security.SecurityConventions.AuthenticatedUsernameKey).ShouldBeFalse();
+ context.CurrentUser.ShouldBeNull();
}
[Fact]
public void Should_not_set_username_in_context_with_broken_encryption_data()
{
var fakePipelines = new FakeApplicationPipelines();
- var fakeMapper = A.Fake<IUsernameMapper>();
- A.CallTo(() => fakeMapper.GetUsernameFromIdentifier(this.userGuid)).Returns("Bob");
- this.config.UsernameMapper = fakeMapper;
+ var fakeMapper = A.Fake<IUserMapper>();
+ var fakeUser = A.Fake<IUserIdentity>();
+ fakeUser.UserName = "Bob";
+ A.CallTo(() => fakeMapper.GetUserFromIdentifier(this.userGuid)).Returns(fakeUser);
+ this.config.UserMapper = fakeMapper;
FormsAuthentication.Enable(fakePipelines, this.config);
this.context.Request.Cookies.Add(FormsAuthentication.FormsAuthenticationCookieName, this.cookieWithBrokenEncryptedData);
var result = fakePipelines.BeforeRequest.Invoke(this.context);
- context.Items.ContainsKey(Security.SecurityConventions.AuthenticatedUsernameKey).ShouldBeFalse();
+ context.CurrentUser.ShouldBeNull();
}
[Fact]
@@ -126,14 +126,12 @@ public static Response LogOutAndRedirectResponse(NancyContext context, string re
{
var userGuid = GetAuthenticatedUserFromCookie(context, configuration);
- if (userGuid == Guid.Empty)
+ if (userGuid != Guid.Empty)
{
- return null;
+ context.CurrentUser =
+ configuration.UserMapper.GetUserFromIdentifier(userGuid);
}
- context.Items[SecurityConventions.AuthenticatedUsernameKey] =
- configuration.UsernameMapper.GetUsernameFromIdentifier(userGuid);
-
return null;
};
}
@@ -32,7 +32,7 @@ public FormsAuthenticationConfiguration(CryptographyConfiguration cryptographyCo
/// <summary>
/// Gets or sets the username/identifier mapper
/// </summary>
- public IUsernameMapper UsernameMapper { get; set; }
+ public IUserMapper UserMapper { get; set; }
/// <summary>
/// Gets or sets the cryptography configuration
@@ -51,7 +51,7 @@ public virtual bool IsValid
return false;
}
- if (this.UsernameMapper == null)
+ if (this.UserMapper == null)
{
return false;
}
@@ -1,18 +1,20 @@
-namespace Nancy.Authentication.Forms
+using Nancy.Security;
+
+namespace Nancy.Authentication.Forms
{
using System;
/// <summary>
/// Provides a mapping between forms auth guid identifiers and
/// real usernames
/// </summary>
- public interface IUsernameMapper
+ public interface IUserMapper
{
/// <summary>
/// Get the real username from an indentifier
/// </summary>
/// <param name="indentifier">User identifier</param>
/// <returns>Matching username, or empty</returns>
- string GetUsernameFromIdentifier(Guid indentifier);
+ IUserIdentity GetUserFromIdentifier(Guid indentifier);
}
}
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using Nancy.Security;
+
+namespace Nancy.Demo.Authentication.Basic
+{
+ public class DemoUserIdentity : IUserIdentity
+ {
+ public string UserName { get; set; }
+
+ public IEnumerable<string> Claims { get; set; }
+ }
+}
@@ -95,6 +95,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AuthenticationBootstrapper.cs" />
+ <Compile Include="DemoUserIdentity.cs" />
<Compile Include="MainModule.cs" />
<Compile Include="SecureModule.cs" />
<Compile Include="UserValidator.cs" />
@@ -11,7 +11,7 @@ public SecureModule()
Get["/"] = x =>
{
- return "Hello " + Context.Items[SecurityConventions.AuthenticatedUsernameKey].ToString();
+ return "Hello " + Context.CurrentUser.UserName;
};
}
}
@@ -3,14 +3,15 @@
using System.Linq;
using System.Web;
using Nancy.Authentication.Basic;
+using Nancy.Security;
namespace Nancy.Demo.Authentication.Basic
{
public class UserValidator : IUserValidator
{
- public bool Validate(string username, string password)
+ public IUserIdentity Validate(string username, string password)
{
- return username == "foo" && password == "bar";
+ return new DemoUserIdentity {UserName = username};
}
}
}
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using Nancy.Security;
+
+namespace Nancy.Demo.Authentication.Forms
+{
+ public class DemoUserIdentity : IUserIdentity
+ {
+ public string UserName { get; set; }
+
+ public IEnumerable<string> Claims { get; set; }
+ }
+}
@@ -13,7 +13,7 @@ protected override void InitialiseInternal(TinyIoC.TinyIoCContainer container)
new FormsAuthenticationConfiguration()
{
RedirectUrl = "~/login",
- UsernameMapper = container.Resolve<IUsernameMapper>(),
+ UserMapper = container.Resolve<IUserMapper>(),
};
FormsAuthentication.Enable(this, formsAuthConfiguration);
@@ -113,6 +113,7 @@
<Compile Include="..\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
+ <Compile Include="DemoUserIdentity.cs" />
<Compile Include="FormsAuthBootstrapper.cs" />
<Compile Include="MainModule.cs" />
<Compile Include="Models\UserModel.cs" />
@@ -11,7 +11,7 @@ public SecureModule() : base("/secure")
this.RequiresAuthentication();
Get["/"] = x => {
- var model = new UserModel(Context.Items[SecurityConventions.AuthenticatedUsernameKey].ToString());
+ var model = new UserModel(Context.CurrentUser.UserName);
return View["secure.cshtml", model];
};
}
Oops, something went wrong.

0 comments on commit 925f935

Please sign in to comment.