Example #1
0
        public SecurityToken ValidateToken(string jwt, IKeycloakParameters options, OidcDataManager uriManager, bool isRefreshToken = false)
        {
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateLifetime         = true,
                RequireExpirationTime    = true,
                ValidateIssuer           = !options.DisableIssuerValidation,
                ValidateAudience         = !options.DisableAudienceValidation,
                ValidateIssuerSigningKey = !options.DisableTokenSignatureValidation,
                RequireSignedTokens      = !options.AllowUnsignedTokens,
                ValidIssuer    = uriManager.GetIssuer(),
                ClockSkew      = options.TokenClockSkew,
                ValidAudiences = new List <string> {
                    "null", options.ClientId
                },
                IssuerSigningKeys  = uriManager.GetJsonWebKeys().GetSigningKeys(),
                AuthenticationType = options.AuthenticationType // Not used
            };
            bool disableAllValidation = isRefreshToken && options.DisableAllRefreshTokenValidation;

            if (disableAllValidation)
            {
                return(ReadJwtToken(jwt));
            }

            bool disableOnlySignatureValidation = isRefreshToken && options.DisableRefreshTokenSignatureValidation;

            return(ValidateToken(jwt, tokenValidationParameters, disableOnlySignatureValidation));
        }
Example #2
0
        /// <summary>
        ///     Validates an IKeycloakParameters object for completeness and correctness
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static void ValidateParameters(IKeycloakParameters parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            // Verify required parameters
            if (parameters.KeycloakUrl == null)
            {
                throw new ArgumentNullException(nameof(parameters.KeycloakUrl));
            }
            if (parameters.Realm == null)
            {
                throw new ArgumentNullException(nameof(parameters.Realm));
            }

            // Set default parameters
            if (string.IsNullOrWhiteSpace(parameters.ResponseType))
            {
                throw new ArgumentNullException(nameof(parameters.ResponseType));
            }
            if (string.IsNullOrWhiteSpace(parameters.Scope))
            {
                throw new ArgumentNullException(nameof(parameters.Scope));
            }
            if (string.IsNullOrWhiteSpace(parameters.CallbackPath))
            {
                throw new ArgumentNullException(nameof(parameters.CallbackPath));
            }

            // Validate other parameters
            if (!Uri.IsWellFormedUriString(parameters.KeycloakUrl, UriKind.Absolute))
            {
                throw new ArgumentException(nameof(parameters.KeycloakUrl));
            }
            if (!Uri.IsWellFormedUriString(parameters.CallbackPath, UriKind.Relative) &&
                parameters.CallbackPath != Constants.KeycloakParameters.NoCallbackUri)
            {
                throw new ArgumentException(nameof(parameters.CallbackPath));
            }
            if (parameters.PostLogoutRedirectUrl != null &&
                !Uri.IsWellFormedUriString(parameters.PostLogoutRedirectUrl, UriKind.RelativeOrAbsolute))
            {
                throw new ArgumentException(nameof(parameters.PostLogoutRedirectUrl));
            }
            var logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

            // Attempt to refresh OIDC metadata from endpoint (on separate thread)
            try
            {
                Task.Run(() => OidcDataManager.GetCachedContextAsync(parameters)).Wait();
            }
            catch (Exception exception)
            {
                logger.Error($"Invalid Keycloak server parameters specified: See inner for server error: {exception.InnerException}");
                throw new ArgumentException("Invalid Keycloak server parameters specified: See inner for server error",
                                            exception);
            }
        }
Example #3
0
        /// <summary>
        ///     Converts a set of JWTs into a Keycloak identity
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="accessToken"></param>
        /// <param name="refreshToken"></param>
        /// <param name="idToken"></param>
        /// <returns></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);
            }
            catch (SecurityTokenExpiredException)
            {
                // Load new identity from token endpoint via refresh token (if possible)
                await kcIdentity.RefreshIdentity(refreshToken);
            }
            return(kcIdentity);
        }
