Esempio n. 1
0
        /// <summary>
        ///     Converts a set of JWTs into a Keycloak identity
        /// If the access token of the identity is about to expire the identity gets refreshed
        /// If a <see cref="SecurityTokenExpiredException"/> is thrown  when converting the set of jwts, the identity
        /// gets refreshed.
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="accessToken"></param>
        /// <param name="refreshToken"></param>
        /// <param name="idToken"></param>
        /// <returns>The identity is returned</returns>
        public static async Task <KeycloakIdentity> ConvertFromJwtAsync(IKeycloakParameters parameters,
                                                                        string accessToken, string refreshToken = null, string idToken = null)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }
            if (accessToken == null)
            {
                throw new ArgumentNullException(nameof(accessToken));
            }

            var kcIdentity = new KeycloakIdentity(parameters);

            try
            {
                await kcIdentity.CopyFromJwt(accessToken, refreshToken, idToken);

                //check if identity is about to expire in 30 secs (default). If yes refresh identity!
                DateTime?accessValidTo =
                    DateTimeExtension.ParseClaimsDateToFormat(
                        kcIdentity.Claims?.FirstOrDefault(c => c.Type == Constants.ClaimTypes.AccessTokenExpiration)?
                        .Value);
                DateTime?refreshValidTo =
                    DateTimeExtension.ParseClaimsDateToFormat(
                        kcIdentity.Claims?.FirstOrDefault(c => c.Type == Constants.ClaimTypes.RefreshTokenExpiration)?
                        .Value);
                var utcNow = DateTime.UtcNow;
                //_logger.Debug($"access {accessValidToX?.ToUniversalTime()} " +
                //              $"utcnow {utcNow} refresh {refreshValidToX?.ToUniversalTime()}.");

                if (utcNow >= accessValidTo?.Subtract(parameters.RefreshBeforeTokenExpiration).ToUniversalTime() &&
                    utcNow <= refreshValidTo?.Subtract(parameters.RefreshBeforeTokenExpiration).ToUniversalTime())
                {
                    _logger.Debug(
                        $"{kcIdentity.Name} access token will expire in less then {parameters.RefreshBeforeTokenExpiration} seconds. Refresh identity.");
                    await kcIdentity.RefreshIdentity(refreshToken);
                }
            }
            catch (SecurityTokenExpiredException)
            {
                _logger.Debug($"SecurityTokenExpiredException was thrown.Refreshing identity with refresh token");
                // Load new identity from token endpoint via refresh token (if possible)
                await kcIdentity.RefreshIdentity(refreshToken);
            }
            catch (ArgumentOutOfRangeException)
            {
                _logger.Debug($"ArgumentOutOfRangeException was thrown when calculating acces token expiration timeframe. No refreshing of identity. User is out of luck.");
            }

            return(kcIdentity);
        }