/// <summary> /// Creates a session cookie meant to be used to hold the generated JSON Web Token and appends it to the response. /// </summary> /// <param name="cookieValue">The cookie value.</param> private void CreateJwtCookieAndAppendToResponse(string cookieValue) { CookieBuilder cookieBuilder = new RequestPathBaseCookieBuilder { Name = _generalSettings.JwtCookieName, //// To support OAuth authentication, a lax mode is required, see https://github.com/aspnet/Security/issues/1231. SameSite = SameSiteMode.Lax, HttpOnly = true, SecurePolicy = CookieSecurePolicy.Always, IsEssential = true, Domain = _generalSettings.HostName }; CookieOptions cookieOptions = cookieBuilder.Build(HttpContext); ICookieManager cookieManager = new ChunkingCookieManager(); cookieManager.AppendResponseCookie( HttpContext, cookieBuilder.Name, cookieValue, cookieOptions); ApplyHeaders(); }
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)); }
public CookieTempDataProvider(IDataProtectionProvider dataProtectionProvider, IOptions <CookieTempDataProviderOptions> options) { _dataProtector = dataProtectionProvider.CreateProtector(Purpose); _tempDataSerializer = new TempDataSerializer(); _chunkingCookieManager = new ChunkingCookieManager(); _options = options; }
public void GlobalSetup() { _chunkingCookieManager = new ChunkingCookieManager() { ChunkSize = 86 }; _httpContext = new DefaultHttpContext(); _cookieOptions = new CookieOptions() { Domain = "foo.com", Path = "/", Secure = true }; _httpContext.Request.Headers["Cookie"] = new[] { "TestCookie=chunks-7", "TestCookieC1=abcdefghi", "TestCookieC2=jklmnopqr", "TestCookieC3=stuvwxyz0", "TestCookieC4=123456789", "TestCookieC5=ABCDEFGHI", "TestCookieC6=JKLMNOPQR", "TestCookieC7=STUVWXYZ" }; _stringToAdd = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
// 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)); }
public CookieTempDataProvider( IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, IOptions <CookieTempDataProviderOptions> options) { _dataProtector = dataProtectionProvider.CreateProtector(Purpose); _logger = loggerFactory.CreateLogger <CookieTempDataProvider>(); _tempDataSerializer = new TempDataSerializer(); _chunkingCookieManager = new ChunkingCookieManager(); _options = options.Value; }
public void DeleteChunkedCookieWithOptionsAndResponseCookies_AllDeleted() { var chunkingCookieManager = new ChunkingCookieManager(); HttpContext httpContext = new DefaultHttpContext(); httpContext.Request.Headers["Cookie"] = new[] { "TestCookie=chunks-7", "TestCookieC1=abcdefghi", "TestCookieC2=jklmnopqr", "TestCookieC3=stuvwxyz0", "TestCookieC4=123456789", "TestCookieC5=ABCDEFGHI", "TestCookieC6=JKLMNOPQR", "TestCookieC7=STUVWXYZ" }; var cookieOptions = new CookieOptions() { Domain = "foo.com", Path = "/", Secure = true, Extensions = { "extension" } }; httpContext.Response.Headers[HeaderNames.SetCookie] = new[] { "TestCookie=chunks-7; domain=foo.com; path=/; secure; other=extension", "TestCookieC1=STUVWXYZ; domain=foo.com; path=/; secure", "TestCookieC2=123456789; domain=foo.com; path=/; secure", "TestCookieC3=stuvwxyz0; domain=foo.com; path=/; secure", "TestCookieC4=123456789; domain=foo.com; path=/; secure", "TestCookieC5=ABCDEFGHI; domain=foo.com; path=/; secure", "TestCookieC6=JKLMNOPQR; domain=foo.com; path=/; secure", "TestCookieC7=STUVWXYZ; domain=foo.com; path=/; secure" }; chunkingCookieManager.DeleteCookie(httpContext, "TestCookie", cookieOptions); Assert.Equal(8, httpContext.Response.Headers[HeaderNames.SetCookie].Count); Assert.Equal(new[] { "TestCookie=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension", "TestCookieC1=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension", "TestCookieC2=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension", "TestCookieC3=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension", "TestCookieC4=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension", "TestCookieC5=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension", "TestCookieC6=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension", "TestCookieC7=; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=foo.com; path=/; secure; extension" }, httpContext.Response.Headers[HeaderNames.SetCookie]); }
public CookieHelper(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; _config = _serviceProvider.GetInstance <IConfiguration>(); if (_config != null) { _cookieName = _config["Cookie:Name"]; _expiryMinutes = int.Parse(_config["Cookie:ExpiryMinutes"]);//TimeOut } _chunkingCookieManager = new ChunkingCookieManager(); _chunkingCookieManager.ChunkSize = 1000; }
public CompositeTempDataProvider( IDataProtectionProvider dataProtectionProvider, IOptions <CookieTempDataProviderOptions> options, TempDataSerializer tempDataSerializer, ILoggerFactory loggerFactory) { _dataProtector = dataProtectionProvider.CreateProtector(Purpose); _tempDataSerializer = tempDataSerializer; _chunkingCookieManager = new ChunkingCookieManager(); _logger = loggerFactory.CreateLogger <CookieTempDataProvider>(); _options = options.Value; _cookieName = options.Value.Cookie.Name; _tempDataCookieLoadFailure = LoggerMessage.Define <string>( LogLevel.Warning, new EventId(3, "TempDataCookieLoadFailure"), "The temp data cookie {CookieName} could not be loaded."); }
public void GetLargeChunkedCookieWithQuotes_Reassembled() { IOwinContext context = new OwinContext(); context.Request.Headers.AppendValues("Cookie", "TestCookie=chunks:7", "TestCookieC1=\"abcdefghi\"", "TestCookieC2=\"jklmnopqr\"", "TestCookieC3=\"stuvwxyz0\"", "TestCookieC4=\"123456789\"", "TestCookieC5=\"ABCDEFGHI\"", "TestCookieC6=\"JKLMNOPQR\"", "TestCookieC7=\"STUVWXYZ\""); string result = new ChunkingCookieManager().GetRequestCookie(context, "TestCookie"); string testString = "\"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\""; Assert.Equal(testString, result); }
public void GetLargeChunkedCookie_Reassembled() { IOwinContext context = new OwinContext(); context.Request.Headers.AppendValues("Cookie", "TestCookie=chunks:7", "TestCookieC1=abcdefghi", "TestCookieC2=jklmnopqr", "TestCookieC3=stuvwxyz0", "TestCookieC4=123456789", "TestCookieC5=ABCDEFGHI", "TestCookieC6=JKLMNOPQR", "TestCookieC7=STUVWXYZ"); string result = new ChunkingCookieManager().GetRequestCookie(context, "TestCookie"); string testString = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; Assert.Equal(testString, result); }
public void GetLargeChunkedCookie_Reassembled() { HttpContext context = new DefaultHttpContext(); context.Request.Headers["Cookie"] = new[] { "TestCookie=chunks:7", "TestCookieC1=abcdefghi", "TestCookieC2=jklmnopqr", "TestCookieC3=stuvwxyz0", "TestCookieC4=123456789", "TestCookieC5=ABCDEFGHI", "TestCookieC6=JKLMNOPQR", "TestCookieC7=STUVWXYZ" }; string result = new ChunkingCookieManager(null).GetRequestCookie(context, "TestCookie"); string testString = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; Assert.Equal(testString, result); }
// 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 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))); }
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()); }
public void GetLargeChunkedCookieWithMissingChunk_ThrowingDisabled_NotReassembled() { IOwinContext context = new OwinContext(); context.Request.Headers.AppendValues("Cookie", "TestCookie=chunks:7", "TestCookieC1=abcdefghi", // Missing chunk "TestCookieC2=jklmnopqr", "TestCookieC3=stuvwxyz0", "TestCookieC4=123456789", "TestCookieC5=ABCDEFGHI", "TestCookieC6=JKLMNOPQR", "TestCookieC7=STUVWXYZ"); string result = new ChunkingCookieManager() { ThrowForPartialCookies = false }.GetRequestCookie(context, "TestCookie"); string testString = "chunks:7"; Assert.Equal(testString, result); }
/// <summary> /// Creates a session cookie meant to be used to hold the generated JSON Web Token and appends it to the response. /// </summary> /// <param name="cookieValue">The cookie value.</param> private void CreateJwtCookieAndAppendToResponse(string cookieValue) { CookieBuilder cookieBuilder = new RequestPathBaseCookieBuilder { Name = "AltinnStudioRuntime", SameSite = SameSiteMode.Lax, HttpOnly = true, SecurePolicy = CookieSecurePolicy.None, IsEssential = true, Domain = _generalSettings.HostName, Expiration = new TimeSpan(0, 1337, 0) }; CookieOptions cookieOptions = cookieBuilder.Build(HttpContext); ICookieManager cookieManager = new ChunkingCookieManager(); cookieManager.AppendResponseCookie( HttpContext, cookieBuilder.Name, cookieValue, cookieOptions); }
/// <summary> /// This handles cookies that are limited by per cookie length. It breaks down long cookies for responses, and reassembles them /// from requests. The cookies are stored in the System.Web object model rather than directly in the headers. /// </summary> public SystemWebChunkingCookieManager() { ChunkSize = 4090; ThrowForPartialCookies = true; Fallback = new ChunkingCookieManager(); }
public DistributedCacheCookieManager() { _cookieManager = new ChunkingCookieManager(); }
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); } } }
public MyChunkingCookieManager() { _cookieManager = new ChunkingCookieManager(); }
public ChunkingCookieManagerWithSubdomains() { _chunkingCookieManager = new ChunkingCookieManager(); }
public void GetLargeChunkedCookieWithMissingChunk_ThrowingDisabled_NotReassembled() { HttpContext context = new DefaultHttpContext(); context.Request.Headers["Cookie"] = new[] { "TestCookie=chunks-7", "TestCookieC1=abcdefghi", // Missing chunk "TestCookieC2=jklmnopqr", "TestCookieC3=stuvwxyz0", "TestCookieC4=123456789", "TestCookieC5=ABCDEFGHI", "TestCookieC6=JKLMNOPQR", "TestCookieC7=STUVWXYZ" }; string result = new ChunkingCookieManager() { ThrowForPartialCookies = false }.GetRequestCookie(context, "TestCookie"); string testString = "chunks-7"; Assert.Equal(testString, result); }
public void GetLargeChunkedCookieWithQuotes_Reassembled() { HttpContext context = new DefaultHttpContext(); context.Request.Headers["Cookie"] = new[] { "TestCookie=chunks:7", "TestCookieC1=\"abcdefghi\"", "TestCookieC2=\"jklmnopqr\"", "TestCookieC3=\"stuvwxyz0\"", "TestCookieC4=\"123456789\"", "TestCookieC5=\"ABCDEFGHI\"", "TestCookieC6=\"JKLMNOPQR\"", "TestCookieC7=\"STUVWXYZ\"" }; string result = new ChunkingCookieManager(null).GetRequestCookie(context, "TestCookie"); string testString = "\"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\""; Assert.Equal(testString, result); }
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 CookieManager() { manager = new ChunkingCookieManager(); }