Example #4
0
        /// <summary>
        ///     Generates the OpenID Connect compliant Keycloak logout URL
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="baseUri"></param>
        /// <param name="redirectUri"></param>
        /// <returns></returns>
        public static async Task <Uri> GenerateLogoutUriAsync(IKeycloakParameters parameters, Uri baseUri,
                                                              Uri redirectUri)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }
            if (baseUri == null)
            {
                throw new ArgumentNullException(nameof(baseUri));
            }
            if (redirectUri == null)
            {
                throw new ArgumentNullException(nameof(redirectUri));
            }

            // Generate logout URI and data
            var uriManager = await OidcDataManager.GetCachedContextAsync(parameters);

            var logoutParams = uriManager.BuildEndSessionEndpointContent(baseUri, null, redirectUri.ToString());
            var logoutUrl    = uriManager.GetEndSessionEndpoint();

            // Return logout URI
            var logoutQueryString = await logoutParams.ReadAsStringAsync();

            return(new Uri(logoutUrl + (!string.IsNullOrEmpty(logoutQueryString) ? "?" + logoutQueryString : "")));
        }
Example #5
0
        /// <summary>
        /// Perform logout of the User entity with the specified <param name="refreshToken"></param>
        /// </summary>
        /// <param name="refreshToken">Claims refresh token</param>
        /// <param name="options"></param>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static async Task <string> HttpLogoutPost(string refreshToken, IKeycloakParameters options, Uri uri)
        {
            var           logger      = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            var           httpClient  = new HttpClient();
            StringContent authContent = new StringContent("refresh_token=" + refreshToken, Encoding.UTF8, "application/x-www-form-urlencoded");

            httpClient.DefaultRequestHeaders.Remove("Authorization");
            httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " +
                                                 Convert.ToBase64String(
                                                     Encoding.UTF8.GetBytes(
                                                         $"{options.ClientId}:{options.ClientSecret}")));


            logger.Debug($"HttpLogoutPost options.ClientId {options.ClientId} to uri {uri}");
            var response = await httpClient.PostAsync(uri, authContent);

            // Fail on unreachable destination
            if (!response.IsSuccessStatusCode)
            {
                logger.Error($"HttpLogoutPost Logging out user: HTTP address unreachable ('{uri}')");
                throw new Exception(
                          $"Logging out user: HTTP address unreachable ('{uri}')");
            }

            httpClient.Dispose();

            logger.Debug("HttpLogoutPost success.disposed client.");
            return(await response.Content.ReadAsStringAsync());
        }
        protected GenericMessage(IKeycloakParameters options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            Options = options;
        }
        protected OidcDataManager(IKeycloakParameters options)
        {
            _options = options;
            _nextCachedRefreshTime = DateTime.Now;

            Authority               = _options.KeycloakUrl + "/realms/" + _options.Realm;
            MetadataEndpoint        = new Uri(Authority + "/" + OpenIdProviderMetadataNames.Discovery);
            TokenValidationEndpoint = new Uri(Authority + "/tokens/validate");
        }
        protected OidcDataManager(IKeycloakParameters options)
        {
            _options = options;
            _nextCachedRefreshTime = DateTime.Now;

            Authority = _options.KeycloakUrl + "/realms/" + _options.Realm;
            MetadataEndpoint = new Uri(Authority + "/" + OpenIdProviderMetadataNames.Discovery);
            TokenValidationEndpoint = new Uri(Authority + "/tokens/validate");
        }
 public RefreshAccessTokenMessage(IKeycloakParameters options, string refreshToken)
     : base(options)
 {
     if (refreshToken == null)
     {
         throw new ArgumentNullException();
     }
     RefreshToken = refreshToken;
 }
Example #10
0
 /// <summary>
 ///     Load a new Keycloak-based identity from a claims identity
 /// </summary>
 /// <param name="parameters"></param>
 protected KeycloakIdentity(IKeycloakParameters parameters)
 {
     if (parameters == null)
     {
         throw new ArgumentNullException(nameof(parameters));
     }
     ValidateParameters(parameters);
     _parameters = parameters;
 }
