/// <summary> /// Creates a result that indicates an error. /// </summary> /// <param name="message"></param> /// <param name="request"></param> /// <returns></returns> protected virtual EndSessionValidationResult Invalid(string message, ValidatedEndSessionRequest request = null) { message = "End session request validation failure: " + message; if (request != null) { var log = new EndSessionRequestValidationLog(request); Logger.LogInformation(message + Environment.NewLine + "{@details}", log); } else { Logger.LogInformation(message); } return(new EndSessionValidationResult { IsError = true, Error = "Invalid request", ErrorDescription = message }); }
/// <summary> /// Logs a success result. /// </summary> /// <param name="request"></param> protected virtual void LogSuccess(ValidatedEndSessionRequest request) { var log = new EndSessionRequestValidationLog(request); Logger.LogInformation("End session request validation success" + Environment.NewLine + "{@details}", log); }
/// <inheritdoc /> public async Task <EndSessionValidationResult> ValidateAsync(NameValueCollection parameters, ClaimsPrincipal subject) { Logger.LogDebug("Start end session request validation"); var isAuthenticated = subject.IsAuthenticated(); if (!isAuthenticated && Options.Authentication.RequireAuthenticatedUserForSignOutMessage) { return(Invalid("User is anonymous. Ignoring end session parameters")); } var validatedRequest = new ValidatedEndSessionRequest { Raw = parameters }; var idTokenHint = parameters.Get(OidcConstants.EndSessionRequest.IdTokenHint); if (idTokenHint.IsPresent()) { // validate id_token - no need to validate token life time var tokenValidationResult = await TokenValidator.ValidateIdentityTokenAsync(idTokenHint, null, false); if (tokenValidationResult.IsError) { return(Invalid("Error validating id token hint", validatedRequest)); } validatedRequest.Client = tokenValidationResult.Client; // validate sub claim against currently logged on user var subClaim = tokenValidationResult.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject); if (subClaim != null && isAuthenticated) { if (subject.GetSubjectId() != subClaim.Value) { return(Invalid("Current user does not match identity token", validatedRequest)); } validatedRequest.Subject = subject; validatedRequest.SessionId = await UserSession.GetSessionIdAsync(); validatedRequest.ClientIds = await UserSession.GetClientListAsync(); } var redirectUri = parameters.Get(OidcConstants.EndSessionRequest.PostLogoutRedirectUri); if (redirectUri.IsPresent()) { if (await UriValidator.IsPostLogoutRedirectUriValidAsync(redirectUri, validatedRequest.Client)) { validatedRequest.PostLogOutUri = redirectUri; } else { Logger.LogWarning("Invalid PostLogoutRedirectUri: {postLogoutRedirectUri}", redirectUri); } } if (validatedRequest.PostLogOutUri != null) { var state = parameters.Get(OidcConstants.EndSessionRequest.State); if (state.IsPresent()) { validatedRequest.State = state; } } } else { // no id_token to authenticate the client, but we do have a user and a user session validatedRequest.Subject = subject; validatedRequest.SessionId = await UserSession.GetSessionIdAsync(); validatedRequest.ClientIds = await UserSession.GetClientListAsync(); } LogSuccess(validatedRequest); return(new EndSessionValidationResult { ValidatedRequest = validatedRequest, IsError = false }); }