public static Task RedirectToIdentityProvider(RedirectToIdentityProviderNotification <OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification) { // If a challenge was issued by the SingleSignOut javascript UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext); if (notification.Request.Uri.AbsolutePath == url.Action("SessionChanged", "Account")) { // Store the state in the cookie so we can distinguish OIDC messages that occurred // as a result of the SingleSignOut javascript. ICookieManager cookieManager = new ChunkingCookieManager(); string cookie = cookieManager.GetRequestCookie(notification.OwinContext, CookieName); AuthenticationTicket ticket = ticketDataFormat.Unprotect(cookie); if (ticket.Properties.Dictionary != null) { ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.AuthenticationType + "SingleSignOut"] = notification.ProtocolMessage.State; } cookieManager.AppendResponseCookie(notification.OwinContext, CookieName, ticketDataFormat.Protect(ticket), new CookieOptions()); // Return prompt=none request (to tenant specific endpoint) to SessionChanged controller. notification.ProtocolMessage.Prompt = "none"; notification.ProtocolMessage.IssuerAddress = notification.OwinContext.Authentication.User.FindFirst("issEndpoint").Value; string redirectUrl = notification.ProtocolMessage.BuildRedirectUrl(); notification.Response.Redirect(url.Action("SessionChanged", "Account") + "?" + redirectUrl); notification.HandleResponse(); } return(Task.FromResult <object>(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> /// Loads the temp data from the request. /// </summary> /// <param name="context">The <see cref="HttpContext"/>.</param> /// <returns>The temp data.</returns> public IDictionary <string, object> LoadTempData(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.Request.Cookies.ContainsKey(_options.Cookie.Name)) { // The cookie we use for temp data is user input, and might be invalid in many ways. // // Since TempData is a best-effort system, we don't want to throw and get a 500 if the cookie is // bad, we will just clear it and ignore the exception. The common case that we've identified for // this is misconfigured data protection settings, which can cause the key used to create the // cookie to no longer be available. try { var encodedValue = _chunkingCookieManager.GetRequestCookie(context, _options.Cookie.Name); if (!string.IsNullOrEmpty(encodedValue)) { var protectedData = WebEncoders.Base64UrlDecode(encodedValue); var unprotectedData = _dataProtector.Unprotect(protectedData); var tempData = _tempDataSerializer.Deserialize(unprotectedData); _logger.TempDataCookieLoadSuccess(_options.Cookie.Name); return(tempData); } } catch (Exception ex) { _logger.TempDataCookieLoadFailure(_options.Cookie.Name, ex); // If we've failed, we want to try and clear the cookie so that this won't keep happening // over and over. if (!context.Response.HasStarted) { _chunkingCookieManager.DeleteCookie(context, _options.Cookie.Name, _options.Cookie.Build(context)); } } } _logger.TempDataCookieNotFound(_options.Cookie.Name); return(new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase)); }
// If the javascript issues an OIDC authorize reuest, and it succeeds, the user is already logged // into AAD. Since the AAD session cookie has changed, we need to check if the same use is still // logged in. public static Task AuthorizationCodeRecieved(AuthorizationCodeReceivedNotification notification) { // If the successful authorize request was issued by the SingleSignOut javascript if (notification.AuthenticationTicket.Properties.RedirectUri.Contains("SessionChanged")) { // Clear the SingleSignOut Cookie ICookieManager cookieManager = new ChunkingCookieManager(); string cookie = cookieManager.GetRequestCookie(notification.OwinContext, CookieName); AuthenticationTicket ticket = ticketDataFormat.Unprotect(cookie); if (ticket.Properties.Dictionary != null) { ticket.Properties.Dictionary[OpenIdConnectAuthenticationDefaults.AuthenticationType + "SingleSignOut"] = ""; } cookieManager.AppendResponseCookie(notification.OwinContext, CookieName, ticketDataFormat.Protect(ticket), new CookieOptions()); Claim existingUserObjectId = notification.OwinContext.Authentication.User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"); Claim incomingUserObjectId = notification.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"); if (existingUserObjectId.Value != null && incomingUserObjectId != null) { // If a different user is logged into AAD if (existingUserObjectId.Value != incomingUserObjectId.Value) { // No need to clear the session state here. It has already been // updated with the new user's session state in SecurityTokenValidated. notification.Response.Redirect("Account/SingleSignOut"); notification.HandleResponse(); } // If the same user is logged into AAD else if (existingUserObjectId.Value == incomingUserObjectId.Value) { // No need to clear the session state, SecurityTokenValidated will do so. // Simply redirect the iframe to a page other than SingleSignOut to reset // the timer in the javascript. notification.Response.Redirect("/"); notification.HandleResponse(); } } } return(Task.FromResult <object>(null)); }
public IDictionary <string, object> LoadTempData(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.Request.Cookies.ContainsKey(CookieName)) { var encodedValue = _chunkingCookieManager.GetRequestCookie(context, CookieName); if (!string.IsNullOrEmpty(encodedValue)) { var protectedData = Base64UrlTextEncoder.Decode(encodedValue); var unprotectedData = _dataProtector.Unprotect(protectedData); return(_tempDataSerializer.Deserialize(unprotectedData)); } } return(new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase)); }
public IActionResult DecryptCookie() { var cookieManager = new ChunkingCookieManager(); var cookie = cookieManager.GetRequestCookie(HttpContext, ".AspNetCore.Identity.Application"); var dataProtector = _protector.CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", "Identity.Application", "v2"); //Get the decrypted cookie as plain text UTF8Encoding specialUtf8Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); var protectedBytes = Base64UrlTextEncoder.Decode(cookie); var plainBytes = dataProtector.Unprotect(protectedBytes); var plainText = specialUtf8Encoding.GetString(plainBytes); //Get teh decrypted cookies as a Authentication Ticket var ticketDataFormat = new TicketDataFormat(dataProtector); var ticket = ticketDataFormat.Unprotect(cookie); return(View(new CookieDetails(plainText, ticket))); }
/// <summary> /// Gets the reassembled cookie using chunkingCookieManager. /// </summary> /// <param name="cookieName">The cookie to get. If null, default cookieName in app.config will be used</param> /// <returns>The value of the cookie or an empty string</returns> public string GetCookie(string cookieName) { try { string cookie = string.Empty; string key = String.IsNullOrEmpty(cookieName) ? _cookieName : cookieName; IHttpContextAccessor currentContextAccessor = _serviceProvider.GetInstance <IHttpContextAccessor>(); if ((currentContextAccessor != null) && (currentContextAccessor.HttpContext != null)) { cookie = _chunkingCookieManager.GetRequestCookie(currentContextAccessor.HttpContext, key); } return(cookie); } catch (Exception ex) { string setBreakPointHere = ex.Message; return(String.Empty); } }
public IActionResult DecryptCookie() { //var cookieValue = HttpContext.Request.Cookies[".AspNetCore.CookiesC1"]; var cookieManager = new ChunkingCookieManager(); var cookieValue = cookieManager.GetRequestCookie(HttpContext, ".AspNetCore.Cookies"); //Get a data protector to use with either approach var dataProtector = _provider.CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", "Cookies", "v2"); //Get the decrypted cookie as plain text UTF8Encoding specialUtf8Encoding = new UTF8Encoding(); byte[] protectedBytes = Base64UrlTextEncoder.Decode(cookieValue); byte[] plainBytes = dataProtector.Unprotect(protectedBytes); string plainText = Encoding.UTF8.GetString(plainBytes).ToString(); return(View()); }
private byte[] GetOrCreateSessionId(IDotvvmRequestContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var sessionIdCookieName = GetSessionIdCookieName(context); if (string.IsNullOrWhiteSpace(sessionIdCookieName)) { throw new FormatException("Configured SessionIdCookieName is missing or empty."); } // Get cookie manager var mgr = new ChunkingCookieManager(); // TODO: Make this configurable // Get application key helper var keyHelper = new ApplicationKeyHelper(context.Configuration.Security); // Get cookie value var sidCookieValue = mgr.GetRequestCookie(context.OwinContext, sessionIdCookieName); if (string.IsNullOrWhiteSpace(sidCookieValue)) { // No SID - generate and protect new one var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(); var sid = new byte[SID_LENGTH]; rng.GetBytes(sid); var protectedSid = keyHelper.ProtectData(sid, KDF_LABEL_SID); // Save to cookie sidCookieValue = Convert.ToBase64String(protectedSid); mgr.AppendResponseCookie( context.OwinContext, sessionIdCookieName, // Configured cookie name sidCookieValue, // Base64-encoded SID value new Microsoft.Owin.CookieOptions { HttpOnly = true, // Don't allow client script access Secure = context.OwinContext.Request.IsSecure // If request goes trough HTTPS, mark as secure only }); // Return newly generated SID return(sid); } else { // Try to read from cookie try { var protectedSid = Convert.FromBase64String(sidCookieValue); var sid = keyHelper.UnprotectData(protectedSid, KDF_LABEL_SID); return(sid); } catch (Exception ex) { // Incorrect Base64 formatting of crypto protection error throw new SecurityException("Value of the SessionID cookie is corrupted or has been tampered with.", ex); } } }
private byte[] GetOrCreateSessionId(IDotvvmRequestContext context, bool canGenerate = true) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var sessionIdCookieName = GetSessionIdCookieName(context); if (string.IsNullOrWhiteSpace(sessionIdCookieName)) { throw new FormatException("Configured SessionIdCookieName is missing or empty."); } // Get cookie manager var mgr = new ChunkingCookieManager(); // TODO: Make this configurable // Construct protector with purposes var userIdentity = ProtectionHelpers.GetUserIdentity(context); var requestIdentity = ProtectionHelpers.GetRequestIdentity(context); var protector = this.protectionProvider.Create(PURPOSE_SID); // Get cookie value var sidCookieValue = mgr.GetRequestCookie(context.GetOwinContext(), sessionIdCookieName); if (!string.IsNullOrWhiteSpace(sidCookieValue)) { // Try to read from cookie try { var protectedSid = Convert.FromBase64String(sidCookieValue); var sid = protector.Unprotect(protectedSid); return(sid); } catch (Exception ex) { // Incorrect Base64 formatting of crypto protection error // Generate new one or thow error if can't if (!canGenerate) { throw new SecurityException("Value of the SessionID cookie is corrupted or has been tampered with.", ex); } // else suppress error and generate new SID } } // No SID - generate and protect new one if (canGenerate) { var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(); var sid = new byte[SID_LENGTH]; rng.GetBytes(sid); var protectedSid = protector.Protect(sid); // Save to cookie sidCookieValue = Convert.ToBase64String(protectedSid); mgr.AppendResponseCookie( context.GetOwinContext(), sessionIdCookieName, // Configured cookie name sidCookieValue, // Base64-encoded SID value new Microsoft.Owin.CookieOptions { HttpOnly = true, // Don't allow client script access Secure = context.HttpContext.Request.IsHttps // If request goes trough HTTPS, mark as secure only }); // Return newly generated SID return(sid); } else { throw new SecurityException("SessionID cookie is missing, so can't verify CSRF token."); } }
public string GetRequestCookie(IOwinContext context, string key) { return(_chunkingCookieManager.GetRequestCookie(context, key)); }
public string GetRequestCookie(HttpContext context, string key) { return(_cookieManager.GetRequestCookie(context, key)); }