Example #11
0
        protected OidcDataManager(IOwinContext context, IKeycloakParameters options)
        {
            _options = options;
            _nextCachedRefreshTime = DateTime.Now;

            var realm = MultiTenantRealmSelector != null?MultiTenantRealmSelector(context) : options.Realm;

            Authority               = _options.KeycloakUrl + "/realms/" + realm;
            MetadataEndpoint        = new Uri(Authority + "/" + OpenIdProviderMetadataNames.Discovery);
            TokenValidationEndpoint = new Uri(Authority + "/tokens/validate");
        }
 /// <summary>
 ///     Converts a JWT token-response endpoint message into a Keycloak identity
 /// </summary>
 /// <param name="parameters"></param>
 /// <param name="message"></param>
 /// <returns></returns>
 public static Task <KeycloakIdentity> ConvertFromTokenResponseAsync(IKeycloakParameters parameters, TokenResponse message)
 {
     if (parameters == null)
     {
         throw new ArgumentNullException(nameof(parameters));
     }
     if (message == null)
     {
         throw new ArgumentNullException(nameof(message));
     }
     return(ConvertFromJwtAsync(parameters, message.AccessToken, message.RefreshToken, message.IdToken));
 }
 /// <summary>
 ///     Converts a keycloak-generated claims identity into a Keycloak identity
 /// </summary>
 /// <param name="parameters"></param>
 /// <param name="identity"></param>
 /// <returns></returns>
 public static Task <KeycloakIdentity> ConvertFromClaimsIdentityAsync(IKeycloakParameters parameters, ClaimsIdentity identity)
 {
     if (parameters == null)
     {
         throw new ArgumentNullException(nameof(parameters));
     }
     if (identity == null)
     {
         throw new ArgumentNullException(nameof(identity));
     }
     return(ConvertFromClaimsAsync(parameters, identity.Claims));
 }
Example #14
0
 /// <summary>
 ///     Trys to validate an IKeycloakParameters object for completeness and correctness
 /// </summary>
 /// <param name="parameters"></param>
 /// <returns></returns>
 public static bool TryValidateParameters(IKeycloakParameters parameters)
 {
     try
     {
         ValidateParameters(parameters);
         return(true);
     }
     catch (Exception)
     {
         return(false);
     }
 }
        public static async Task <OidcDataManager> CreateCachedContext(IKeycloakParameters options,
                                                                       bool preload = true)
        {
            var newContext = new OidcDataManager(options);

            OidcManagerCache[options.AuthenticationType + CachedContextPostfix] = newContext;
            if (preload)
            {
                await newContext.ValidateCachedContextAsync();
            }
            return(newContext);
        }
Example #16
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);
        }
Example #17
0
        /// <summary>
        ///     Generates the local URL on which to accept OIDC callbacks from Keycloak
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="baseUri"></param>
        /// <returns></returns>
        public static async Task <Uri> GenerateLoginCallbackUriAsync(IKeycloakParameters parameters, Uri baseUri)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }
            if (baseUri == null)
            {
                throw new ArgumentNullException(nameof(baseUri));
            }

            return((await OidcDataManager.GetCachedContextAsync(parameters)).GetCallbackUri(baseUri));
        }
 public bool TryValidateToken(string jwt, IKeycloakParameters options, OidcDataManager uriManager, out SecurityToken rToken)
 {
     try
     {
         rToken = ValidateToken(jwt, options, uriManager);
         return true;
     }
     catch (Exception)
     {
         rToken = null;
         return false;
     }
 }
Example #19
0
 public bool TryValidateToken(string jwt, IKeycloakParameters options, OidcDataManager uriManager, out SecurityToken rToken, bool isRefreshToken = false)
 {
     try
     {
         rToken = ValidateToken(jwt, options, uriManager, isRefreshToken);
         return(true);
     }
     catch (Exception)
     {
         rToken = null;
         return(false);
     }
 }
