This repository has been archived by the owner on Jan 24, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Token authentication and authorization implementation.
- Loading branch information
1 parent
e68ea60
commit 9ae0a54
Showing
30 changed files
with
2,251 additions
and
0 deletions.
There are no files selected for viewing
113 changes: 113 additions & 0 deletions
113
src/Nancy.Authentication.Token.Tests/Nancy.Authentication.Token.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | ||
<PropertyGroup> | ||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||
<ProjectGuid>{3C131D45-AF1D-4659-8B26-A9F55EED0D20}</ProjectGuid> | ||
<OutputType>Library</OutputType> | ||
<AppDesignerFolder>Properties</AppDesignerFolder> | ||
<RootNamespace>Nancy.Authentication.Token.Tests</RootNamespace> | ||
<AssemblyName>Nancy.Authentication.Token.Tests</AssemblyName> | ||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> | ||
<FileAlignment>512</FileAlignment> | ||
<TargetFrameworkProfile /> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||
<DebugSymbols>true</DebugSymbols> | ||
<DebugType>full</DebugType> | ||
<Optimize>false</Optimize> | ||
<OutputPath>bin\Debug\</OutputPath> | ||
<DefineConstants>DEBUG;TRACE</DefineConstants> | ||
<ErrorReport>prompt</ErrorReport> | ||
<WarningLevel>4</WarningLevel> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||
<DebugType>pdbonly</DebugType> | ||
<Optimize>true</Optimize> | ||
<OutputPath>bin\Release\</OutputPath> | ||
<DefineConstants>TRACE</DefineConstants> | ||
<ErrorReport>prompt</ErrorReport> | ||
<WarningLevel>4</WarningLevel> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'MonoDebug|AnyCPU'"> | ||
<DebugSymbols>true</DebugSymbols> | ||
<OutputPath>bin\MonoDebug\</OutputPath> | ||
<DefineConstants>DEBUG;TRACE</DefineConstants> | ||
<DebugType>full</DebugType> | ||
<PlatformTarget>AnyCPU</PlatformTarget> | ||
<ErrorReport>prompt</ErrorReport> | ||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'MonoRelease|AnyCPU'"> | ||
<OutputPath>bin\MonoRelease\</OutputPath> | ||
<DefineConstants>TRACE</DefineConstants> | ||
<Optimize>true</Optimize> | ||
<DebugType>pdbonly</DebugType> | ||
<PlatformTarget>AnyCPU</PlatformTarget> | ||
<ErrorReport>prompt</ErrorReport> | ||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Reference Include="FakeItEasy, Version=1.14.0.0, Culture=neutral, PublicKeyToken=eff28e2146d5fd2c, processorArchitecture=MSIL"> | ||
<SpecificVersion>False</SpecificVersion> | ||
<HintPath>..\packages\FakeItEasy.1.14.0\lib\net40\FakeItEasy.dll</HintPath> | ||
</Reference> | ||
<Reference Include="System" /> | ||
<Reference Include="System.Core" /> | ||
<Reference Include="System.Xml.Linq" /> | ||
<Reference Include="System.Data.DataSetExtensions" /> | ||
<Reference Include="Microsoft.CSharp" /> | ||
<Reference Include="System.Data" /> | ||
<Reference Include="System.Xml" /> | ||
<Reference Include="xunit, Version=1.9.1.1600, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | ||
<SpecificVersion>False</SpecificVersion> | ||
<HintPath>..\packages\xunit.1.9.1\lib\net20\xunit.dll</HintPath> | ||
</Reference> | ||
<Reference Include="xunit.extensions, Version=1.9.1.1600, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | ||
<SpecificVersion>False</SpecificVersion> | ||
<HintPath>..\packages\xunit.extensions.1.9.1\lib\net20\xunit.extensions.dll</HintPath> | ||
</Reference> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Compile Include="..\Nancy.Tests\Fakes\FakeRequest.cs"> | ||
<Link>Fakes\FakeRequest.cs</Link> | ||
</Compile> | ||
<Compile Include="..\Nancy.Tests\ShouldExtensions.cs"> | ||
<Link>ShouldExtensions.cs</Link> | ||
</Compile> | ||
<Compile Include="..\SharedAssemblyInfo.cs"> | ||
<Link>Properties\SharedAssemblyInfo.cs</Link> | ||
</Compile> | ||
<Compile Include="Storage\FileSystemTokenKeyStoreFixture.cs" /> | ||
<Compile Include="TokenAuthenticationConfigurationFixture.cs" /> | ||
<Compile Include="TokenAuthenticationFixture.cs" /> | ||
<Compile Include="TokenizerFixture.cs" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<None Include="app.config" /> | ||
<None Include="packages.config" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\Nancy.Authentication.Token\Nancy.Authentication.Token.csproj"> | ||
<Project>{97fa024a-f6ed-4086-bcc1-1a51be63474c}</Project> | ||
<Name>Nancy.Authentication.Token</Name> | ||
</ProjectReference> | ||
<ProjectReference Include="..\Nancy.Testing\Nancy.Testing.csproj"> | ||
<Project>{D79203C0-B672-4751-9C95-C3AB7D3FEFBE}</Project> | ||
<Name>Nancy.Testing</Name> | ||
</ProjectReference> | ||
<ProjectReference Include="..\Nancy\Nancy.csproj"> | ||
<Project>{34576216-0dca-4b0f-a0dc-9075e75a676f}</Project> | ||
<Name>Nancy</Name> | ||
</ProjectReference> | ||
</ItemGroup> | ||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | ||
Other similar extension points exist, see Microsoft.Common.targets. | ||
<Target Name="BeforeBuild"> | ||
</Target> | ||
<Target Name="AfterBuild"> | ||
</Target> | ||
--> | ||
</Project> |
55 changes: 55 additions & 0 deletions
55
src/Nancy.Authentication.Token.Tests/Storage/FileSystemTokenKeyStoreFixture.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using System; | ||
|
||
namespace Nancy.Authentication.Token.Tests.Storage | ||
{ | ||
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 : IDisposable | ||
{ | ||
private FileSystemTokenKeyStore keyStore; | ||
|
||
public FileSystemTokenKeyStoreFixture() | ||
{ | ||
var rootPathProvider = new FakeRootPathProvider(); | ||
this.keyStore = new FileSystemTokenKeyStore(rootPathProvider); | ||
} | ||
|
||
[Fact] | ||
public void Should_store_keys_in_file() | ||
{ | ||
var keys = new Dictionary<DateTime, byte[]>(); | ||
|
||
keys.Add(DateTime.UtcNow, Encoding.UTF8.GetBytes("fake encryption key")); | ||
|
||
keyStore.Store(keys); | ||
|
||
Assert.True(File.Exists(keyStore.FilePath)); | ||
} | ||
|
||
[Fact] | ||
public void Should_retrieve_keys_from_file() | ||
{ | ||
var keys = new Dictionary<DateTime, byte[]>(); | ||
|
||
keys.Add(DateTime.UtcNow, Encoding.UTF8.GetBytes("fake encryption key")); | ||
|
||
keyStore.Store(keys); | ||
|
||
var retrievedKeys = keyStore.Retrieve(); | ||
|
||
Assert.True(Encoding.UTF8.GetString(retrievedKeys.Values.First()) | ||
== "fake encryption key"); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
keyStore.Purge(); | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/Nancy.Authentication.Token.Tests/TokenAuthenticationConfigurationFixture.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
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)); | ||
} | ||
} | ||
} |
166 changes: 166 additions & 0 deletions
166
src/Nancy.Authentication.Token.Tests/TokenAuthenticationFixture.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
namespace Nancy.Authentication.Token.Tests | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Threading; | ||
using FakeItEasy; | ||
|
||
using Nancy.Security; | ||
using Nancy.Tests; | ||
using Nancy.Bootstrapper; | ||
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<ITokenizer>()); | ||
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<IPipelines>(); | ||
|
||
// When | ||
TokenAuthentication.Enable(pipelines, this.config); | ||
|
||
// Then | ||
A.CallTo(() => pipelines.BeforeRequest.AddItemToStartOfPipeline(A<Func<NancyContext, Response>>.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<IPipelines>(), 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 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)).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<ITokenizer>(); | ||
var fakeUser = A.Fake<IUserIdentity>(); | ||
A.CallTo(() => tokenizer.Detokenize("mytoken", context)).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<string> values) | ||
{ | ||
var header = new Dictionary<string, IEnumerable<string>> | ||
{ | ||
{ 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(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that this PR has been merged, I realize there would be a benefit to adding a BrowserContextExtension in Nancy.Testing for TokenAuth. However, this would require Nancy.Testing taking a dependency on Nancy.Authentication.Token.
@grumpydev @thecodejunkie let me know if you have objections to Nancy.Testing taking this dependency. If not, I'll go ahead and implement the Extension and send in another PR.
--Jeff
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm not sure we would want that dependency, it would either have to handle loading it dynamically, or be a separate testing thing.
We've had similar issues with forms auth testing - not sure what the best solution is.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem. It's fairly trivial to just fake up my own extension method in my own code.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the
FileSystemTokenKeyStoreFixture
tests needs some love. They're somewhat brittle. Every now and then theShould_retrieve_keys_from_file
tests fail withThe issue is probably because the tests, in the fixture, share a keystore instance and the purging can get messed up.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just pushed an update to the tests - would be ace if you gave them a quick look as well =)
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does do that - unless you have statics there's no "state" issues between tests.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any thoughts on how you can revoke a token? The scenario is that an admin removes user from database, yet the token hasn't expired. If the token has an expiry of 24 hours, then there is window where the user could still access site.
I've tried setting up a registry where I record the token issue with the user, but I see only 1 token being recorded in the keyChain.bin file.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the great explanation - I hadn't grasped that key to the token generation was stored. Makes sense now.
I had also thought of the "blacklist" approach as well. Could very well be a simple list that is checked on each request like you suggest, and perhaps a purge on regular basis that compares to the active user list. In a sense it will dictated by what the security required by the business. Unfortunately, there are cases where you need to lock down access immediately. But I agree that those scenarios are best handled other mechanisms and this keeps the Token solution cleaner.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought regarding documentation - your explanation is really and maybe could included as "Further detail" link for a discussion of the mechanics.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, @dhrobbins
Done: https://github.com/NancyFx/Nancy/wiki/Token-Authentication#under-the-covers
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey guys, i have one question! What's about load balancing?
And why the generation-key can't be static stored in the web.config or something like that?
best regards
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello Jeff, i like your Security first way. But i think the problem is, that if you application ist so small, that you doesnt need any fail over mechanism, then you dont need to be afraid of any hacker atacks ;-) If you armed for brute force attack, then i could attack you by DDoS. Ok via DDoS i can't stealing any Data, but i can produce a lot of damage. However, what i mean ist: there are a lot of Security reasons, an the solution shuld solve more then only one Problem ;-)
The simplest and most usable load balancing scenario ist:
Load Balancer (balancing by round robin, not sticky sesstion!)
|
|-------- Web Server1 (KeyChain.bin with random generated keys: AAA..., BBB...)
|-------- Web Server2 (KeyChain.bin with random generated keys: CCC..., DDD...)
|-------- Web Server3 (KeyChain.bin with random generated keys: EEE..., FFF...)
With the existing solution, the keys will be generated on each webserver, and will be stored localy on each webserver. If you login on "Web Server1" and Load balancer forwards you on the next Request to "Web Server2" then you AuthTicket cannot be Decrypted, because of different Key, wich ist loaded from localy KeyChain.bin!!!
This solution is not realy Stateless, and this ist my beggest Problem! REST Full Services and JWT are designed to be stateless!
I've wrote a simple JWTTokenizer. It uses the john sheehans nice lightwight solution: https://github.com/johnsheehan/jwt . If someone have the same problem as me, here is my very simple Solution:
a simple JWTTokenizer with shared secret key stored in the Web.config
Injection and configuration
Only what you need is to inject this JWTTokenizer, instead of default Tokenizer within you Bootstrap class:
in the future
For the future i think it should be the combination of your existing solution an Shared_Secret_Key Solution. In the class TokenKeyRing within Tokenizer.cs you could implement something like:
your existing implementation of random Key generation
And then you could provide some different implementations of ISharedSecredKeyProvider. For Example your already existing implementation:
one of possible implementations
Or my favorite implementation would be this:
there are a lot of challanges like expiration an synchronisation of keys across multiple webservers. But i think it could be the possible way, why not!
sorry for my bad english!
best regards
Ilja
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd certainly like to see some way to invalidate a token. I don't see a way to do this without keeping a list of user/token(s) and then perhaps a blacklist for revoked but not expired tokens.
I'm leaning towards using the in memory keystore, so I guess the user/tokens & blacklist could be in memory too.. I guess that depends on how many users you expect to be logged in.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding invalidating the token, @jeffdoolittle mentioned that dropping the token on the client side essentially eliminates the token for that user. If you kept a black list of the new people to reject then you could redirect to a "Get lost" page that then purges the localStorage / cookie from the client.
Basically you would have to check the list for each transaction between the client and web server. If it's small enough you could just cache it. Clearly you would have to purge this list periodically, but you'd need to ensure that the client side token purge has occurred. On the bright side of things after the token expires, the "Get lost LUser" is locked out.
Another idea would be to create a claim of "Locked Out" and in the entry point of the Modules, test for that claim, redirect to "Get Lost" page, purge on the client, etc. This way you could just record the "Locked Claim" in the database / document and not have to maintain a list in memory, and purge the list. Simply mark the user as "Locked Out", then after the expiry period you can delete the user out of the system, and they won't have access anyway.
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello,
Exists a way to force re-login? Or force to expire a Token?
Thank you!
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thecodemonkey thanks, I encounter the load balancing issue too. #2279
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where are keyChain.bin? i can't find it on my computer
9ae0a54
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dhrobbins
Hey guys, Have you solved the problem of expiring keys immediately? Can you give a solution to the problem?