private static Task AuthenticationFailed( AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) { context.OwinContext.Response.Redirect("/Home/Error?message=" + context.Exception.Message); context.HandleResponse(); // Suppress the exception return Task.FromResult(0); }
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification) { notification.HandleResponse(); notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message); return Task.FromResult(0); }
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync() { if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path)) { return null; } OpenIdConnectMessage openIdConnectMessage = null; if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(Request.ContentType) && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && Request.Body.CanRead) { if (!Request.Body.CanSeek) { _logger.WriteVerbose("Buffering request body"); MemoryStream memoryStream = new MemoryStream(); await Request.Body.CopyToAsync(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); Request.Body = memoryStream; } IFormCollection form = await Request.ReadFormAsync(); Request.Body.Seek(0, SeekOrigin.Begin); openIdConnectMessage = new OpenIdConnectMessage(form); } if (openIdConnectMessage == null) { return null; } ExceptionDispatchInfo authFailedEx = null; string policy = string.Empty; try { var messageReceivedNotification = new MessageReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage }; await Options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (messageReceivedNotification.Skipped) { return null; } AuthenticationProperties properties = GetPropertiesFromState(openIdConnectMessage.State); if (properties == null) { _logger.WriteWarning("The state field is missing or invalid."); return null; } string nonce = null; if (Options.ProtocolValidator.RequireNonce) { nonce = RetrieveNonce(openIdConnectMessage); } if (!string.IsNullOrWhiteSpace(openIdConnectMessage.Error)) { throw new OpenIdConnectProtocolException( string.Format(CultureInfo.InvariantCulture, openIdConnectMessage.Error, "", openIdConnectMessage.ErrorDescription ?? string.Empty, openIdConnectMessage.ErrorUri ?? string.Empty)); } if (string.IsNullOrWhiteSpace(openIdConnectMessage.IdToken)) { _logger.WriteWarning("The id_token is missing."); return null; } var securityTokenReceivedNotification = new SecurityTokenReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (securityTokenReceivedNotification.Skipped) { return null; } // Enable Per-Policy Metadata Retreival if (properties.Dictionary.TryGetValue(PolicyParameter, out policy)) { B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager; _configuration = await mgr.GetConfigurationAsync(Context.Request.CallCancelled, policy); } else { _logger.WriteWarning("No policy identifier was found in the Authentication Properties of the request."); return null; } TokenValidationParameters tvp = Options.TokenValidationParameters.Clone(); IEnumerable<string> issuers = new[] { _configuration.Issuer }; tvp.ValidIssuers = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers)); tvp.IssuerSigningTokens = (tvp.IssuerSigningTokens == null ? _configuration.SigningTokens : tvp.IssuerSigningTokens.Concat(_configuration.SigningTokens)); SecurityToken validatedToken; ClaimsPrincipal principal = Options.SecurityTokenHandlers.ValidateToken(openIdConnectMessage.IdToken, tvp, out validatedToken); ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity; JwtSecurityToken jwt = validatedToken as JwtSecurityToken; AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties); if (!string.IsNullOrWhiteSpace(openIdConnectMessage.SessionState)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = openIdConnectMessage.SessionState; } if (!string.IsNullOrWhiteSpace(_configuration.CheckSessionIframe)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.CheckSessionIFrame] = _configuration.CheckSessionIframe; } if (Options.UseTokenLifetime) { DateTime issued = jwt.ValidFrom; if (issued != DateTime.MinValue) { ticket.Properties.IssuedUtc = issued.ToUniversalTime(); } DateTime expires = jwt.ValidTo; if (expires != DateTime.MinValue) { ticket.Properties.ExpiresUtc = expires.ToUniversalTime(); } ticket.Properties.AllowRefresh = false; } var securityTokenValidatedNotification = new SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { AuthenticationTicket = ticket, ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); if (securityTokenValidatedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (securityTokenValidatedNotification.Skipped) { return null; } ticket = securityTokenValidatedNotification.AuthenticationTicket; var protocolValidationContext = new OpenIdConnectProtocolValidationContext { AuthorizationCode = openIdConnectMessage.Code, Nonce = nonce, }; Options.ProtocolValidator.Validate(jwt, protocolValidationContext); if (openIdConnectMessage.Code != null) { var authorizationCodeReceivedNotification = new AuthorizationCodeReceivedNotification(Context, Options) { AuthenticationTicket = ticket, Code = openIdConnectMessage.Code, JwtSecurityToken = jwt, ProtocolMessage = openIdConnectMessage, RedirectUri = ticket.Properties.Dictionary.ContainsKey(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey) ? ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey] : string.Empty, }; await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification); if (authorizationCodeReceivedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (authorizationCodeReceivedNotification.Skipped) { return null; } ticket = authorizationCodeReceivedNotification.AuthenticationTicket; } return ticket; } catch (Exception exception) { authFailedEx = ExceptionDispatchInfo.Capture(exception); } if (authFailedEx != null) { _logger.WriteError("Exception occurred while processing message: '" + authFailedEx.ToString()); if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) { B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager; mgr.RequestRefresh(policy); } var authenticationFailedNotification = new AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, Exception = authFailedEx.SourceException }; await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return GetHandledResponseTicket(); } if (authenticationFailedNotification.Skipped) { return null; } authFailedEx.Throw(); } return null; }
// If the javascript issues an OIDC authorize request, and it fails (meaning the user needs to login) // this notification will be triggered with the error message 'login_required' public static Task AuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification) { string cookieStateValue = null; ICookieManager cookieManager = new ChunkingCookieManager(); string cookie = cookieManager.GetRequestCookie(notification.OwinContext, CookieName); AuthenticationTicket ticket = ticketDataFormat.Unprotect(cookie); if (ticket.Properties.Dictionary != null) ticket.Properties.Dictionary.TryGetValue(OpenIdConnectAuthenticationDefaults.AuthenticationType + "SingleSignOut", out cookieStateValue); // If the failed authentication was a result of a request by the SingleSignOut javascript if (cookieStateValue != null && cookieStateValue.Contains(notification.ProtocolMessage.State) && notification.Exception.Message == "login_required"); { // Clear the SingleSignOut cookie, and clear the OIDC session state so //that we don't see any further "Session Changed" messages from the iframe. ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = ""; ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.AuthenticationType + "SingleSignOut"] = ""; cookieManager.AppendResponseCookie(notification.OwinContext, CookieName, ticketDataFormat.Protect(ticket), new CookieOptions()); notification.Response.Redirect("Account/SingleSignOut"); notification.HandleResponse(); } return Task.FromResult<object>(null); }
/// <summary> /// Invokes the login procedure (2nd leg of SP-Initiated login). Analagous to Saml20SignonHandler from ASP.Net DLL /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task<AuthenticationTicket> Invoke(IOwinContext context) { Logger.Debug(TraceMessages.SignOnHandlerCalled); ExceptionDispatchInfo authFailedEx = null; try { var messageReceivedNotification = new MessageReceivedNotification<SamlMessage, SamlAuthenticationOptions>(context, options) { ProtocolMessage = new SamlMessage(context, configuration, null) }; await options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return null; // GetHandledResponseTicket() } if (messageReceivedNotification.Skipped) { return null; } var requestParams = await HandleResponse(context); var assertion = context.Get<Saml20Assertion>("Saml2:assertion"); var securityTokenReceivedNotification = new SecurityTokenReceivedNotification<SamlMessage, SamlAuthenticationOptions>(context, options) { ProtocolMessage = new SamlMessage(context, configuration, assertion) }; await options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return null; // GetHandledResponseTicket(); } if (securityTokenReceivedNotification.Skipped) { return null; } var ticket = await GetAuthenticationTicket(context, requestParams); var securityTokenValidatedNotification = new SecurityTokenValidatedNotification<SamlMessage, SamlAuthenticationOptions>(context, options) { AuthenticationTicket = ticket, ProtocolMessage = new SamlMessage(context, configuration, assertion) }; await options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); if (securityTokenValidatedNotification.HandledResponse) { return null; // GetHandledResponseTicket(); } if (securityTokenValidatedNotification.Skipped) { return null; // null; } // Flow possible changes ticket = securityTokenValidatedNotification.AuthenticationTicket; context.Authentication.AuthenticationResponseGrant = new AuthenticationResponseGrant(ticket.Identity, ticket.Properties); return ticket; } catch (Exception ex) { authFailedEx = ExceptionDispatchInfo.Capture(ex); } if (authFailedEx != null) { Logger.Error("Exception occurred while processing message: " + authFailedEx.SourceException); var message = new SamlMessage(context, configuration, context.Get<Saml20Assertion>("Saml2:assertion")); var authenticationFailedNotification = new AuthenticationFailedNotification<SamlMessage, SamlAuthenticationOptions>(context, options) { ProtocolMessage = message, Exception = authFailedEx.SourceException }; await options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return null;//GetHandledResponseTicket(); } if (authenticationFailedNotification.Skipped) { return null; //null } authFailedEx.Throw(); } return null; }
private Task AuthFailed(AuthenticationFailedNotification <Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> arg) { arg.Response.Redirect(string.Format("/home?msg=", arg.Exception.Message)); return(Task.FromResult(0)); }
private Task OnAuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) { context.HandleResponse(); context.Response.Redirect("/Home/Error?message=" + context.Exception.Message); return(Task.FromResult(0)); }
/// <summary> /// Invoked to process incoming authentication messages. /// </summary> /// <returns></returns> protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { // Allow login to be constrained to a specific path. if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path)) { return(null); } WsFederationMessage wsFederationMessage = null; // assumption: if the ContentType is "application/x-www-form-urlencoded" it should be safe to read as it is small. if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(Request.ContentType) // May have media/type; charset=utf-8, allow partial match. && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && Request.Body.CanRead) { if (!Request.Body.CanSeek) { _logger.WriteVerbose("Buffering request body"); // Buffer in case this body was not meant for us. MemoryStream memoryStream = new MemoryStream(); await Request.Body.CopyToAsync(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); Request.Body = memoryStream; } IFormCollection form = await Request.ReadFormAsync(); Request.Body.Seek(0, SeekOrigin.Begin); // TODO: a delegate on WsFederationAuthenticationOptions would allow for users to hook their own custom message. wsFederationMessage = new WsFederationMessage(form); } if (wsFederationMessage == null || !wsFederationMessage.IsSignInMessage) { return(null); } ExceptionDispatchInfo authFailedEx = null; try { var messageReceivedNotification = new MessageReceivedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options) { ProtocolMessage = wsFederationMessage }; await Options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (messageReceivedNotification.Skipped) { return(null); } if (wsFederationMessage.Wresult == null) { _logger.WriteWarning("Received a sign-in message without a WResult."); return(null); } string token = wsFederationMessage.GetToken(); if (string.IsNullOrWhiteSpace(token)) { _logger.WriteWarning("Received a sign-in message without a token."); return(null); } var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options) { ProtocolMessage = wsFederationMessage }; await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (securityTokenReceivedNotification.Skipped) { return(null); } if (_configuration == null) { _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.Request.CallCancelled); } // Copy and augment to avoid cross request race conditions for updated configurations. TokenValidationParameters tvp = Options.TokenValidationParameters.Clone(); IEnumerable <string> issuers = new[] { _configuration.Issuer }; tvp.ValidIssuers = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers)); tvp.IssuerSigningKeys = (tvp.IssuerSigningKeys == null ? _configuration.SigningKeys : tvp.IssuerSigningKeys.Concat(_configuration.SigningKeys)); ClaimsPrincipal principal = null; SecurityToken parsedToken = null; foreach (var validator in Options.SecurityTokenHandlers) { if (validator.CanReadToken(token)) { principal = validator.ValidateToken(token, tvp, out parsedToken); break; } } if (principal == null) { throw new SecurityTokenException("no validator found"); } ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity; // Retrieve our cached redirect uri string state = wsFederationMessage.Wctx; // WsFed allows for uninitiated logins, state may be missing. AuthenticationProperties properties = GetPropertiesFromWctx(state); AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties); if (Options.UseTokenLifetime) { // Override any session persistence to match the token lifetime. DateTime issued = parsedToken.ValidFrom; if (issued != DateTime.MinValue) { ticket.Properties.IssuedUtc = issued.ToUniversalTime(); } DateTime expires = parsedToken.ValidTo; if (expires != DateTime.MinValue) { ticket.Properties.ExpiresUtc = expires.ToUniversalTime(); } ticket.Properties.AllowRefresh = false; } var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options) { AuthenticationTicket = ticket, ProtocolMessage = wsFederationMessage, }; await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); if (securityTokenValidatedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (securityTokenValidatedNotification.Skipped) { return(null); } // Flow possible changes ticket = securityTokenValidatedNotification.AuthenticationTicket; return(ticket); } catch (Exception exception) { // We can't await inside a catch block, capture and handle outside. authFailedEx = ExceptionDispatchInfo.Capture(exception); } if (authFailedEx != null) { _logger.WriteError("Exception occurred while processing message: ", authFailedEx.SourceException); // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification. if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) { Options.ConfigurationManager.RequestRefresh(); } var authenticationFailedNotification = new AuthenticationFailedNotification <WsFederationMessage, WsFederationAuthenticationOptions>(Context, Options) { ProtocolMessage = wsFederationMessage, Exception = authFailedEx.SourceException }; await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (authenticationFailedNotification.Skipped) { return(null); } authFailedEx.Throw(); } return(null); }
protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path)) { return(null); } OpenIdConnectMessage openIdConnectMessage = null; if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(Request.ContentType) && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && Request.Body.CanRead) { if (!Request.Body.CanSeek) { _logger.WriteVerbose("Buffering request body"); MemoryStream memoryStream = new MemoryStream(); await Request.Body.CopyToAsync(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); Request.Body = memoryStream; } IFormCollection form = await Request.ReadFormAsync(); Request.Body.Seek(0, SeekOrigin.Begin); openIdConnectMessage = new OpenIdConnectMessage(form); } if (openIdConnectMessage == null) { return(null); } ExceptionDispatchInfo authFailedEx = null; try { var messageReceivedNotification = new MessageReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage }; await Options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (messageReceivedNotification.Skipped) { return(null); } AuthenticationProperties properties = new AuthenticationProperties(); properties.RedirectUri = Options.RedirectUri; if (properties == null) { _logger.WriteWarning("The state field is missing or invalid."); return(null); } string nonce = null; if (Options.ProtocolValidator.RequireNonce) { nonce = RetrieveNonce(openIdConnectMessage); } if (!string.IsNullOrWhiteSpace(openIdConnectMessage.Error)) { throw new OpenIdConnectProtocolException( string.Format(CultureInfo.InvariantCulture, openIdConnectMessage.Error, "", openIdConnectMessage.ErrorDescription ?? string.Empty, openIdConnectMessage.ErrorUri ?? string.Empty)); } if (string.IsNullOrWhiteSpace(openIdConnectMessage.IdToken)) { _logger.WriteWarning("The id_token is missing."); return(null); } var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (securityTokenReceivedNotification.Skipped) { return(null); } B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager; _configuration = await mgr.GetConfigurationAsync(Context.Request.CallCancelled, "b2c_1_sign_in_v2"); TokenValidationParameters tvp = Options.TokenValidationParameters.Clone(); IEnumerable <string> issuers = new[] { _configuration.Issuer }; tvp.ValidIssuers = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers)); tvp.IssuerSigningTokens = (tvp.IssuerSigningTokens == null ? _configuration.SigningTokens : tvp.IssuerSigningTokens.Concat(_configuration.SigningTokens)); SecurityToken validatedToken; ClaimsPrincipal principal = Options.SecurityTokenHandlers.ValidateToken(openIdConnectMessage.IdToken, tvp, out validatedToken); ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity; JwtSecurityToken jwt = validatedToken as JwtSecurityToken; AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties); if (!string.IsNullOrWhiteSpace(openIdConnectMessage.SessionState)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = openIdConnectMessage.SessionState; } if (!string.IsNullOrWhiteSpace(_configuration.CheckSessionIframe)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.CheckSessionIFrame] = _configuration.CheckSessionIframe; } if (Options.UseTokenLifetime) { DateTime issued = jwt.ValidFrom; if (issued != DateTime.MinValue) { ticket.Properties.IssuedUtc = issued.ToUniversalTime(); } DateTime expires = jwt.ValidTo; if (expires != DateTime.MinValue) { ticket.Properties.ExpiresUtc = expires.ToUniversalTime(); } ticket.Properties.AllowRefresh = false; } var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { AuthenticationTicket = ticket, ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); if (securityTokenValidatedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (securityTokenValidatedNotification.Skipped) { return(null); } ticket = securityTokenValidatedNotification.AuthenticationTicket; var protocolValidationContext = new OpenIdConnectProtocolValidationContext { AuthorizationCode = openIdConnectMessage.Code, Nonce = nonce, }; Options.ProtocolValidator.Validate(jwt, protocolValidationContext); if (openIdConnectMessage.Code != null) { var authorizationCodeReceivedNotification = new AuthorizationCodeReceivedNotification(Context, Options) { AuthenticationTicket = ticket, Code = openIdConnectMessage.Code, JwtSecurityToken = jwt, ProtocolMessage = openIdConnectMessage, RedirectUri = ticket.Properties.Dictionary.ContainsKey(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey) ? ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey] : string.Empty, }; await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification); if (authorizationCodeReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (authorizationCodeReceivedNotification.Skipped) { return(null); } ticket = authorizationCodeReceivedNotification.AuthenticationTicket; } return(ticket); } catch (Exception exception) { authFailedEx = ExceptionDispatchInfo.Capture(exception); } if (authFailedEx != null) { _logger.WriteError("Exception occurred while processing message: '" + authFailedEx.ToString()); if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) { B2CConfigurationManager mgr = Options.ConfigurationManager as B2CConfigurationManager; mgr.RequestRefresh("b2c_1_sign_in"); } var authenticationFailedNotification = new AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, Exception = authFailedEx.SourceException }; await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (authenticationFailedNotification.Skipped) { return(null); } authFailedEx.Throw(); } return(null); }
// Used for avoiding yellow-screen-of-death private Task AuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification) { notification.HandleResponse(); notification.Response.Redirect("/Home/Error?message=" + notification.Exception.Message); return(Task.FromResult(0)); }
private Task OnAuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification) { notification.HandleResponse(); notification.Response.Redirect("/Error/ShowError?signIn=true&errorMessage=" + notification.Exception.Message); return(Task.FromResult(0)); }
/// <summary> /// Invoked to process incoming authentication messages. /// </summary> /// <returns>An <see cref="AuthenticationTicket"/> if successful.</returns> protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { // Allow login to be constrained to a specific path. Need to make this runtime configurable. if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path)) { return(null); } OpenIdConnectMessage openIdConnectMessage = null; // assumption: if the ContentType is "application/x-www-form-urlencoded" it should be safe to read as it is small. if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(Request.ContentType) // May have media/type; charset=utf-8, allow partial match. && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && Request.Body.CanRead) { if (!Request.Body.CanSeek) { _logger.WriteVerbose("Buffering request body"); // Buffer in case this body was not meant for us. MemoryStream memoryStream = new MemoryStream(); await Request.Body.CopyToAsync(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); Request.Body = memoryStream; } IFormCollection form = await Request.ReadFormAsync(); Request.Body.Seek(0, SeekOrigin.Begin); // TODO: a delegate on OpenIdConnectAuthenticationOptions would allow for users to hook their own custom message. openIdConnectMessage = new OpenIdConnectMessage(form); } if (openIdConnectMessage == null) { return(null); } ExceptionDispatchInfo authFailedEx = null; try { var messageReceivedNotification = new MessageReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage }; await Options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (messageReceivedNotification.Skipped) { return(null); } // runtime always adds state, if we don't find it OR we failed to 'unprotect' it this is not a message we // should process. AuthenticationProperties properties = GetPropertiesFromState(openIdConnectMessage.State); if (properties == null) { _logger.WriteWarning("The state field is missing or invalid."); return(null); } // devs will need to hook AuthenticationFailedNotification to avoid having 'raw' runtime errors displayed to users. if (!string.IsNullOrWhiteSpace(openIdConnectMessage.Error)) { throw new OpenIdConnectProtocolException( string.Format(CultureInfo.InvariantCulture, Resources.Exception_OpenIdConnectMessageError, openIdConnectMessage.Error, openIdConnectMessage.ErrorDescription ?? string.Empty, openIdConnectMessage.ErrorUri ?? string.Empty)); } // code is only accepted with id_token, in this version, hence check for code is inside this if // OpenIdConnect protocol allows a Code to be received without the id_token if (string.IsNullOrWhiteSpace(openIdConnectMessage.IdToken)) { _logger.WriteWarning("The id_token is missing."); return(null); } var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (securityTokenReceivedNotification.Skipped) { return(null); } if (_configuration == null) { _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.Request.CallCancelled); } // Copy and augment to avoid cross request race conditions for updated configurations. TokenValidationParameters tvp = Options.TokenValidationParameters.Clone(); IEnumerable <string> issuers = new[] { _configuration.Issuer }; tvp.ValidIssuers = (tvp.ValidIssuers == null ? issuers : tvp.ValidIssuers.Concat(issuers)); tvp.IssuerSigningKeys = (tvp.IssuerSigningKeys == null ? _configuration.SigningKeys : tvp.IssuerSigningKeys.Concat <SecurityKey>(_configuration.SigningKeys)); SecurityToken validatedToken; ClaimsPrincipal principal = Options.SecurityTokenValidator.ValidateToken(openIdConnectMessage.IdToken, tvp, out validatedToken); ClaimsIdentity claimsIdentity = principal.Identity as ClaimsIdentity; // claims principal could have changed claim values, use bits received on wire for validation. JwtSecurityToken jwt = validatedToken as JwtSecurityToken; AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, properties); string nonce = null; if (Options.ProtocolValidator.RequireNonce) { if (String.IsNullOrWhiteSpace(openIdConnectMessage.Nonce)) { openIdConnectMessage.Nonce = jwt.Payload.Nonce; } // deletes the nonce cookie nonce = RetrieveNonce(openIdConnectMessage); } // remember 'session_state' and 'check_session_iframe' if (!string.IsNullOrWhiteSpace(openIdConnectMessage.SessionState)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.SessionState] = openIdConnectMessage.SessionState; } if (!string.IsNullOrWhiteSpace(_configuration.CheckSessionIframe)) { ticket.Properties.Dictionary[OpenIdConnectSessionProperties.CheckSessionIFrame] = _configuration.CheckSessionIframe; } if (Options.UseTokenLifetime) { // Override any session persistence to match the token lifetime. DateTime issued = jwt.ValidFrom; if (issued != DateTime.MinValue) { ticket.Properties.IssuedUtc = issued.ToUniversalTime(); } DateTime expires = jwt.ValidTo; if (expires != DateTime.MinValue) { ticket.Properties.ExpiresUtc = expires.ToUniversalTime(); } ticket.Properties.AllowRefresh = false; } var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { AuthenticationTicket = ticket, ProtocolMessage = openIdConnectMessage, }; await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); if (securityTokenValidatedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (securityTokenValidatedNotification.Skipped) { return(null); } // Flow possible changes ticket = securityTokenValidatedNotification.AuthenticationTicket; Options.ProtocolValidator.ValidateAuthenticationResponse(new OpenIdConnectProtocolValidationContext() { ClientId = Options.ClientId, ProtocolMessage = openIdConnectMessage, ValidatedIdToken = jwt, Nonce = nonce }); if (openIdConnectMessage.Code != null) { var authorizationCodeReceivedNotification = new AuthorizationCodeReceivedNotification(Context, Options) { AuthenticationTicket = ticket, Code = openIdConnectMessage.Code, JwtSecurityToken = jwt, ProtocolMessage = openIdConnectMessage, RedirectUri = ticket.Properties.Dictionary.ContainsKey(OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey) ? ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.RedirectUriUsedForCodeKey] : string.Empty, }; await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification); if (authorizationCodeReceivedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (authorizationCodeReceivedNotification.Skipped) { return(null); } // Flow possible changes ticket = authorizationCodeReceivedNotification.AuthenticationTicket; } return(ticket); } catch (Exception exception) { // We can't await inside a catch block, capture and handle outside. authFailedEx = ExceptionDispatchInfo.Capture(exception); } if (authFailedEx != null) { _logger.WriteError("Exception occurred while processing message: ", authFailedEx.SourceException); // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification. if (Options.RefreshOnIssuerKeyNotFound && authFailedEx.SourceException.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) { Options.ConfigurationManager.RequestRefresh(); } var authenticationFailedNotification = new AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) { ProtocolMessage = openIdConnectMessage, Exception = authFailedEx.SourceException }; await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return(GetHandledResponseTicket()); } if (authenticationFailedNotification.Skipped) { return(null); } authFailedEx.Throw(); } return(null); }
/// <summary> /// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using <see cref="TokenValidationParameters"/> set in the options. /// </summary> /// <returns></returns> protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { string token = null; try { // Give application opportunity to find from a different location, adjust, or reject token var messageReceivedNotification = new MessageReceivedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options) { ProtocolMessage = Context, }; // notification can set the token await Options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return(messageReceivedNotification.AuthenticationTicket); } if (messageReceivedNotification.Skipped) { return(null); } // If application retrieved token from somewhere else, use that. token = messageReceivedNotification.Token; if (string.IsNullOrEmpty(token)) { string authorization = Request.Headers.Get("Authorization"); // If no authorization header found, nothing to process further if (string.IsNullOrEmpty(authorization)) { return(null); } if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { token = authorization.Substring("Bearer ".Length).Trim(); } // If no token found, no further work possible if (string.IsNullOrEmpty(token)) { return(null); } } // notify user token was received var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options) { ProtocolMessage = Context, SecurityToken = token, }; await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return(securityTokenReceivedNotification.AuthenticationTicket); } if (securityTokenReceivedNotification.Skipped) { return(null); } if (_configuration == null && Options.ConfigurationManager != null) { _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted); } var validationParameters = Options.TokenValidationParameters.Clone(); if (_configuration != null) { if (validationParameters.ValidIssuer == null && !string.IsNullOrWhiteSpace(_configuration.Issuer)) { validationParameters.ValidIssuer = _configuration.Issuer; } else { IEnumerable <string> issuers = new[] { _configuration.Issuer }; validationParameters.ValidIssuers = (validationParameters.ValidIssuers == null ? issuers : validationParameters.ValidIssuers.Concat(issuers)); } validationParameters.IssuerSigningKeys = (validationParameters.IssuerSigningKeys == null ? _configuration.SigningKeys : validationParameters.IssuerSigningKeys.Concat(_configuration.SigningKeys)); } SecurityToken validatedToken; foreach (var validator in Options.SecurityTokenValidators) { if (validator.CanReadToken(token)) { ClaimsPrincipal principal = validator.ValidateToken(token, validationParameters, out validatedToken); AuthenticationTicket ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Options.AuthenticationScheme); var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options) { ProtocolMessage = Context, AuthenticationTicket = ticket }; if (securityTokenReceivedNotification.HandledResponse) { return(securityTokenValidatedNotification.AuthenticationTicket); } if (securityTokenReceivedNotification.Skipped) { return(null); } return(ticket); } } throw new InvalidOperationException("No SecurityTokenValidator available for token: " + token ?? "null"); } catch (Exception ex) { _logger.LogError("Exception occurred while processing message", ex); // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification. if (Options.RefreshOnIssuerKeyNotFound && ex.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) { Options.ConfigurationManager.RequestRefresh(); } var authenticationFailedNotification = new AuthenticationFailedNotification <HttpContext, OAuthBearerAuthenticationOptions>(Context, Options) { ProtocolMessage = Context, Exception = ex }; await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return(authenticationFailedNotification.AuthenticationTicket); } if (authenticationFailedNotification.Skipped) { return(null); } throw; } }
private Task OnAuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> arg) { arg.HandleResponse(); arg.Response.Redirect("/?errormessage" + arg.Exception.Message); return(Task.FromResult(0)); }
/// <summary> /// Invokes the login procedure (2nd leg of SP-Initiated login). Analagous to Saml20SignonHandler from ASP.Net DLL /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task <AuthenticationTicket> Invoke(IOwinContext context) { Logger.Debug(TraceMessages.SignOnHandlerCalled); ExceptionDispatchInfo authFailedEx = null; try { var messageReceivedNotification = new MessageReceivedNotification <SamlMessage, SamlAuthenticationOptions>(context, options) { ProtocolMessage = new SamlMessage(context, configuration, null) }; await options.Notifications.MessageReceived(messageReceivedNotification); if (messageReceivedNotification.HandledResponse) { return(null); // GetHandledResponseTicket() } if (messageReceivedNotification.Skipped) { return(null); } var requestParams = await HandleResponse(context); var assertion = context.Get <Saml20Assertion>("Saml2:assertion"); var securityTokenReceivedNotification = new SecurityTokenReceivedNotification <SamlMessage, SamlAuthenticationOptions>(context, options) { ProtocolMessage = new SamlMessage(context, configuration, assertion) }; await options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); if (securityTokenReceivedNotification.HandledResponse) { return(null); // GetHandledResponseTicket(); } if (securityTokenReceivedNotification.Skipped) { return(null); } var ticket = await GetAuthenticationTicket(context, requestParams); var securityTokenValidatedNotification = new SecurityTokenValidatedNotification <SamlMessage, SamlAuthenticationOptions>(context, options) { AuthenticationTicket = ticket, ProtocolMessage = new SamlMessage(context, configuration, assertion) }; await options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); if (securityTokenValidatedNotification.HandledResponse) { return(null); // GetHandledResponseTicket(); } if (securityTokenValidatedNotification.Skipped) { return(null); // null; } // Flow possible changes ticket = securityTokenValidatedNotification.AuthenticationTicket; context.Authentication.AuthenticationResponseGrant = new AuthenticationResponseGrant(ticket.Identity, ticket.Properties); return(ticket); } catch (Exception ex) { authFailedEx = ExceptionDispatchInfo.Capture(ex); } if (authFailedEx != null) { Logger.Error("Exception occurred while processing message: " + authFailedEx.SourceException); var message = new SamlMessage(context, configuration, context.Get <Saml20Assertion>("Saml2:assertion")); var authenticationFailedNotification = new AuthenticationFailedNotification <SamlMessage, SamlAuthenticationOptions>(context, options) { ProtocolMessage = message, Exception = authFailedEx.SourceException }; await options.Notifications.AuthenticationFailed(authenticationFailedNotification); if (authenticationFailedNotification.HandledResponse) { return(null);//GetHandledResponseTicket(); } if (authenticationFailedNotification.Skipped) { return(null); //null } authFailedEx.Throw(); } return(null); }
private static Task AuthenticationFailed(AuthenticationFailedNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> authenticationFailedNotification) { // serilogAdapter.Exception(authenticationFailedNotification.Exception); return(Task.FromResult(0)); }