/* * dbMango * * Copyright 2025 Deutsche Bank AG * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Collections.Concurrent; using System.Security.Claims; namespace Rms.Service.Bootstrap.Security; /// /// Server-side authentication storage. /// See https://stackoverflow.com/questions/72868249/how-to-handle-user-oidc-tokens-in-blazor-server-when-the-browser-is-refreshed-an /// public interface IServerSideTokenStore { /// /// Remove all tokens /// Task ClearTokensAsync(ClaimsPrincipal principal); /// /// Get tokens by user claim "sub" (i.e. subject) /// Task GetTokensAsync(ClaimsPrincipal principal); /// /// Store user tokens by user claim "sub" (i.e. subject) /// Task StoreTokensAsync(ClaimsPrincipal principal, UserTokens userTokens); /// /// Extract user ID (normally email) from user claims. /// /// /// string? GetId(ClaimsPrincipal principal); } internal class ServerSideTokenStore : IServerSideTokenStore { private readonly ConcurrentDictionary _userTokenProviders = new(); public Task ClearTokensAsync(ClaimsPrincipal principal) { var userSub = GetId(principal); if (userSub == null) return Task.CompletedTask; _userTokenProviders.TryRemove(userSub, out _); return Task.CompletedTask; } public Task GetTokensAsync(ClaimsPrincipal principal) { var userSub = GetId(principal); if (userSub == null) return Task.FromResult((UserTokens?)null); _userTokenProviders.TryGetValue(userSub, out var value); return Task.FromResult(value); } public Task StoreTokensAsync(ClaimsPrincipal principal, UserTokens userTokens) { var userSub = GetId(principal); if (userSub == null) return Task.CompletedTask; _userTokenProviders[userSub] = userTokens; return Task.CompletedTask; } private static string? Get(ClaimsPrincipal principal, string claimType) => principal.Identities .SelectMany(x => x.Claims) .FirstOrDefault(x => x.Type == claimType && !string.IsNullOrWhiteSpace(x.Value)) ?.Value; public string? GetId(ClaimsPrincipal principal) => Get(principal, ClaimTypes.Email) ?? Get(principal, "email") ?? Get(principal, ClaimTypes.NameIdentifier) ?? Get(principal, ClaimTypes.Name) ?? Get(principal, "usersub") ; }