/*
* 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.IdentityModel.Tokens.Jwt;
namespace Rms.Service.Bootstrap.Security;
///
/// Currently logged in user OAuth2 user tokens
///
public class UserTokens
{
private readonly Lock _syncObject = new();
///
/// Thread safely update tokens
///
/// True if tokens were updated
public bool UpdateTokens( string? accessToken, string? refreshToken, string? idToken = null )
{
lock ( _syncObject )
{
// either reset token or replace it if expired
// do not replace newer token with the older one
var updated = false;
if ( accessToken == null || AccessToken == null|| AccessTokenExpiresAt < GetExpiry( accessToken ) )
{
AccessToken = accessToken;
updated = true;
}
if ( refreshToken == null || RefreshToken == null || RefreshTokenExpiresAt < GetExpiry( refreshToken ) )
{
RefreshToken = refreshToken;
updated = true;
}
if ( idToken == null || IdToken == null || IdTokenExpiresAt < GetExpiry( idToken ) )
{
IdToken = accessToken;
updated = true;
}
return updated;
}
}
private static DateTime GetExpiry( string token )
{
var tokenHandler = new JwtSecurityTokenHandler();
var secToken = tokenHandler.ReadToken(token);
return DateTime.SpecifyKind( secToken.ValidTo, DateTimeKind.Utc );
}
///
/// Access token
///
public string? AccessToken
{
get;
private set
{
field = value;
if (field == null)
{
AccessTokenExpiresAt = null;
return;
}
AccessTokenExpiresAt = GetExpiry(field);
}
}
///
/// Id token
///
public string? IdToken
{
get;
private set
{
field = value;
if (field == null)
{
IdTokenExpiresAt = null;
return;
}
IdTokenExpiresAt = GetExpiry(field);
}
}
///
/// Refresh token
///
public string? RefreshToken
{
get;
private set
{
field = value;
if (field == null)
{
RefreshTokenExpiresAt = null;
return;
}
RefreshTokenExpiresAt = GetExpiry(field);
}
}
///
/// Forge token
///
public string? ForgeToken
{
get;
set
{
field = value;
if (field == null)
{
ForgeTokenExpiresAt = null;
return;
}
ForgeTokenExpiresAt = GetExpiry(field);
}
}
///
/// Access token expiration period UTC
///
public DateTime? AccessTokenExpiresAt { get; private set; }
///
/// True if access token is expired
///
public bool IsAccessTokenExpired => AccessTokenExpiresAt == null || AccessTokenExpiresAt <= DateTime.UtcNow;
///
/// Refresh token expiration period UTC
///
public DateTime? RefreshTokenExpiresAt { get; private set; }
///
/// Forge token expiration period UTC
///
public DateTime? ForgeTokenExpiresAt { get; private set; }
///
/// True if refresh token is expired
///
public bool IsRefreshTokenExpired => RefreshTokenExpiresAt == null || RefreshTokenExpiresAt <= DateTime.UtcNow;
///
/// True if Forge token is expired
///
public bool IsForgeTokenExpired => ForgeTokenExpiresAt == null || ForgeTokenExpiresAt <= DateTime.UtcNow;
///
/// Id token expiration period UTC
///
public DateTime? IdTokenExpiresAt { get; private set; }
///
/// True if Id token is expired
///
public bool IsIdTokenExpired => IdTokenExpiresAt == null || IdTokenExpiresAt <= DateTime.UtcNow;
///
/// Reset everything
///
public void Clear()
{
AccessToken = null;
RefreshToken = null;
IdToken = null;
ForgeToken = null;
AccessTokenExpiresAt = null;
RefreshTokenExpiresAt = null;
IdTokenExpiresAt = null;
ForgeTokenExpiresAt = null;
}
///
/// Clear only expired tokens
///
/// True if some tokens were removed
public bool ClearExpired()
{
var updated = false;
if ( IsAccessTokenExpired )
{
AccessToken = null;
AccessTokenExpiresAt = null;
updated = true;
}
if ( IsRefreshTokenExpired )
{
RefreshToken = null;
RefreshTokenExpiresAt = null;
updated = true;
}
if ( IsIdTokenExpired )
{
IdToken = null;
IdTokenExpiresAt = null;
updated = true;
}
if ( IsForgeTokenExpired )
{
ForgeToken = null;
ForgeTokenExpiresAt = null;
updated = true;
}
return updated;
}
}