Example #20
0
        public RequestAccessTokenMessage(Uri baseUri, IKeycloakParameters options,
                                         AuthorizationResponse authResponse)
            : base(options)
        {
            if (baseUri == null)
            {
                throw new ArgumentNullException(nameof(baseUri));
            }
            if (authResponse == null)
            {
                throw new ArgumentNullException(nameof(authResponse));
            }

            BaseUri      = baseUri;
            AuthResponse = authResponse;
        }
        /// <summary>
        ///     Validates an IKeycloakParameters object for completeness and correctness
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static void ValidateParameters(IKeycloakParameters parameters)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            // Verify required parameters
            if (parameters.KeycloakUrl == null)
            {
                throw new ArgumentNullException(nameof(parameters.KeycloakUrl));
            }
            if (parameters.Realm == null && parameters.MultiTenantRealmSelector == null)
            {
                throw new ArgumentNullException(nameof(parameters.Realm));
            }

            // Set default parameters
            if (string.IsNullOrWhiteSpace(parameters.ResponseType))
            {
                throw new ArgumentNullException(nameof(parameters.ResponseType));
            }
            if (string.IsNullOrWhiteSpace(parameters.Scope))
            {
                throw new ArgumentNullException(nameof(parameters.Scope));
            }
            if (string.IsNullOrWhiteSpace(parameters.CallbackPath))
            {
                throw new ArgumentNullException(nameof(parameters.CallbackPath));
            }

            // Validate other parameters
            if (!Uri.IsWellFormedUriString(parameters.KeycloakUrl, UriKind.Absolute))
            {
                throw new ArgumentException(nameof(parameters.KeycloakUrl));
            }
            if (!Uri.IsWellFormedUriString(parameters.CallbackPath, UriKind.Relative) &&
                parameters.CallbackPath != Constants.KeycloakParameters.NoCallbackUri)
            {
                throw new ArgumentException(nameof(parameters.CallbackPath));
            }
            if (parameters.PostLogoutRedirectUrl != null &&
                !Uri.IsWellFormedUriString(parameters.PostLogoutRedirectUrl, UriKind.RelativeOrAbsolute))
            {
                throw new ArgumentException(nameof(parameters.PostLogoutRedirectUrl));
            }
        }
        /// <summary>
        ///     Converts a keycloak-generated claims list into a Keycloak identity
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="claims"></param>
        /// <returns></returns>
        public static Task <KeycloakIdentity> ConvertFromClaimsAsync(IKeycloakParameters parameters, IEnumerable <Claim> claims)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }
            if (claims == null)
            {
                throw new ArgumentNullException(nameof(claims));
            }

            var claimLookup  = claims.ToLookup(c => c.Type, c => c.Value);
            var idToken      = claimLookup[Constants.ClaimTypes.IdToken].FirstOrDefault();
            var accessToken  = claimLookup[Constants.ClaimTypes.AccessToken].FirstOrDefault();
            var refreshToken = claimLookup[Constants.ClaimTypes.RefreshToken].FirstOrDefault();

            return(ConvertFromJwtAsync(parameters, accessToken, refreshToken, idToken));
        }
        public SecurityToken ValidateToken(string jwt, IKeycloakParameters options, OidcDataManager uriManager)
        {
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateLifetime = true,
                RequireExpirationTime = true,
                ValidateIssuer = !options.DisableIssuerValidation,
                ValidateAudience = !options.DisableAudienceValidation,
                ValidateIssuerSigningKey = !options.DisableTokenSignatureValidation,
                RequireSignedTokens = !options.AllowUnsignedTokens,
                ValidIssuer = uriManager.GetIssuer(),
                ClockSkew = options.TokenClockSkew,
                ValidAudiences = new List<string> {"null", options.ClientId},
                IssuerSigningTokens = uriManager.GetJsonWebKeys().GetSigningTokens(),
                AuthenticationType = options.AuthenticationType // Not used
            };

            return ValidateToken(jwt, tokenValidationParameters);
        }
