diff --git a/src/Nancy.Authentication.Token.Tests/Nancy.Authentication.Token.Tests.csproj b/src/Nancy.Authentication.Token.Tests/Nancy.Authentication.Token.Tests.csproj
deleted file mode 100644
index 56fcef0b89..0000000000
--- a/src/Nancy.Authentication.Token.Tests/Nancy.Authentication.Token.Tests.csproj
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
- Debug
- AnyCPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}
- Library
- Properties
- Nancy.Authentication.Token.Tests
- Nancy.Authentication.Token.Tests
- v4.5
- 512
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- false
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- false
-
-
- true
- bin\MonoDebug\
- DEBUG;TRACE
- full
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- false
-
-
- bin\MonoRelease\
- TRACE
- true
- pdbonly
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- false
-
-
-
- False
- ..\packages\FakeItEasy.1.19.0\lib\net40\FakeItEasy.dll
-
-
-
-
-
-
-
-
-
- False
- ..\packages\xunit.1.9.1\lib\net20\xunit.dll
-
-
- False
- ..\packages\xunit.extensions.1.9.1\lib\net20\xunit.extensions.dll
-
-
-
-
- Fakes\FakeRequest.cs
-
-
- ShouldExtensions.cs
-
-
- Properties\SharedAssemblyInfo.cs
-
-
-
-
-
-
-
-
-
-
-
-
- {97fa024a-f6ed-4086-bcc1-1a51be63474c}
- Nancy.Authentication.Token
-
-
- {D79203C0-B672-4751-9C95-C3AB7D3FEFBE}
- Nancy.Testing
-
-
- {34576216-0dca-4b0f-a0dc-9075e75a676f}
- Nancy
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token.Tests/Storage/FileSystemTokenKeyStoreFixture.cs b/src/Nancy.Authentication.Token.Tests/Storage/FileSystemTokenKeyStoreFixture.cs
deleted file mode 100644
index d047db4c09..0000000000
--- a/src/Nancy.Authentication.Token.Tests/Storage/FileSystemTokenKeyStoreFixture.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-namespace Nancy.Authentication.Token.Tests.Storage
-{
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
-
- using Nancy.Authentication.Token.Storage;
- using Nancy.Testing.Fakes;
-
- using Xunit;
-
- public class FileSystemTokenKeyStoreFixture
- {
- [Fact]
- public void Should_store_keys_in_file()
- {
- // Given
- var keyStore = GetKeyStore();
- try
- {
- var keys = new Dictionary
- {
- { DateTime.UtcNow, Encoding.UTF8.GetBytes("fake encryption key") }
- };
-
- // When
- keyStore.Store(keys);
-
- // Then
- Assert.True(File.Exists(keyStore.FilePath));
- }
- finally
- {
- keyStore.Purge();
- }
- }
-
- [Fact]
- public void Should_retrieve_keys_from_file()
- {
- // Given
- var keyStore = GetKeyStore();
- try
- {
- var keys = new Dictionary
- {
- { DateTime.UtcNow, Encoding.UTF8.GetBytes("fake encryption key") }
- };
-
- keyStore.Store(keys);
-
- // When
- var retrievedKeys = keyStore.Retrieve();
-
- // Then
- Assert.True(Encoding.UTF8.GetString(retrievedKeys.Values.First()) == "fake encryption key");
- }
- finally
- {
- keyStore.Purge();
- }
- }
-
- private static FileSystemTokenKeyStore GetKeyStore()
- {
- var rootPathProvider = new FakeRootPathProvider();
- return new FileSystemTokenKeyStore(rootPathProvider);
- }
- }
-}
diff --git a/src/Nancy.Authentication.Token.Tests/TokenAuthenticationConfigurationFixture.cs b/src/Nancy.Authentication.Token.Tests/TokenAuthenticationConfigurationFixture.cs
deleted file mode 100644
index 65999ee00a..0000000000
--- a/src/Nancy.Authentication.Token.Tests/TokenAuthenticationConfigurationFixture.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace Nancy.Authentication.Token.Tests
-{
- using System;
-
- using Nancy.Tests;
-
- using Xunit;
-
- public class TokenAuthenticationConfigurationFixture
- {
- [Fact]
- public void Should_throw_with_null_tokenizer()
- {
- var result = Record.Exception(() => new TokenAuthenticationConfiguration(null));
-
- result.ShouldBeOfType(typeof (ArgumentException));
- }
- }
-}
diff --git a/src/Nancy.Authentication.Token.Tests/TokenAuthenticationFixture.cs b/src/Nancy.Authentication.Token.Tests/TokenAuthenticationFixture.cs
deleted file mode 100644
index 42fbe4094d..0000000000
--- a/src/Nancy.Authentication.Token.Tests/TokenAuthenticationFixture.cs
+++ /dev/null
@@ -1,188 +0,0 @@
-namespace Nancy.Authentication.Token.Tests
-{
- using System;
- using System.Collections.Generic;
- using System.Threading;
-
- using FakeItEasy;
-
- using Nancy.Bootstrapper;
- using Nancy.Security;
- using Nancy.Tests;
- using Nancy.Tests.Fakes;
-
- using Xunit;
-
- public class TokenAuthenticationFixture
- {
- private readonly TokenAuthenticationConfiguration config;
- private readonly IPipelines hooks;
-
- public TokenAuthenticationFixture()
- {
- this.config = new TokenAuthenticationConfiguration(A.Fake());
- this.hooks = new Pipelines();
- TokenAuthentication.Enable(this.hooks, this.config);
- }
-
- [Fact]
- public void Should_add_a_pre_hook_in_application_when_enabled()
- {
- // Given
- var pipelines = A.Fake();
-
- // When
- TokenAuthentication.Enable(pipelines, this.config);
-
- // Then
- A.CallTo(() => pipelines.BeforeRequest.AddItemToStartOfPipeline(A>.Ignored))
- .MustHaveHappened(Repeated.Exactly.Once);
- }
-
- [Fact]
- public void Should_add_both_token_and_requires_auth_pre_hook_in_module_when_enabled()
- {
- // Given
- var module = new FakeModule();
-
- // When
- TokenAuthentication.Enable(module, this.config);
-
- // Then
- module.Before.PipelineDelegates.ShouldHaveCount(2);
- }
-
- [Fact]
- public void Should_throw_with_null_config_passed_to_enable_with_application()
- {
- // Given, When
- var result = Record.Exception(() => TokenAuthentication.Enable(A.Fake(), null));
-
- // Then
- result.ShouldBeOfType(typeof(ArgumentNullException));
- }
-
- [Fact]
- public void Should_throw_with_null_config_passed_to_enable_with_module()
- {
- // Given, When
- var result = Record.Exception(() => TokenAuthentication.Enable(new FakeModule(), null));
-
- // Then
- result.ShouldBeOfType(typeof(ArgumentNullException));
- }
-
- [Fact]
- public void Should_throw_with_null_pipeline_passed_to_enable_with_config()
- {
- // Given, When
- var result = Record.Exception(() => TokenAuthentication.Enable((IPipelines)null, null));
-
- // Then
- result.ShouldBeOfType(typeof(ArgumentNullException));
- }
-
- [Fact]
- public void Should_throw_with_null_module_passed_to_enable_with_config()
- {
- // Given, When
- var result = Record.Exception(() => TokenAuthentication.Enable((INancyModule)null, null));
-
- // Then
- result.ShouldBeOfType(typeof(ArgumentNullException));
- }
-
- [Fact]
- public void Pre_request_hook_should_not_set_auth_details_with_no_auth_headers()
- {
- // Given
- var context = new NancyContext()
- {
- Request = new FakeRequest("GET", "/")
- };
-
- // When
- var result = this.hooks.BeforeRequest.Invoke(context, new CancellationToken());
-
- // Then
- result.Result.ShouldBeNull();
- context.CurrentUser.ShouldBeNull();
- }
-
- [Fact]
- public void Pre_request_hook_should_not_set_auth_details_when_invalid_scheme_in_auth_header()
- {
- // Given
- var context = CreateContextWithHeader(
- "Authorization", new[] { "FooScheme" + " " + "A-FAKE-TOKEN" });
-
- // When
- var result = this.hooks.BeforeRequest.Invoke(context, new CancellationToken());
-
- // Then
- result.Result.ShouldBeNull();
- context.CurrentUser.ShouldBeNull();
- }
-
- [Fact]
- public void Pre_request_hook_should_call_tokenizer_with_token_in_auth_header()
- {
- // Given
- var context = CreateContextWithHeader(
- "Authorization", new[] { "Token" + " " + "mytoken" });
-
- // When
- this.hooks.BeforeRequest.Invoke(context, new CancellationToken());
-
- // Then
- A.CallTo(() => config.Tokenizer.Detokenize("mytoken", context, A.Ignored)).MustHaveHappened();
- }
-
- [Fact]
- public void Should_set_user_in_context_with_valid_username_in_auth_header()
- {
- // Given
- var fakePipelines = new Pipelines();
-
- var context = CreateContextWithHeader(
- "Authorization", new[] { "Token" + " " + "mytoken" });
-
- var tokenizer = A.Fake();
- var fakeUser = A.Fake();
- A.CallTo(() => tokenizer.Detokenize("mytoken", context, A.Ignored)).Returns(fakeUser);
-
- var cfg = new TokenAuthenticationConfiguration(tokenizer);
-
- TokenAuthentication.Enable(fakePipelines, cfg);
-
- // When
- fakePipelines.BeforeRequest.Invoke(context, new CancellationToken());
-
- // Then
- context.CurrentUser.ShouldBeSameAs(fakeUser);
- }
-
- private static NancyContext CreateContextWithHeader(string name, IEnumerable values)
- {
- var header = new Dictionary>
- {
- { name, values }
- };
-
- return new NancyContext()
- {
- Request = new FakeRequest("GET", "/", header)
- };
- }
-
- class FakeModule : NancyModule
- {
- public FakeModule()
- {
- this.After = new AfterPipeline();
- this.Before = new BeforePipeline();
- this.OnError = new ErrorPipeline();
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token.Tests/TokenizerFixture.cs b/src/Nancy.Authentication.Token.Tests/TokenizerFixture.cs
deleted file mode 100644
index b708c0b8c0..0000000000
--- a/src/Nancy.Authentication.Token.Tests/TokenizerFixture.cs
+++ /dev/null
@@ -1,340 +0,0 @@
-namespace Nancy.Authentication.Token.Tests
-{
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
-
- using FakeItEasy;
-
- using Nancy.Authentication.Token.Storage;
- using Nancy.Security;
- using Nancy.Tests;
- using Nancy.Tests.Fakes;
-
- using Xunit;
-
- public class TokenizerFixture
- {
- private readonly NancyContext context;
- private readonly FakeRequest request;
-
- public TokenizerFixture()
- {
- context = new NancyContext();
- request = new FakeRequest("GET", "/",
- new Dictionary>
- {
- {"User-Agent", new[] {"a fake user agent"}}
- });
- context.Request = request;
- }
-
- [Fact]
- public void Should_throw_argument_exception_if_token_expiration_exceeds_key_expiration()
- {
- var result = Record.Exception(() =>
- {
- CreateTokenizer(cfg => cfg.TokenExpiration(() => TimeSpan.FromDays(8)));
- });
-
- result.ShouldBeOfType();
- }
-
- [Fact]
- public void Should_throw_argument_exception_if_key_expiration_is_less_than_token_expiration()
- {
- var result = Record.Exception(() =>
- {
- CreateTokenizer(cfg => cfg.KeyExpiration(() => TimeSpan.FromTicks(1)));
- });
-
- result.ShouldBeOfType();
- }
-
- [Fact]
- public void Should_be_able_to_create_token_from_user_identity()
- {
- var tokenizer = CreateTokenizer();
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context);
-
- token.ShouldNotBeNull();
- }
-
- [Fact]
- public void Should_be_able_to_extract_user_identity_from_token()
- {
- var tokenizer = CreateTokenizer();
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context);
-
- var detokenizedIdentity = tokenizer.Detokenize(token, this.context, new DefaultUserIdentityResolver());
-
- detokenizedIdentity.ShouldNotBeNull();
-
- detokenizedIdentity.UserName.ShouldEqual("joe");
-
- detokenizedIdentity.Claims.ShouldEqualSequence(new[] { "claim1", "claim2" });
- }
-
- [Fact]
- public void Should_not_be_able_to_extract_user_identity_from_modified_token()
- {
- var tokenizer = CreateTokenizer();
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context);
- var parts = token.Split(new[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
- var bytes = Convert.FromBase64String(parts[0]);
-
- var tweak = new List(bytes);
- tweak.Add(Encoding.UTF8.GetBytes("X")[0]);
-
- var badToken = Convert.ToBase64String(tweak.ToArray()) + ":" + parts[1];
-
- var detokenizedIdentity = tokenizer.Detokenize(badToken, this.context, new DefaultUserIdentityResolver());
-
- detokenizedIdentity.ShouldBeNull();
- }
-
- [Fact]
- public void Should_be_able_to_extract_user_identity_from_token_with_extra_items()
- {
- var tokenizer = CreateTokenizer();
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context);
-
- var detokenizedIdentity = tokenizer.Detokenize(token, this.context, new DefaultUserIdentityResolver());
-
- detokenizedIdentity.ShouldNotBeNull();
-
- detokenizedIdentity.UserName.ShouldEqual("joe");
-
- detokenizedIdentity.Claims.ShouldEqualSequence(new[] { "claim1", "claim2" });
- }
-
- [Fact]
- public void Should_fail_to_detokenize_when_additional_items_do_not_match()
- {
- var tokenizer = CreateTokenizer();
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context);
-
- var badRequest = new FakeRequest("GET", "/",
- new Dictionary>
- {
- {"User-Agent", new[] {"uh oh! no matchey!"}}
- });
- var badContext = new NancyContext
- {
- Request = badRequest
- };
-
- var detokenizedIdentity = tokenizer.Detokenize(token, badContext, new DefaultUserIdentityResolver());
-
- detokenizedIdentity.ShouldBeNull();
- }
-
- [Fact]
- public void Should_expire_token_when_expiration_has_lapsed()
- {
- var tokenizer = CreateTokenizer(cfg => cfg.TokenExpiration(() => TimeSpan.FromMilliseconds(10)));
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context);
-
- Thread.Sleep(20);
-
- var detokenizedIdentity = tokenizer.Detokenize(token, this.context, new DefaultUserIdentityResolver());
-
- detokenizedIdentity.ShouldBeNull();
- }
-
- [Fact]
- public void Should_not_expire_token_when_key_expiration_has_lapsed_but_token_expiration_has_not()
- {
- var tokenizer = CreateTokenizer(cfg =>
- {
- cfg.TokenExpiration(() => TimeSpan.FromMilliseconds(50));
- cfg.KeyExpiration(() => TimeSpan.FromMilliseconds(100));
- });
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- tokenizer.Tokenize(identity, context); // prime the pump to generate a key
-
- Thread.Sleep(75); // key is 75% to its expiration
-
- var token = tokenizer.Tokenize(identity, context);
-
- Thread.Sleep(25); // key is now expired but should not be purged until token expiration lapses
-
- var detokenizedIdentity = tokenizer.Detokenize(token, this.context, new DefaultUserIdentityResolver());
-
- detokenizedIdentity.ShouldNotBeNull();
- }
-
- [Fact]
- public void Should_generate_new_token_after_previous_key_has_expired()
- {
- var tokenizer = CreateTokenizer(cfg =>
- {
- cfg.TokenExpiration(() => TimeSpan.FromMilliseconds(50));
- cfg.KeyExpiration(() => TimeSpan.FromMilliseconds(100));
- cfg.TokenStamp(() => new DateTime(2014, 1, 1));
- });
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context); // prime the pump to generate a key
-
- Thread.Sleep(120); // expire the key
-
- var secondToken = tokenizer.Tokenize(identity, context);
-
- token.ShouldNotEqual(secondToken);
- }
-
- [Fact]
- public void Should_expire_token_when_key_expiration_has_lapsed()
- {
- var tokenizer = CreateTokenizer(cfg =>
- {
- cfg.TokenExpiration(() => TimeSpan.FromMilliseconds(10));
- cfg.KeyExpiration(() => TimeSpan.FromMilliseconds(20));
- });
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- var token = tokenizer.Tokenize(identity, context);
-
- Thread.Sleep(30);
-
- var detokenizedIdentity = tokenizer.Detokenize(token, this.context, new DefaultUserIdentityResolver());
-
- detokenizedIdentity.ShouldBeNull();
- }
-
- [Fact]
- public void Should_retrieve_keys_from_store_when_tokenizer_is_created()
- {
- var keyCache = A.Fake();
-
- CreateTokenizer(cfg => cfg.WithKeyCache(keyCache));
-
- A.CallTo(() => keyCache.Retrieve()).MustHaveHappened(Repeated.Exactly.Once);
- }
-
- [Fact]
- public void Should_store_keys_when_the_first_token_is_tokenized()
- {
- var keyCache = A.Fake();
-
- var tokenizer = CreateTokenizer(cfg => cfg.WithKeyCache(keyCache));
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- tokenizer.Tokenize(identity, this.context);
-
- A.CallTo(() => keyCache.Store(A>.Ignored)).MustHaveHappened(Repeated.Exactly.Once);
- }
-
- [Fact]
- public void Should_store_keys_when_a_key_is_purged()
- {
- var keyCache = A.Fake();
-
- var tokenizer = CreateTokenizer(cfg =>
- {
- cfg.TokenExpiration(() => TimeSpan.FromMilliseconds(1));
- cfg.KeyExpiration(() => TimeSpan.FromMilliseconds(2));
- cfg.WithKeyCache(keyCache);
- });
-
- var identity = new FakeUserIdentity
- {
- UserName = "joe",
- Claims = new[] { "claim1", "claim2" }
- };
-
- tokenizer.Tokenize(identity, context);
-
- Thread.Sleep(5);
-
- tokenizer.Tokenize(identity, context);
-
- A.CallTo(() => keyCache.Store(A>.Ignored)).MustHaveHappened(Repeated.AtLeast.Once);
- }
-
- private Tokenizer CreateTokenizer(Action configuration = null)
- {
- var tokenizer = new Tokenizer(cfg =>
- {
- cfg.WithKeyCache(new InMemoryTokenKeyStore());
-
- if (configuration != null)
- {
- configuration(cfg);
- }
- });
- return tokenizer;
- }
-
- public class FakeUserIdentity : IUserIdentity
- {
- public string UserName { get; set; }
- public IEnumerable Claims { get; set; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token.Tests/app.config b/src/Nancy.Authentication.Token.Tests/app.config
deleted file mode 100644
index 6fe47bb290..0000000000
--- a/src/Nancy.Authentication.Token.Tests/app.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/src/Nancy.Authentication.Token.Tests/packages.config b/src/Nancy.Authentication.Token.Tests/packages.config
deleted file mode 100644
index 18f13949c6..0000000000
--- a/src/Nancy.Authentication.Token.Tests/packages.config
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/src/Nancy.Authentication.Token/DefaultUserIdentityResolver.cs b/src/Nancy.Authentication.Token/DefaultUserIdentityResolver.cs
deleted file mode 100644
index 28930d7207..0000000000
--- a/src/Nancy.Authentication.Token/DefaultUserIdentityResolver.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-namespace Nancy.Authentication.Token
-{
- using System.Collections.Generic;
-
- using Nancy.Security;
-
- ///
- /// The default user identity resolver.
- /// This creates a plain user identity based on username and claims.
- ///
- public class DefaultUserIdentityResolver : IUserIdentityResolver
- {
- ///
- /// Gets the from username and claims.
- ///
- /// The username.
- /// The claims.
- /// Current .
- /// A populated , or null
- public IUserIdentity GetUser(string userName, IEnumerable claims, NancyContext context)
- {
- return new TokenUserIdentity(userName, claims);
- }
-
- private class TokenUserIdentity : IUserIdentity
- {
- public TokenUserIdentity(string userName, IEnumerable claims)
- {
- this.UserName = userName;
- this.Claims = claims;
- }
-
- public string UserName { get; private set; }
-
- public IEnumerable Claims { get; private set; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/ITokenizer.cs b/src/Nancy.Authentication.Token/ITokenizer.cs
deleted file mode 100644
index 2d6655d940..0000000000
--- a/src/Nancy.Authentication.Token/ITokenizer.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace Nancy.Authentication.Token
-{
- using Nancy.Security;
-
- ///
- /// Encodes and decodes authorization tokens.
- ///
- public interface ITokenizer
- {
- ///
- /// Create a token from a
- ///
- /// The user identity from which to create a token.
- /// Current .
- /// The generated token.
- string Tokenize(IUserIdentity userIdentity, NancyContext context);
-
- ///
- /// Create a from a token
- ///
- /// The token from which to create a user identity.
- /// Current .
- /// The user identity resolver.
- /// The detokenized user identity.
- IUserIdentity Detokenize(string token, NancyContext context, IUserIdentityResolver userIdentityResolver);
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/IUserIdentityResolver.cs b/src/Nancy.Authentication.Token/IUserIdentityResolver.cs
deleted file mode 100644
index 1067922477..0000000000
--- a/src/Nancy.Authentication.Token/IUserIdentityResolver.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace Nancy.Authentication.Token
-{
- using System.Collections.Generic;
-
- using Nancy.Security;
-
- ///
- /// Provides a mapping between username and an .
- ///
- public interface IUserIdentityResolver
- {
- ///
- /// Gets the from username and claims.
- ///
- /// The username.
- /// The claims.
- /// Current .
- /// A populated , or null
- IUserIdentity GetUser(string userName, IEnumerable claims, NancyContext context);
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/Nancy.Authentication.Token.csproj b/src/Nancy.Authentication.Token/Nancy.Authentication.Token.csproj
deleted file mode 100644
index bf6935e3b8..0000000000
--- a/src/Nancy.Authentication.Token/Nancy.Authentication.Token.csproj
+++ /dev/null
@@ -1,104 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}
- Library
- Properties
- Nancy.Authentication.Token
- Nancy.Authentication.Token
- v4.5
- 512
- ..\
- true
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- bin\Debug\Nancy.Authentication.Token.XML
- false
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- bin\Release\Nancy.Authentication.Token.XML
- false
-
-
- true
- bin\MonoDebug\
- DEBUG;TRACE
- full
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- bin\MonoDebug\Nancy.Authentication.Token.XML
- false
-
-
- bin\MonoRelease\
- TRACE
- true
- pdbonly
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- bin\MonoRelease\Nancy.Authentication.Token.XML
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
- Properties\SharedAssemblyInfo.cs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {34576216-0dca-4b0f-a0dc-9075e75a676f}
- Nancy
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/Properties/Internals.cs b/src/Nancy.Authentication.Token/Properties/Internals.cs
deleted file mode 100644
index 312935b597..0000000000
--- a/src/Nancy.Authentication.Token/Properties/Internals.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-using System.Runtime.CompilerServices;
-
-[assembly: InternalsVisibleTo("Nancy.Authentication.Token.Tests")]
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/README.md b/src/Nancy.Authentication.Token/README.md
deleted file mode 100644
index 09b5a1c16a..0000000000
--- a/src/Nancy.Authentication.Token/README.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# Meet Nancy Token Authentication
-
-The Nancy.Authentication.Token project was built for use by heterogeneous clients (iOS apps, Android apps, Angular SPA apps, etc.) that all communicate with the same back-end Nancy application.
-
-## Rationale
-
-Token authentication and authorization was built with the following requirements:
-
-* No Cookies (since not all client apps are web browsers)
-* Avoid retrieving users and permissions from a backend data store once the user has been authenticated/authorized
-* Allow client apps to store a token containing the current user's credentials for resubmission on subsequent requests (after first authenticating)
-* Prevent rogue clients from simply generating their own spoofed credentials by incorporating a one-way hashing algorithm that ensures the token has not been tampered with
-* Use server side keys for token hash generation with a configurable key expiration interval
-* Use file system storage of server-side token generation private keys to allow keys to survive an application restart or an app pool recycle. Note: an "in memory" option is available primarily for testing, but could be used in a situation where expiring all user sessions on an application restart is acceptable behavior.
-
-Token Authentication can be wired up in a simliar fashion to other available forms of Nancy authentication.
-
-```csharp
-public class Bootstrapper : DefaultNancyBootstrapper
-{
- protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
- {
- TokenAuthentication.Enable(pipelines, new TokenAuthenticationConfiguration(container.Resolve()));
- }
-}
-```
-
-You will need to provide your own form of initial user authentication. This can use your own custom implementation that queries
-from a database, from an AD store, from a webservice, or any other form you choose. It could also use another form of Nancy authentication (Basic with an IUserValidator implementation
-for example).
-
-Tokens are generated from an `IUserIdentity` and a `NancyContext` by an implementation of `ITokenizer`. The
-default implementation is named `Tokenizer` and provides some configuration options. By default, it generates a token
-that includes the following components:
-
-* User name
-* Pipe separated list of user claims
-* UTC now in ticks
-* The client's "User-Agent" http header value (required)
-
-It is recommended that you configure the Tokenizer to use an additional piece of information that can uniquely identify
-the client device.
-
-The following code shows an example of how you can perform the initial user authorization and return the generated token to the client.
-
-```csharp
-public class AuthModule : NancyModule
-{
- public AuthModule(ITokenizer tokenizer)
- : base("/auth")
- {
- Post["/"] = x =>
- {
- var userName = (string)this.Request.Form.UserName;
- var password = (string)this.Request.Form.Password;
-
- var userIdentity = UserDatabase.ValidateUser(userName, password);
-
- if (userIdentity == null)
- {
- return HttpStatusCode.Unauthorized;
- }
-
- var token = tokenizer.Tokenize(userIdentity, Context);
-
- return new
- {
- Token = token,
- };
- };
-
- Get["/validation"] = _ =>
- {
- this.RequiresAuthentication();
- return "Yay! You are authenticated!";
- };
-
- Get["/admin"] = _ =>
- {
- this.RequiresAuthentication();
- this.RequiresClaims(new[] { "admin" });
- return "Yay! You are authorized!";
- };
- }
-}
-```
-
-## Contributors
-
-Nancy.Authentication.Token was originally created by the crack development team at [Lotpath](http://lotpath.com) ([Lotpath on github](http://github.com/Lotpath)).
diff --git a/src/Nancy.Authentication.Token/Storage/FileSystemTokenKeyStore.cs b/src/Nancy.Authentication.Token/Storage/FileSystemTokenKeyStore.cs
deleted file mode 100644
index ce40ae3ed1..0000000000
--- a/src/Nancy.Authentication.Token/Storage/FileSystemTokenKeyStore.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-namespace Nancy.Authentication.Token.Storage
-{
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Runtime.Serialization.Formatters.Binary;
-
- ///
- /// Stores encryption keys in the file system
- ///
- public class FileSystemTokenKeyStore : ITokenKeyStore
- {
- private IRootPathProvider rootPathProvider;
-
- private BinaryFormatter binaryFormatter;
-
- private static object syncLock = new object();
-
- ///
- /// Creates a new
- ///
- public FileSystemTokenKeyStore()
- : this(new DefaultRootPathProvider())
- {
- }
-
- ///
- /// Creates a new
- ///
- ///
- public FileSystemTokenKeyStore(IRootPathProvider rootPathProvider)
- {
- this.rootPathProvider = rootPathProvider;
- this.binaryFormatter = new BinaryFormatter();
- }
-
- ///
- /// Retrieves encryption keys.
- ///
- /// Keys
- public IDictionary Retrieve()
- {
- lock (syncLock)
- {
- if (!File.Exists(FilePath))
- {
- return new Dictionary();
- }
-
- using (var fileStream = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.None))
- {
- return (Dictionary)binaryFormatter.Deserialize(fileStream);
- }
- }
- }
-
- ///
- /// Stores encyrption keys.
- ///
- /// Keys
- public void Store(IDictionary keys)
- {
- lock (syncLock)
- {
- if (!Directory.Exists(StorageLocation))
- {
- Directory.CreateDirectory(StorageLocation);
- }
-
- var keyChain = new Dictionary(keys);
-
- using (var fileStream = new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
- {
- binaryFormatter.Serialize(fileStream, keyChain);
- }
- }
- }
-
- ///
- /// Purges encryption keys
- ///
- public void Purge()
- {
- if (File.Exists(FilePath))
- {
- File.Delete(FilePath);
- }
- if (Directory.Exists(StorageLocation))
- {
- Directory.Delete(StorageLocation);
- }
- }
-
- ///
- /// The location where token keys are stored
- ///
- public string FilePath
- {
- get
- {
- return Path.Combine(StorageLocation, "keyChain.bin");
- }
- }
-
- private string StorageLocation
- {
- get
- {
- return Path.Combine(rootPathProvider.GetRootPath(), "keyStore");
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/Storage/ITokenKeyStore.cs b/src/Nancy.Authentication.Token/Storage/ITokenKeyStore.cs
deleted file mode 100644
index 1cb92e4f2c..0000000000
--- a/src/Nancy.Authentication.Token/Storage/ITokenKeyStore.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace Nancy.Authentication.Token.Storage
-{
- using System;
- using System.Collections.Generic;
-
- ///
- /// Stores and retrieves encryption keys
- ///
- public interface ITokenKeyStore
- {
- ///
- /// Retrieves encryption keys
- ///
- /// Keys
- IDictionary Retrieve();
-
- ///
- /// Stores encryption keys
- ///
- /// Keys
- void Store(IDictionary keys);
-
- ///
- /// Purges encryption keys
- ///
- void Purge();
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/Storage/InMemoryTokenKeyStore.cs b/src/Nancy.Authentication.Token/Storage/InMemoryTokenKeyStore.cs
deleted file mode 100644
index 170eaa0226..0000000000
--- a/src/Nancy.Authentication.Token/Storage/InMemoryTokenKeyStore.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-namespace Nancy.Authentication.Token.Storage
-{
- using System;
- using System.Collections.Generic;
-
- ///
- /// In in memory implementation of . Useful for testing or scenarios
- /// where encryption keys do not need to persist across application restarts (due to updates, app pool
- /// expiration, etc.)
- ///
- public class InMemoryTokenKeyStore : ITokenKeyStore
- {
- private IDictionary keys;
-
- ///
- /// Retrieves encryption keys
- ///
- /// Keys
- public IDictionary Retrieve()
- {
- return new Dictionary(this.keys ?? new Dictionary());
- }
-
- ///
- /// Stores encryption keys
- ///
- /// Keys
- public void Store(IDictionary keys)
- {
- this.keys = new Dictionary(keys);
- }
-
- ///
- /// Purges encryption keys
- ///
- public void Purge()
- {
- this.keys = new Dictionary();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/TokenAuthentication.cs b/src/Nancy.Authentication.Token/TokenAuthentication.cs
deleted file mode 100644
index 040c27e008..0000000000
--- a/src/Nancy.Authentication.Token/TokenAuthentication.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-namespace Nancy.Authentication.Token
-{
- using System;
-
- using Nancy.Bootstrapper;
- using Nancy.Security;
-
- ///
- /// Nancy Token authentication implementation
- ///
- public static class TokenAuthentication
- {
- private const string Scheme = "Token";
-
- ///
- /// Enables Token authentication for the application
- ///
- /// Pipelines to add handlers to (usually "this")
- /// Forms authentication configuration
- public static void Enable(IPipelines pipelines, TokenAuthenticationConfiguration configuration)
- {
- if (pipelines == null)
- {
- throw new ArgumentNullException("pipelines");
- }
-
- if (configuration == null)
- {
- throw new ArgumentNullException("configuration");
- }
-
- pipelines.BeforeRequest.AddItemToStartOfPipeline(GetCredentialRetrievalHook(configuration));
- }
-
- ///
- /// Enables Token authentication for a module
- ///
- /// Module to add handlers to (usually "this")
- /// Forms authentication configuration
- public static void Enable(INancyModule module, TokenAuthenticationConfiguration configuration)
- {
- if (module == null)
- {
- throw new ArgumentNullException("module");
- }
-
- if (configuration == null)
- {
- throw new ArgumentNullException("configuration");
- }
-
- module.RequiresAuthentication();
- module.Before.AddItemToStartOfPipeline(GetCredentialRetrievalHook(configuration));
- }
-
- ///
- /// Gets the pre request hook for loading the authenticated user's details
- /// from the auth header.
- ///
- /// Token authentication configuration to use
- /// Pre request hook delegate
- private static Func GetCredentialRetrievalHook(TokenAuthenticationConfiguration configuration)
- {
- if (configuration == null)
- {
- throw new ArgumentNullException("configuration");
- }
-
- return context =>
- {
- RetrieveCredentials(context, configuration);
- return null;
- };
- }
-
- private static void RetrieveCredentials(NancyContext context, TokenAuthenticationConfiguration configuration)
- {
- var token = ExtractTokenFromHeader(context.Request);
- if (token == null)
- {
- return;
- }
-
- var user = configuration.Tokenizer.Detokenize(token, context, configuration.UserIdentityResolver);
- if (user != null)
- {
- context.CurrentUser = user;
- }
- }
-
- private static string ExtractTokenFromHeader(Request request)
- {
- var authorization = request.Headers.Authorization;
-
- if (string.IsNullOrEmpty(authorization))
- {
- return null;
- }
-
- if (!authorization.StartsWith(Scheme))
- {
- return null;
- }
-
- try
- {
- var encodedToken = authorization.Substring(Scheme.Length).Trim();
- return String.IsNullOrWhiteSpace(encodedToken) ? null : encodedToken;
- }
- catch (FormatException)
- {
- return null;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/TokenAuthenticationConfiguration.cs b/src/Nancy.Authentication.Token/TokenAuthenticationConfiguration.cs
deleted file mode 100644
index 8ddc4f107b..0000000000
--- a/src/Nancy.Authentication.Token/TokenAuthenticationConfiguration.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-namespace Nancy.Authentication.Token
-{
- using System;
-
- ///
- /// Configuration options for token authentication
- ///
- public class TokenAuthenticationConfiguration
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// A valid instance of class
- /// The user identity resolver.
- public TokenAuthenticationConfiguration(ITokenizer tokenizer, IUserIdentityResolver userIdentityResolver = null)
- {
- if (tokenizer == null)
- {
- throw new ArgumentNullException("tokenizer");
- }
-
- this.Tokenizer = tokenizer;
- this.UserIdentityResolver = userIdentityResolver ?? new DefaultUserIdentityResolver();
- }
-
- ///
- /// Gets the token validator
- ///
- public ITokenizer Tokenizer { get; private set; }
-
- ///
- /// Gets or sets the user identity resolver
- ///
- public IUserIdentityResolver UserIdentityResolver { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Authentication.Token/Tokenizer.cs b/src/Nancy.Authentication.Token/Tokenizer.cs
deleted file mode 100644
index 062ab003c2..0000000000
--- a/src/Nancy.Authentication.Token/Tokenizer.cs
+++ /dev/null
@@ -1,413 +0,0 @@
-namespace Nancy.Authentication.Token
-{
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Security.Cryptography;
- using System.Text;
-
- using Nancy.Authentication.Token.Storage;
- using Nancy.ErrorHandling;
- using Nancy.Security;
-
- ///
- /// Default implementation of
- ///
- public class Tokenizer : ITokenizer
- {
- private readonly TokenValidator validator;
- private ITokenKeyStore keyStore = new FileSystemTokenKeyStore();
- private Encoding encoding = Encoding.UTF8;
- private string claimsDelimiter = "|";
- private string hashDelimiter = ":";
- private string itemDelimiter = Environment.NewLine;
- private Func tokenStamp = () => DateTime.UtcNow;
- private Func now = () => DateTime.UtcNow;
- private Func tokenExpiration = () => TimeSpan.FromDays(1);
- private Func keyExpiration = () => TimeSpan.FromDays(7);
-
- private Func[] additionalItems =
- {
- ctx => ctx.Request.Headers.UserAgent
- };
-
- ///
- /// Initializes a new instance of the class.
- ///
- public Tokenizer()
- : this(null)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The configuration that should be used by the tokenizer.
- public Tokenizer(Action configuration)
- {
- if (configuration != null)
- {
- var configurator = new TokenizerConfigurator(this);
- configuration.Invoke(configurator);
- }
- var keyRing = new TokenKeyRing(this);
- this.validator = new TokenValidator(keyRing);
- }
-
- ///
- /// Creates a token from a .
- ///
- /// The user identity from which to create a token.
- /// Current .
- /// The generated token.
- public string Tokenize(IUserIdentity userIdentity, NancyContext context)
- {
- var items = new List
- {
- userIdentity.UserName,
- string.Join(this.claimsDelimiter, userIdentity.Claims),
- this.tokenStamp().Ticks.ToString(CultureInfo.InvariantCulture)
- };
-
- if (this.additionalItems != null)
- {
- foreach (var item in this.additionalItems.Select(additionalItem => additionalItem(context)))
- {
- if (string.IsNullOrWhiteSpace(item))
- {
- throw new RouteExecutionEarlyExitException(new Response { StatusCode = HttpStatusCode.Unauthorized });
- }
- items.Add(item);
- }
- }
-
- var message = string.Join(this.itemDelimiter, items);
- var token = CreateToken(message);
- return token;
- }
-
- ///
- /// Creates a from a token.
- ///
- /// The token from which to create a user identity.
- /// Current .
- /// The user identity resolver.
- /// The detokenized user identity.
- public IUserIdentity Detokenize(string token, NancyContext context, IUserIdentityResolver userIdentityResolver)
- {
- var tokenComponents = token.Split(new[] { this.hashDelimiter }, StringSplitOptions.None);
- if (tokenComponents.Length != 2)
- {
- return null;
- }
-
- var messagebytes = Convert.FromBase64String(tokenComponents[0]);
- var hash = Convert.FromBase64String(tokenComponents[1]);
-
- if (!this.validator.IsValid(messagebytes, hash))
- {
- return null;
- }
-
- var items = this.encoding.GetString(messagebytes).Split(new[] { this.itemDelimiter }, StringSplitOptions.None);
-
- if (this.additionalItems != null)
- {
- var additionalItemCount = additionalItems.Count();
- for (var i = 0; i < additionalItemCount; i++)
- {
- var tokenizedValue = items[i + 3];
- var currentValue = additionalItems.ElementAt(i)(context);
- if (tokenizedValue != currentValue)
- {
- // todo: may need to log here as this probably indicates hacking
- return null;
- }
- }
- }
-
- var generatedOn = new DateTime(long.Parse(items[2]));
-
- if (tokenStamp() - generatedOn > tokenExpiration())
- {
- return null;
- }
-
- var userName = items[0];
- var claims = items[1].Split(new[] { this.claimsDelimiter }, StringSplitOptions.None);
-
- return userIdentityResolver.GetUser(userName, claims, context);
- }
-
- private string CreateToken(string message)
- {
- var messagebytes = this.encoding.GetBytes(message);
- var hash = this.validator.CreateHash(messagebytes);
- return Convert.ToBase64String(messagebytes) + this.hashDelimiter + Convert.ToBase64String(hash);
- }
-
- ///
- /// Provides an API for configuring a instance.
- ///
- public class TokenizerConfigurator
- {
- private readonly Tokenizer tokenizer;
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- public TokenizerConfigurator(Tokenizer tokenizer)
- {
- this.tokenizer = tokenizer;
- }
-
- ///
- /// Sets the token key store used by the tokenizer
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator WithKeyCache(ITokenKeyStore store)
- {
- this.tokenizer.keyStore = store;
- return this;
- }
-
- ///
- /// Sets the encoding used by the tokenizer
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator Encoding(Encoding encoding)
- {
- this.tokenizer.encoding = encoding;
- return this;
- }
-
- ///
- /// Sets the delimiter between document and its hash
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator HashDelimiter(string hashDelimiter)
- {
- this.tokenizer.hashDelimiter = hashDelimiter;
- return this;
- }
-
- ///
- /// Sets the delimiter between each item to be tokenized
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator ItemDelimiter(string itemDelimiter)
- {
- this.tokenizer.itemDelimiter = itemDelimiter;
- return this;
- }
-
- ///
- /// Sets the delimiter between each claim
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator ClaimsDelimiter(string claimsDelimiter)
- {
- this.tokenizer.claimsDelimiter = claimsDelimiter;
- return this;
- }
-
- ///
- /// Sets the token expiration interval. An expired token will cause a user to become unauthorized (logged out).
- /// Suggested value is 1 day (which is also the default).
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator TokenExpiration(Func expiration)
- {
- this.tokenizer.tokenExpiration = expiration;
-
- if (this.tokenizer.tokenExpiration() >= this.tokenizer.keyExpiration())
- {
- throw new ArgumentException("Token expiration must be less than key expiration", "expiration");
- }
-
- return this;
- }
-
- ///
- /// Sets the key expiration interval. Must be longer than the value.
- /// When keys expire, they are scheduled to purge once any tokens they have been used to generate have expired.
- /// Suggested range is 2 to 14 days. The default is 7 days.
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator KeyExpiration(Func expiration)
- {
- this.tokenizer.keyExpiration = expiration;
-
- if (this.tokenizer.tokenExpiration() >= this.tokenizer.keyExpiration())
- {
- throw new ArgumentException("Key expiration must be greater than token expiration", "expiration");
- }
-
- return this;
- }
-
- ///
- /// Sets the token-generated-at timestamp
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator TokenStamp(Func tokenStamp)
- {
- this.tokenizer.tokenStamp = tokenStamp;
- return this;
- }
-
- ///
- /// Sets the current date/time.
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator Now(Func now)
- {
- this.tokenizer.now = now;
- return this;
- }
-
- ///
- /// Sets any additional items to be included when tokenizing. The default includes Request.Headers.UserAgent.
- ///
- ///
- /// A reference to the current
- public TokenizerConfigurator AdditionalItems(params Func[] additionalItems)
- {
- this.tokenizer.additionalItems = additionalItems;
- return this;
- }
- }
-
- private class TokenValidator
- {
- private readonly TokenKeyRing keyRing;
-
- internal TokenValidator(TokenKeyRing keyRing)
- {
- this.keyRing = keyRing;
- }
-
- public bool IsValid(byte[] message, byte[] hash)
- {
- return this.keyRing
- .AllKeys()
- .Select(key => GenerateHash(key, message))
- .Any(hash.SequenceEqual);
- }
-
- public byte[] CreateHash(byte[] message)
- {
- var key = this.keyRing
- .NonExpiredKeys()
- .First();
-
- return GenerateHash(key, message);
- }
-
- private byte[] GenerateHash(byte[] key, byte[] message)
- {
- using (var hmac = new HMACSHA256(key))
- {
- return hmac.ComputeHash(message);
- }
- }
- }
-
- private class TokenKeyRing
- {
- private readonly Tokenizer tokenizer;
-
- private readonly IDictionary keys;
-
- internal TokenKeyRing(Tokenizer tokenizer)
- {
- this.tokenizer = tokenizer;
- keys = this.tokenizer.keyStore.Retrieve();
- }
-
- public IEnumerable AllKeys()
- {
- return this.Keys(true);
- }
-
- public IEnumerable NonExpiredKeys()
- {
- return this.Keys(false);
- }
-
- private IEnumerable Keys(bool includeExpired)
- {
- var entriesToPurge = new List();
- var validKeys = new List();
-
- foreach (var entry in this.keys.OrderByDescending(x => x.Key))
- {
- if (IsReadyToPurge(entry))
- {
- entriesToPurge.Add(entry.Key);
- }
- else if (!IsExpired(entry) || includeExpired)
- {
- validKeys.Add(entry.Value);
- }
- }
-
- var shouldStore = false;
-
- foreach (var entry in entriesToPurge)
- {
- this.keys.Remove(entry);
- shouldStore = true;
- }
-
- if (validKeys.Count == 0)
- {
- var key = CreateKey();
- this.keys[this.tokenizer.now()] = key;
- validKeys.Add(key);
- shouldStore = true;
- }
-
- if (shouldStore)
- {
- this.tokenizer.keyStore.Store(keys);
- }
-
- return validKeys;
- }
-
- private bool IsReadyToPurge(KeyValuePair entry)
- {
- return this.tokenizer.now() - entry.Key > (this.tokenizer.keyExpiration() + this.tokenizer.tokenExpiration());
- }
-
- private bool IsExpired(KeyValuePair entry)
- {
- return this.tokenizer.now() - entry.Key > this.tokenizer.keyExpiration();
- }
-
- private byte[] CreateKey()
- {
- var secretKey = new byte[64];
-
- using (var rng = new RNGCryptoServiceProvider())
- {
- rng.GetBytes(secretKey);
- }
-
- return secretKey;
- }
- }
- }
-}
diff --git a/src/Nancy.Authentication.Token/nancy.authentication.token.nuspec b/src/Nancy.Authentication.Token/nancy.authentication.token.nuspec
deleted file mode 100644
index 8a1fb8c3d4..0000000000
--- a/src/Nancy.Authentication.Token/nancy.authentication.token.nuspec
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- Nancy.Authentication.Token
- 0.0.0
- Andreas Håkansson, Steven Robbins and contributors
- false
- A token based authentication provider for Nancy.
- Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications.
- en-US
- Andreas Håkansson, Steven Robbins and contributors
- http://nancyfx.org/nancy-nuget.png
- https://github.com/NancyFx/Nancy/blob/master/license.txt
- http://nancyfx.org
-
-
-
- Nancy Token Authentication
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token.TestingDemo/LoginFixture.cs b/src/Nancy.Demo.Authentication.Token.TestingDemo/LoginFixture.cs
deleted file mode 100644
index d10580115b..0000000000
--- a/src/Nancy.Demo.Authentication.Token.TestingDemo/LoginFixture.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-namespace Nancy.Demo.Authentication.Token.TestingDemo
-{
- using Nancy.Testing;
- using Nancy.Tests;
-
- using Xunit;
-
- public class LoginFixture
- {
- private readonly Browser browser;
-
- public LoginFixture()
- {
- var bootstrapper = new TestBootstrapper();
- this.browser = new Browser(bootstrapper);
- }
-
- [Fact]
- public void Should_return_generated_token_for_valid_user_credentials()
- {
- // Given, When
- var response = this.browser.Post("/auth/", (with) =>
- {
- with.HttpRequest();
- with.Accept("application/json");
- with.Header("User-Agent", "Nancy Browser");
- with.FormValue("UserName", "demo");
- with.FormValue("Password", "demo");
- });
-
- // Then
- response.Body.DeserializeJson().ShouldNotBeNull();
- }
-
- [Fact]
- public void Should_return_unauthorized_for_invalid_user_credentials()
- {
- // Given, When
- var response = this.browser.Post("/auth/", (with) =>
- {
- with.HttpRequest();
- with.Accept("application/json");
- with.Header("User-Agent", "Nancy Browser");
- with.FormValue("UserName", "bad");
- with.FormValue("Password", "boy");
- });
-
- // Then
- response.StatusCode.ShouldEqual(HttpStatusCode.Unauthorized);
- }
-
- [Fact]
- public void Should_return_unauthorized_when_not_authenticated()
- {
- // Given, When
- var response = this.browser.Get("/auth/validation/", (with) =>
- {
- with.HttpRequest();
- });
-
- // Then
- response.StatusCode.ShouldEqual(HttpStatusCode.Unauthorized);
- }
-
- [Fact]
- public void Should_return_forbidden_when_not_authorized()
- {
- // Given, When
- var response = this.browser.Post("/auth/", (with) =>
- {
- with.HttpRequest();
- with.Accept("application/json");
- with.Header("User-Agent", "Nancy Browser");
- with.FormValue("UserName", "nonadmin");
- with.FormValue("Password", "nonadmin");
- });
-
- var token = response.Body.DeserializeJson().Token;
-
- var secondResponse = response.Then.Get("/auth/admin/", with =>
- {
- with.HttpRequest();
- with.Header("User-Agent", "Nancy Browser");
- with.Header("Authorization", "Token " + token);
- });
-
- // Then
- secondResponse.StatusCode.ShouldEqual(HttpStatusCode.Forbidden);
- }
-
- [Fact]
- public void Should_return_unauthorized_without_user_agent()
- {
- // Given, When
- var response = this.browser.Post("/auth/", (with) =>
- {
- with.HttpRequest();
- with.Accept("application/json");
- with.FormValue("UserName", "demo");
- with.FormValue("Password", "demo");
- with.Header("User-Agent", null);
- });
-
- // Then
- response.StatusCode.ShouldEqual(HttpStatusCode.Unauthorized);
- }
-
- public class AuthResponse
- {
- public string Token { get; set; }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token.TestingDemo/Nancy.Demo.Authentication.Token.TestingDemo.csproj b/src/Nancy.Demo.Authentication.Token.TestingDemo/Nancy.Demo.Authentication.Token.TestingDemo.csproj
deleted file mode 100644
index dd44e0e1ea..0000000000
--- a/src/Nancy.Demo.Authentication.Token.TestingDemo/Nancy.Demo.Authentication.Token.TestingDemo.csproj
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}
- Library
- Properties
- Nancy.Demo.Authentication.Token.TestingDemo
- Nancy.Demo.Authentication.Token.TestingDemo
- v4.5
- 512
-
-
-
- true
- full
- false
- bin\
- DEBUG;TRACE
- prompt
- 4
- false
-
-
- pdbonly
- true
- bin\
- TRACE
- prompt
- 4
- false
-
-
- true
- bin\
- DEBUG;TRACE
- full
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- false
-
-
- bin\
- TRACE
- true
- pdbonly
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- false
-
-
-
-
-
-
-
-
-
-
- False
- ..\packages\xunit.1.9.1\lib\net20\xunit.dll
-
-
- False
- ..\packages\xunit.extensions.1.9.1\lib\net20\xunit.extensions.dll
-
-
-
-
- ShouldExtensions.cs
-
-
- Properties\SharedAssemblyInfo.cs
-
-
-
-
-
-
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}
- Nancy.Authentication.Token
-
-
- {35460aa4-b94a-4b64-9418-7243ec3d2f01}
- Nancy.Demo.Authentication.Token
-
-
- {d79203c0-b672-4751-9c95-c3ab7d3fefbe}
- Nancy.Testing
-
-
- {2c6f51df-015c-4db6-b44c-0e5e4f25e2a9}
- Nancy.ViewEngines.Razor
-
-
- {34576216-0dca-4b0f-a0dc-9075e75a676f}
- Nancy
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token.TestingDemo/TestBootstrapper.cs b/src/Nancy.Demo.Authentication.Token.TestingDemo/TestBootstrapper.cs
deleted file mode 100644
index ace6cb1cc6..0000000000
--- a/src/Nancy.Demo.Authentication.Token.TestingDemo/TestBootstrapper.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-namespace Nancy.Demo.Authentication.Token.TestingDemo
-{
- using System;
- using System.IO;
-
- using Nancy.Authentication.Token;
- using Nancy.Authentication.Token.Storage;
- using Nancy.Testing;
- using Nancy.Testing.Fakes;
- using Nancy.TinyIoc;
-
- public class TestBootstrapper : TokenAuthBootstrapper
- {
- protected override void ConfigureApplicationContainer(TinyIoCContainer container)
- {
- container.Register(new Tokenizer(cfg => cfg.WithKeyCache(new InMemoryTokenKeyStore())));
- }
-
- protected override IRootPathProvider RootPathProvider
- {
- get
- {
- var assemblyFilePath =
- new Uri(typeof(TokenAuthBootstrapper).Assembly.CodeBase).LocalPath;
-
- var assemblyPath =
- Path.GetDirectoryName(assemblyFilePath);
-
- var rootPath =
- PathHelper.GetParent(assemblyPath, 2);
-
- rootPath =
- Path.Combine(rootPath, @"Nancy.Demo.Authentication.Token");
-
- FakeRootPathProvider.RootPath = rootPath;
-
- return new FakeRootPathProvider();
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token.TestingDemo/packages.config b/src/Nancy.Demo.Authentication.Token.TestingDemo/packages.config
deleted file mode 100644
index 0c7d926236..0000000000
--- a/src/Nancy.Demo.Authentication.Token.TestingDemo/packages.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/src/Nancy.Demo.Authentication.Token/AuthModule.cs b/src/Nancy.Demo.Authentication.Token/AuthModule.cs
deleted file mode 100644
index 86c35dd5d3..0000000000
--- a/src/Nancy.Demo.Authentication.Token/AuthModule.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-namespace Nancy.Demo.Authentication.Token
-{
- using Nancy.Authentication.Token;
- using Nancy.Security;
-
- public class AuthModule : NancyModule
- {
- public AuthModule(ITokenizer tokenizer)
- : base("/auth")
- {
- Post["/"] = x =>
- {
- var userName = (string)this.Request.Form.UserName;
- var password = (string)this.Request.Form.Password;
-
- var userIdentity = UserDatabase.ValidateUser(userName, password);
-
- if (userIdentity == null)
- {
- return HttpStatusCode.Unauthorized;
- }
-
- var token = tokenizer.Tokenize(userIdentity, Context);
-
- return new
- {
- Token = token,
- };
- };
-
- Get["/validation"] = _ =>
- {
- this.RequiresAuthentication();
- return "Yay! You are authenticated!";
- };
-
- Get["/admin"] = _ =>
- {
- this.RequiresClaims(new[] { "admin" });
- return "Yay! You are authorized!";
- };
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token/DemoUserIdentity.cs b/src/Nancy.Demo.Authentication.Token/DemoUserIdentity.cs
deleted file mode 100644
index f8be8595b4..0000000000
--- a/src/Nancy.Demo.Authentication.Token/DemoUserIdentity.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace Nancy.Demo.Authentication.Token
-{
- using System.Collections.Generic;
-
- using Nancy.Security;
-
- public class DemoUserIdentity : IUserIdentity
- {
- public string UserName { get; set; }
- public IEnumerable Claims { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token/Nancy.Demo.Authentication.Token.csproj b/src/Nancy.Demo.Authentication.Token/Nancy.Demo.Authentication.Token.csproj
deleted file mode 100644
index 6657ca240c..0000000000
--- a/src/Nancy.Demo.Authentication.Token/Nancy.Demo.Authentication.Token.csproj
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}
- Exe
- Properties
- Nancy.Demo.Authentication.Token
- Nancy.Demo.Authentication.Token
- v4.5
- 512
-
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- false
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- false
-
-
-
-
-
-
- true
- bin\MonoDebug\
- DEBUG;TRACE
- full
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- false
-
-
- bin\MonoRelease\
- TRACE
- true
- pdbonly
- AnyCPU
- prompt
- MinimumRecommendedRules.ruleset
- false
-
-
-
-
-
-
-
-
-
-
- Properties\SharedAssemblyInfo.cs
-
-
-
-
-
-
-
-
-
-
-
-
- {97fa024a-f6ed-4086-bcc1-1a51be63474c}
- Nancy.Authentication.Token
-
-
- {aa7f66eb-ec2c-47de-855f-30b3e6ef2134}
- Nancy.Hosting.Self
-
-
- {34576216-0dca-4b0f-a0dc-9075e75a676f}
- Nancy
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token/Program.cs b/src/Nancy.Demo.Authentication.Token/Program.cs
deleted file mode 100644
index 21893aa7cc..0000000000
--- a/src/Nancy.Demo.Authentication.Token/Program.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace Nancy.Demo.Authentication.Token
-{
- using System;
-
- using Nancy.Hosting.Self;
-
- class Program
- {
- static void Main(string[] args)
- {
- var uri =
- new Uri("http://localhost:3579");
-
- using (var host = new NancyHost(uri))
- {
- host.Start();
-
- Console.WriteLine("Your application is running on " + uri);
- Console.WriteLine("Press any [Enter] to close the host.");
- Console.ReadLine();
- }
- }
- }
-}
diff --git a/src/Nancy.Demo.Authentication.Token/TokenAuthBootstrapper.cs b/src/Nancy.Demo.Authentication.Token/TokenAuthBootstrapper.cs
deleted file mode 100644
index 1bf0be96d3..0000000000
--- a/src/Nancy.Demo.Authentication.Token/TokenAuthBootstrapper.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace Nancy.Demo.Authentication.Token
-{
- using Nancy.Authentication.Token;
- using Nancy.Bootstrapper;
- using Nancy.TinyIoc;
-
- public class TokenAuthBootstrapper : DefaultNancyBootstrapper
- {
- protected override void ConfigureApplicationContainer(TinyIoCContainer container)
- {
- container.Register(new Tokenizer());
- // Example options for specifying additional values for token generation
-
- //container.Register(new Tokenizer(cfg =>
- // cfg.AdditionalItems(
- // ctx =>
- // ctx.Request.Headers["X-Custom-Header"].FirstOrDefault(),
- // ctx => ctx.Request.Query.extraValue)));
- }
-
- protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
- {
- TokenAuthentication.Enable(pipelines, new TokenAuthenticationConfiguration(container.Resolve()));
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token/UserDatabase.cs b/src/Nancy.Demo.Authentication.Token/UserDatabase.cs
deleted file mode 100644
index 59e7008819..0000000000
--- a/src/Nancy.Demo.Authentication.Token/UserDatabase.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-namespace Nancy.Demo.Authentication.Token
-{
- using System;
- using System.Collections.Generic;
- using System.Linq;
-
- using Nancy.Security;
-
- public class UserDatabase
- {
- private static readonly List> Users = new List>();
- private static readonly Dictionary> Claims = new Dictionary>();
-
- static UserDatabase()
- {
- Users.Add(new Tuple("demo", "demo"));
- Claims.Add("demo", new List { "demo", "admin" });
-
- Users.Add(new Tuple("nonadmin", "nonadmin"));
- Claims.Add("nonadmin", new List { "demo", });
- }
-
- public static IUserIdentity ValidateUser(string userName, string password)
- {
- var user = Users.FirstOrDefault(x => x.Item1 == userName && x.Item2 == password);
- if (user == null)
- {
- return null;
- }
-
- var claims = Claims[user.Item1];
- return new DemoUserIdentity {UserName = user.Item1, Claims = claims};
- }
- }
-}
\ No newline at end of file
diff --git a/src/Nancy.Demo.Authentication.Token/app.config b/src/Nancy.Demo.Authentication.Token/app.config
deleted file mode 100644
index 6fe47bb290..0000000000
--- a/src/Nancy.Demo.Authentication.Token/app.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/src/Nancy.sln b/src/Nancy.sln
index 7093039a3e..659a68f237 100644
--- a/src/Nancy.sln
+++ b/src/Nancy.sln
@@ -123,14 +123,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Owin.Tests", "Nancy.O
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Demo.ConstraintRouting", "Nancy.Demo.ConstraintRouting\Nancy.Demo.ConstraintRouting.csproj", "{972C2D45-49B6-4109-9A3A-0C8BC9225B95}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Authentication.Token.Tests", "Nancy.Authentication.Token.Tests\Nancy.Authentication.Token.Tests.csproj", "{3C131D45-AF1D-4659-8B26-A9F55EED0D20}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Authentication.Token", "Nancy.Authentication.Token\Nancy.Authentication.Token.csproj", "{97FA024A-F6ED-4086-BCC1-1A51BE63474C}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Demo.Authentication.Token", "Nancy.Demo.Authentication.Token\Nancy.Demo.Authentication.Token.csproj", "{35460AA4-B94A-4B64-9418-7243EC3D2F01}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Demo.Authentication.Token.TestingDemo", "Nancy.Demo.Authentication.Token.TestingDemo\Nancy.Demo.Authentication.Token.TestingDemo.csproj", "{9121DA01-7BFD-49F0-9937-0D3E7875ADB9}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Metadata.Modules", "Nancy.Metadata.Modules\Nancy.Metadata.Modules.csproj", "{DC8AAA8B-7FD0-47C4-9413-3CC94088BCC4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Metadata.Modules.Tests", "Nancy.Metadata.Modules.Tests\Nancy.Metadata.Modules.Tests.csproj", "{508A3A68-2012-4E62-925F-2F3083A013FC}"
@@ -817,54 +809,6 @@ Global
{972C2D45-49B6-4109-9A3A-0C8BC9225B95}.Release|Any CPU.ActiveCfg = Release|Any CPU
{972C2D45-49B6-4109-9A3A-0C8BC9225B95}.Release|Any CPU.Build.0 = Release|Any CPU
{972C2D45-49B6-4109-9A3A-0C8BC9225B95}.Release|x86.ActiveCfg = Release|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.Debug|x86.ActiveCfg = Debug|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.MonoDebug|Any CPU.ActiveCfg = MonoDebug|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.MonoDebug|Any CPU.Build.0 = MonoDebug|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.MonoDebug|x86.ActiveCfg = Debug|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.MonoRelease|Any CPU.ActiveCfg = MonoRelease|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.MonoRelease|Any CPU.Build.0 = MonoRelease|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.MonoRelease|x86.ActiveCfg = Release|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.Release|Any CPU.Build.0 = Release|Any CPU
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20}.Release|x86.ActiveCfg = Release|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.Debug|x86.ActiveCfg = Debug|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.MonoDebug|Any CPU.ActiveCfg = MonoDebug|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.MonoDebug|Any CPU.Build.0 = MonoDebug|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.MonoDebug|x86.ActiveCfg = Debug|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.MonoRelease|Any CPU.ActiveCfg = MonoRelease|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.MonoRelease|Any CPU.Build.0 = MonoRelease|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.MonoRelease|x86.ActiveCfg = Release|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.Release|Any CPU.Build.0 = Release|Any CPU
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C}.Release|x86.ActiveCfg = Release|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Debug|x86.ActiveCfg = Debug|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.MonoDebug|Any CPU.ActiveCfg = MonoDebug|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.MonoDebug|Any CPU.Build.0 = MonoDebug|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.MonoDebug|x86.ActiveCfg = Debug|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.MonoRelease|Any CPU.ActiveCfg = MonoRelease|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.MonoRelease|Any CPU.Build.0 = MonoRelease|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.MonoRelease|x86.ActiveCfg = Release|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Release|Any CPU.Build.0 = Release|Any CPU
- {35460AA4-B94A-4B64-9418-7243EC3D2F01}.Release|x86.ActiveCfg = Release|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.Debug|x86.ActiveCfg = Debug|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.MonoDebug|Any CPU.ActiveCfg = MonoDebug|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.MonoDebug|Any CPU.Build.0 = MonoDebug|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.MonoDebug|x86.ActiveCfg = Debug|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.MonoRelease|Any CPU.ActiveCfg = MonoRelease|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.MonoRelease|Any CPU.Build.0 = MonoRelease|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.MonoRelease|x86.ActiveCfg = Release|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.Release|Any CPU.Build.0 = Release|Any CPU
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9}.Release|x86.ActiveCfg = Release|Any CPU
{DC8AAA8B-7FD0-47C4-9413-3CC94088BCC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC8AAA8B-7FD0-47C4-9413-3CC94088BCC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC8AAA8B-7FD0-47C4-9413-3CC94088BCC4}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -966,10 +910,6 @@ Global
{864AF449-0902-44FC-BEEE-06BA9A6F4A8F} = {E944109B-0B7A-4ADE-8602-004CEFA5897D}
{34DDDA42-4041-4F92-87A6-F0E8CE12C7E3} = {A427F9F8-0A6F-4EEA-837F-FCDAB6E7D4B3}
{972C2D45-49B6-4109-9A3A-0C8BC9225B95} = {4A24657F-9695-437B-9702-2541ED280628}
- {3C131D45-AF1D-4659-8B26-A9F55EED0D20} = {A427F9F8-0A6F-4EEA-837F-FCDAB6E7D4B3}
- {97FA024A-F6ED-4086-BCC1-1A51BE63474C} = {E944109B-0B7A-4ADE-8602-004CEFA5897D}
- {35460AA4-B94A-4B64-9418-7243EC3D2F01} = {4A24657F-9695-437B-9702-2541ED280628}
- {9121DA01-7BFD-49F0-9937-0D3E7875ADB9} = {4A24657F-9695-437B-9702-2541ED280628}
{DC8AAA8B-7FD0-47C4-9413-3CC94088BCC4} = {E944109B-0B7A-4ADE-8602-004CEFA5897D}
{508A3A68-2012-4E62-925F-2F3083A013FC} = {A427F9F8-0A6F-4EEA-837F-FCDAB6E7D4B3}
{7959D79C-9E2B-4871-9470-6A6B527ABE5E} = {4A24657F-9695-437B-9702-2541ED280628}