コード例 #1
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 : "")));
        }
        /// <summary>
        /// Method logs generates the logout url for the realm and performs a user log out
        /// and issues a redirection to the login page for the user to enter credentials again.
        /// </summary>
        /// <param name="identity">Current identity signed in keycloak. It will be forced log out.</param>
        /// <returns>Redirection to login page</returns>
        private async Task ForceLogoutRedirectAsync(ClaimsIdentity identity)
        {
            // generate logout uri
            var uri = await KeycloakIdentity.GenerateLogoutUriAsync(Options, Request.Uri);

            //foreach (var claim in identity.Claims)
            //{
            //    _logger.Debug($"ForceLogoutRedirectAsync user claim {claim.Type} - {claim.Value}");
            //}

            _logger.Debug($"Force logout identity with isAuthenticated:{identity.IsAuthenticated}");

            Claim firstOrDefault = identity.Claims.FirstOrDefault(claim => claim.Type == "refresh_token");

            if (firstOrDefault != null)
            {
                await OidcDataManager.HttpLogoutPost(firstOrDefault.Value, Options, uri);
            }

            //redirect to relogin
            var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);

            if (challenge == null)
            {
                _logger.Debug($"Force logged out {identity.Name}.Challenge is null.Return.");
                return;
            }

            _logger.Debug($"Force logged out {identity.Name}.Redirecting from challenge properties.");
            await LoginRedirectAsync(challenge.Properties);
        }
コード例 #3
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);
            }
        }
コード例 #4
0
        private async Task <string> ExecuteHttpRequestAsync()
        {
            var uriManager = OidcDataManager.GetCachedContext(Options);
            var response   = await SendHttpPostRequest(uriManager.GetTokenEndpoint(),
                                                       uriManager.BuildAccessTokenEndpointContent(Request.Uri, AuthResponse.Code));

            return(await response.Content.ReadAsStringAsync());
        }
コード例 #5
0
        private async Task <string> ExecuteHttpRequestAsync()
        {
            var uriManager = await OidcDataManager.GetCachedContextAsync(Context, Options);

            var response =
                await
                SendHttpPostRequest(uriManager.GetTokenEndpoint(),
                                    uriManager.BuildRefreshTokenEndpointContent(RefreshToken));

            return(await response.Content.ReadAsStringAsync());
        }
コード例 #6
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));
        }
コード例 #7
0
        protected async Task CopyFromJwt(string accessToken, string refreshToken = null, string idToken = null)
        {
            if (accessToken == null)
            {
                throw new ArgumentException(nameof(accessToken));
            }

            // Validate JWTs provided
            var tokenHandler = new KeycloakTokenHandler();
            var uriManager   = await OidcDataManager.GetCachedContextAsync(_parameters);

            SecurityToken accessSecurityToken, idSecurityToken = null, refreshSecurityToken = null;

            if (_parameters.UseRemoteTokenValidation)
            {
                accessSecurityToken = await KeycloakTokenHandler.ValidateTokenRemote(accessToken, uriManager);
            }
            else
            {
                accessSecurityToken = tokenHandler.ValidateToken(accessToken, _parameters, uriManager);
            }

            // Double-check
            if (accessSecurityToken == null)
            {
                throw new Exception("Internal error: Invalid access token; valid required");
            }

            if (idToken != null)
            {
                idSecurityToken = tokenHandler.ValidateToken(idToken, _parameters, uriManager);
            }
            if (refreshToken != null)
            {
                refreshSecurityToken = tokenHandler.ValidateToken(refreshToken, _parameters, uriManager);
            }

            // Save to this object
            // TODO: Convert to MS claims parsing in token handler
            _kcClaims = GenerateJwtClaims(accessSecurityToken as JwtSecurityToken, idSecurityToken as JwtSecurityToken,
                                          refreshSecurityToken as JwtSecurityToken);
            _idToken      = idSecurityToken as JwtSecurityToken;
            _accessToken  = accessSecurityToken as JwtSecurityToken;
            _refreshToken = refreshSecurityToken as JwtSecurityToken;
        }
コード例 #8
0
        /// <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 : "")));
        }
コード例 #9
0
        public static async Task <ClaimsIdentity> GetKeycloakIdentityAsync(string username, string password)
        {
            if (Options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
            {
                throw new InvalidCredentialException("username or password is empty.");
            }
            var uriManager = await OidcDataManager.GetCachedContextAsync(Options);

            var response = SendHttpPostRequest(uriManager.GetTokenEndpoint(), uriManager.BuildROPCAccessTokenEndpointContent(username, password));

            var result = await response.Content.ReadAsStringAsync();

            var tokenrespones = new TokenResponse(result);

            var claimidentity = await KeycloakIdentity.ConvertFromTokenResponseAsync(Options, tokenrespones);

            var identity = await claimidentity.ToClaimsIdentityAsync();

            return(new ClaimsIdentity(identity.Claims, Options.SignInAsAuthenticationSchema, identity.NameClaimType, identity.RoleClaimType));
        }