Example #24
0
        public SecurityToken ValidateToken(string jwt, IKeycloakParameters options, OidcDataManager uriManager)
        {
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateLifetime         = true,
                RequireExpirationTime    = true,
                ValidateIssuer           = !options.DisableIssuerValidation,
                ValidateAudience         = !options.DisableAudienceValidation,
                ValidateIssuerSigningKey = !options.DisableTokenSignatureValidation,
                RequireSignedTokens      = !options.AllowUnsignedTokens,
                ValidIssuer    = uriManager.GetIssuer(),
                ClockSkew      = options.TokenClockSkew,
                ValidAudiences = new List <string> {
                    "null", options.ClientId
                },
                IssuerSigningKeys = uriManager.GetJsonWebKeys().GetSigningKeys(),
            };

            return(ValidateToken(jwt, tokenValidationParameters));
        }
        /// <summary>
        ///     Converts a JWT token-response endpoint message into a Keycloak identity
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="response"></param>
        /// <param name="baseUri"></param>
        /// <returns></returns>
        public static async Task <KeycloakIdentity> ConvertFromAuthResponseAsync(IKeycloakParameters parameters, AuthorizationResponse response, Uri baseUri)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }
            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }
            if (baseUri == null)
            {
                throw new ArgumentNullException(nameof(baseUri));
            }

            response.ThrowIfError();
            var message = new RequestAccessTokenMessage(baseUri, parameters, response);

            return(await ConvertFromTokenResponseAsync(parameters, await message.ExecuteAsync()));
        }
        /// <summary>
        ///     Generates the OpenID Connect compliant Keycloak login URL
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="baseUri"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public static async Task <Uri> GenerateLoginUriAsync(IKeycloakParameters parameters, Uri baseUri, string state = null)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }
            if (baseUri == null)
            {
                throw new ArgumentNullException(nameof(baseUri));
            }

            // Generate login URI and data
            var uriManager = await OidcDataManager.GetCachedContextAsync(parameters);

            var loginParams = uriManager.BuildAuthorizationEndpointContent(baseUri, state ?? Guid.NewGuid().ToString());
            var loginUrl    = uriManager.GetAuthorizationEndpoint();

            // Return login URI
            var loginQueryString = await loginParams.ReadAsStringAsync();

            return(new Uri(loginUrl + (!string.IsNullOrEmpty(loginQueryString) ? "?" + loginQueryString : "")));
        }
 public static async Task<OidcDataManager> CreateCachedContext(IKeycloakParameters options,
     bool preload = true)
 {
     var newContext = new OidcDataManager(options);
     OidcManagerCache[options.AuthenticationType + CachedContextPostfix] = newContext;
     if (preload) await newContext.ValidateCachedContextAsync();
     return newContext;
 }
        /// <summary>
        ///     Converts a JWT token-response endpoint message into a Keycloak identity
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="response"></param>
        /// <param name="baseUri"></param>
        /// <returns></returns>
        public static async Task<KeycloakIdentity> ConvertFromAuthResponseAsync(IKeycloakParameters parameters,
            AuthorizationResponse response, Uri baseUri)
        {
            if (parameters == null) throw new ArgumentNullException(nameof(parameters));
            if (response == null) throw new ArgumentNullException(nameof(response));
            if (baseUri == null) throw new ArgumentNullException(nameof(baseUri));

            response.ThrowIfError();
            var message = new RequestAccessTokenMessage(baseUri, parameters, response);
            return await ConvertFromTokenResponseAsync(parameters, await message.ExecuteAsync());
        }
 public static OidcDataManager GetCachedContext(IKeycloakParameters options)
 {
     return(GetCachedContext(options.AuthenticationType));
 }
        /// <summary>
        ///     Converts a set of JWTs into a Keycloak identity
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="accessToken"></param>
        /// <param name="refreshToken"></param>
        /// <param name="idToken"></param>
        /// <returns></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);
            }
            catch (SecurityTokenExpiredException)
            {
                // Load new identity from token endpoint via refresh token (if possible)
                await kcIdentity.RefreshIdentity(refreshToken);
            }
            return kcIdentity;
        }
 public async Task<SecurityToken> ValidateTokenAsync(string jwt, IKeycloakParameters options)
 {
     var uriManager = await OidcDataManager.GetCachedContextAsync(options);
     return ValidateToken(jwt, options, uriManager);
 }
        public static Task ValidateCachedContextAsync(IKeycloakParameters options)
        {
            var context = GetCachedContext(options.AuthenticationType);

            return(context.ValidateCachedContextAsync());
        }
 public static Task<OidcDataManager> GetCachedContextAsync(IKeycloakParameters options)
 {
     var context = GetCachedContextSafe(options.AuthenticationType);
     return context != null ? Task.FromResult(context) : CreateCachedContext(options);
 }
        /// <summary>
        ///     Converts a keycloak-generated claims list into a Keycloak identity
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="claims"></param>
        /// <returns></returns>
        public static Task<KeycloakIdentity> ConvertFromClaimsAsync(IKeycloakParameters parameters,
            IEnumerable<Claim> claims)
        {
            if (parameters == null) throw new ArgumentNullException(nameof(parameters));
            if (claims == null) throw new ArgumentNullException(nameof(claims));

            var claimLookup = claims.ToLookup(c => c.Type, c => c.Value);
            var idToken = claimLookup[Constants.ClaimTypes.IdToken].FirstOrDefault();
            var accessToken = claimLookup[Constants.ClaimTypes.AccessToken].FirstOrDefault();
            var refreshToken = claimLookup[Constants.ClaimTypes.RefreshToken].FirstOrDefault();

            return ConvertFromJwtAsync(parameters, accessToken, refreshToken, idToken);
        }
 /// <summary>
 ///     Converts a keycloak-generated claims identity into a Keycloak identity
 /// </summary>
 /// <param name="parameters"></param>
 /// <param name="identity"></param>
 /// <returns></returns>
 public static Task<KeycloakIdentity> ConvertFromClaimsIdentityAsync(IKeycloakParameters parameters,
     ClaimsIdentity identity)
 {
     if (parameters == null) throw new ArgumentNullException(nameof(parameters));
     if (identity == null) throw new ArgumentNullException(nameof(identity));
     return ConvertFromClaimsAsync(parameters, identity.Claims);
 }
 public static Task ValidateCachedContextAsync(IKeycloakParameters options)
 {
     var context = GetCachedContext(options.AuthenticationType);
     return context.ValidateCachedContextAsync();
 }
