-
Notifications
You must be signed in to change notification settings - Fork 159
/
PeriodicCookieEvent.cs
60 lines (52 loc) · 2.58 KB
/
PeriodicCookieEvent.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Copyright (c) 2022 Jon P Smith, GitHub: JonPSmith, web: http://www.thereformedprogrammer.net/
// Licensed under MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using AuthPermissions;
using AuthPermissions.BaseCode.CommonCode;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.DependencyInjection;
namespace ExamplesCommonCode.IdentityCookieCode;
/// <summary>
/// This contains a method that will periodically refresh the claims of each logged-in user
/// </summary>
public static class PeriodicCookieEvent
{
/// <summary>
/// Used in the "periodically update user's claims" feature
/// </summary>
public const string TimeToRefreshUserClaimType = "TimeToRefreshUserClaim";
/// <summary>
/// This method will be called on every HTTP request where a user is logged in (therefore you should keep the No change code quick)
/// This method implements a way to update user's claims defined by a claim with the Type
/// <see cref="TimeToRefreshUserClaimType"/>, which contains the time by which the refresh should occur.
/// </summary>
/// <param name="context"></param>
public static async Task PeriodicRefreshUsersClaims(CookieValidatePrincipalContext context)
{
var originalClaims = context.Principal.Claims.ToList();
if (originalClaims.GetClaimDateTimeTicksValue(TimeToRefreshUserClaimType) < DateTime.UtcNow)
{
//Need to refresh the user's claims
var userId = originalClaims.GetUserIdFromClaims();
if (userId == null)
//this shouldn't happen, but best to return
return;
var claimsCalculator = context.HttpContext.RequestServices.GetRequiredService<IClaimsCalculator>();
var newClaims = await claimsCalculator.GetClaimsForAuthUserAsync(userId);
newClaims.AddRange(originalClaims.RemoveUpdatedClaimsFromOriginalClaims(newClaims)); //Copy over unchanged claims
var identity = new ClaimsIdentity(newClaims, "Cookie");
var newPrincipal = new ClaimsPrincipal(identity);
context.ReplacePrincipal(newPrincipal);
context.ShouldRenew = true;
}
}
private static IEnumerable<Claim> RemoveUpdatedClaimsFromOriginalClaims(this List<Claim> originalClaims, List<Claim> newClaims)
{
var newClaimTypes = newClaims.Select(x => x.Type);
return originalClaims.Where(x => !newClaimTypes.Contains(x.Type));
}
}