Example #37
0
 public static Task ValidateCachedContextAsync(IOwinContext context, IKeycloakParameters options)
 {
     return(GetCachedContext(context, options.AuthenticationType)
            .ValidateCachedContextAsync());
 }
Example #38
0
        public static async Task <SecurityToken> ValidateTokenRemote(string jwt, IKeycloakParameters options)
        {
            var uriManager = await OidcDataManager.GetCachedContextAsync(options);

            return(await ValidateTokenRemote(jwt, uriManager));
        }
        /// <summary>
        ///     Generates the local URL on which to accept OIDC callbacks from Keycloak
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="baseUri"></param>
        /// <returns></returns>
        public static async Task<Uri> GenerateLoginCallbackUriAsync(IKeycloakParameters parameters, Uri baseUri)
        {
            if (parameters == null) throw new ArgumentNullException(nameof(parameters));
            if (baseUri == null) throw new ArgumentNullException(nameof(baseUri));

            return (await OidcDataManager.GetCachedContextAsync(parameters)).GetCallbackUri(baseUri);
        }
        /// <summary>
        ///     Generates the OpenID Connect compliant Keycloak logout URL
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="baseUri"></param>
        /// <param name="redirectUrl"></param>
        /// <returns></returns>
        public static async Task<Uri> GenerateLogoutUriAsync(IKeycloakParameters parameters, Uri baseUri,
            string redirectUrl = null)
        {
            if (parameters == null) throw new ArgumentNullException(nameof(parameters));
            if (baseUri == null) throw new ArgumentNullException(nameof(baseUri));

            // Generate logout URI and data
            var uriManager = await OidcDataManager.GetCachedContextAsync(parameters);
            var logoutParams = uriManager.BuildEndSessionEndpointContent(baseUri, null, redirectUrl);
            var logoutUrl = uriManager.GetEndSessionEndpoint();

            // Return logout URI
            var logoutQueryString = await logoutParams.ReadAsStringAsync();
            return new Uri(logoutUrl + (!string.IsNullOrEmpty(logoutQueryString) ? "?" + logoutQueryString : ""));
        }
 /// <summary>
 ///     Load a new Keycloak-based identity from a claims identity
 /// </summary>
 /// <param name="parameters"></param>
 protected KeycloakIdentity(IKeycloakParameters parameters)
 {
     if (parameters == null) throw new ArgumentNullException(nameof(parameters));
     ValidateParameters(parameters);
     _parameters = parameters;
 }
 public static OidcDataManager GetCachedContext(IKeycloakParameters options)
 {
     return GetCachedContext(options.AuthenticationType);
 }
        public static Task <OidcDataManager> GetCachedContextAsync(IKeycloakParameters options)
        {
            var context = GetCachedContextSafe(options.AuthenticationType);

            return(context != null?Task.FromResult(context) : CreateCachedContext(options));
        }
 /// <summary>
 ///     Converts a JWT token-response endpoint message into a Keycloak identity
 /// </summary>
 /// <param name="parameters"></param>
 /// <param name="message"></param>
 /// <returns></returns>
 public static Task<KeycloakIdentity> ConvertFromTokenResponseAsync(IKeycloakParameters parameters,
     TokenResponse message)
 {
     if (parameters == null) throw new ArgumentNullException(nameof(parameters));
     if (message == null) throw new ArgumentNullException(nameof(message));
     return ConvertFromJwtAsync(parameters, message.AccessToken, message.RefreshToken, message.IdToken);
 }
        /// <summary>
        ///     Generates the OpenID Connect compliant Keycloak login URL
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="baseUri"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public static async Task<Uri> GenerateLoginUriAsync(IKeycloakParameters parameters, Uri baseUri,
            string state = null)
        {
            if (parameters == null) throw new ArgumentNullException(nameof(parameters));
            if (baseUri == null) throw new ArgumentNullException(nameof(baseUri));

            // Generate login URI and data
            var uriManager = await OidcDataManager.GetCachedContextAsync(parameters);
            var loginParams = uriManager.BuildAuthorizationEndpointContent(baseUri, state ?? Guid.NewGuid().ToString());
            var loginUrl = uriManager.GetAuthorizationEndpoint();

            // Return login URI
            var loginQueryString = await loginParams.ReadAsStringAsync();
            return new Uri(loginUrl + (!string.IsNullOrEmpty(loginQueryString) ? "?" + loginQueryString : ""));
        }
        public async Task <SecurityToken> ValidateTokenAsync(IOwinContext context, string jwt, IKeycloakParameters options)
        {
            var uriManager = await OidcDataManager.GetCachedContextAsync(context, options);

            return(ValidateToken(jwt, options, uriManager));
        }
 /// <summary>
 ///     Trys to validate an IKeycloakParameters object for completeness and correctness
 /// </summary>
 /// <param name="parameters"></param>
 /// <returns></returns>
 public static bool TryValidateParameters(IKeycloakParameters parameters)
 {
     try
     {
         ValidateParameters(parameters);
         return true;
     }
     catch (Exception)
     {
         return false;
     }
 }
        /// <summary>
        ///     Validates an IKeycloakParameters object for completeness and correctness
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static void ValidateParameters(IKeycloakParameters parameters)
        {
            if (parameters == null) throw new ArgumentNullException(nameof(parameters));

            // Verify required parameters
            if (parameters.KeycloakUrl == null)
                throw new ArgumentNullException(nameof(parameters.KeycloakUrl));
            if (parameters.Realm == null)
                throw new ArgumentNullException(nameof(parameters.Realm));

            // Set default parameters
            if (string.IsNullOrWhiteSpace(parameters.ResponseType))
                throw new ArgumentNullException(nameof(parameters.ResponseType));
            if (string.IsNullOrWhiteSpace(parameters.Scope))
                throw new ArgumentNullException(nameof(parameters.Scope));
            if (string.IsNullOrWhiteSpace(parameters.CallbackPath))
                throw new ArgumentNullException(nameof(parameters.CallbackPath));

            // Validate other parameters
            if (!Uri.IsWellFormedUriString(parameters.KeycloakUrl, UriKind.Absolute))
                throw new ArgumentException(nameof(parameters.KeycloakUrl));
            if (!Uri.IsWellFormedUriString(parameters.CallbackPath, UriKind.Relative) &&
                parameters.CallbackPath != Constants.KeycloakParameters.NoCallbackUri)
                throw new ArgumentException(nameof(parameters.CallbackPath));
            if (parameters.PostLogoutRedirectUrl != null &&
                !Uri.IsWellFormedUriString(parameters.PostLogoutRedirectUrl, UriKind.RelativeOrAbsolute))
                throw new ArgumentException(nameof(parameters.PostLogoutRedirectUrl));

            // Attempt to refresh OIDC metadata from endpoint (on separate thread)
            try
            {
                Task.Run(() => OidcDataManager.GetCachedContextAsync(parameters)).Wait();
            }
            catch (Exception exception)
            {
                throw new ArgumentException("Invalid Keycloak server parameters specified: See inner for server error",
                    exception);
            }
        }
Example #49
0
        public async Task <SecurityToken> ValidateTokenAsync(string jwt, IKeycloakParameters options, bool isRefreshToken = false)
        {
            var uriManager = await OidcDataManager.GetCachedContextAsync(options);

            return(ValidateToken(jwt, options, uriManager, isRefreshToken));
        }