private void SetTokenCookies(String accessToken, SecurityToken token, String refreshToken)
        {
            //There is no end to the pain of trying to get this right, fix the path here to ensure its correct.
            var cookiePath = CookieUtils.FixPath(Options.CookiePath);

            var expires = Options.StoreCookiesInSession ? default(DateTimeOffset?) : token.ValidTo;

            cookieManager.AppendResponseCookie(Context, BearerCookieName, accessToken, new CookieOptions()
            {
                Secure   = true,
                HttpOnly = Options.BearerHttpOnly,
                Path     = cookiePath,
                Expires  = expires,
                SameSite = Options.SameSite
            });

            cookieManager.AppendResponseCookie(Context, RefreshCookieName, refreshToken, new CookieOptions()
            {
                Secure   = true,
                HttpOnly = Options.RefreshHttpOnly,
                Path     = cookiePath,
                Expires  = expires,
                SameSite = Options.SameSite
            });
        }
예제 #2
0
        protected void GenerateCorrelationId(ICookieManager cookieManager, AuthenticationProperties properties)
        {
            if (cookieManager == null)
            {
                throw new ArgumentNullException("cookieManager");
            }
            if (properties == null)
            {
                throw new ArgumentNullException("properties");
            }

            string correlationKey = Constants.CorrelationPrefix + BaseOptions.AuthenticationType;

            var nonceBytes = new byte[32];

            Random.GetBytes(nonceBytes);
            string correlationId = TextEncodings.Base64Url.Encode(nonceBytes);

            var cookieOptions = new CookieOptions
            {
                SameSite = SameSiteMode.None,
                HttpOnly = true,
                Secure   = Request.IsSecure
            };

            properties.Dictionary[correlationKey] = correlationId;

            cookieManager.AppendResponseCookie(Context, correlationKey, correlationId, cookieOptions);
        }
예제 #3
0
        private static void ApplyCookies(
            CommandResult commandResult,
            IOwinContext context,
            IDataProtector dataProtector,
            ICookieManager cookieManager,
            bool emitSameSiteNone)
        {
            var serializedCookieData = commandResult.GetSerializedRequestState();

            if (serializedCookieData != null && !string.IsNullOrEmpty(commandResult.SetCookieName))
            {
                var protectedData = HttpRequestData.ConvertBinaryData(
                    dataProtector.Protect(serializedCookieData));

                cookieManager.AppendResponseCookie(context,
                                                   commandResult.SetCookieName,
                                                   protectedData,
                                                   new CookieOptions()
                {
                    HttpOnly = true,
                    Secure   = commandResult.SetCookieSecureFlag,
                    SameSite = emitSameSiteNone ? SameSiteMode.None : default(SameSiteMode?)
                });
            }

            commandResult.ApplyClearCookie(context, cookieManager);
        }
        private void OAuthAuthenticationTokenProviderOnReceive(AuthenticationTokenReceiveContext context)
        {
            AuthenticationTicket result   = null;
            ClaimsIdentity       identity = _identityHelper.GetCurrentClaimsPrincipal()?.Identity as ClaimsIdentity;

            if (identity?.IsAuthenticated ?? false)
            {
                result = BuildOAuthAuthenticationTicket(identity);
            }
            else
            {
                identity = context.OwinContext.Get <ClaimsIdentity>(OAuthAuthentication.OAuthOwinContextKey);
                if (identity != null)
                {
                    result = BuildOAuthAuthenticationTicket(identity);
                    string sessionId = _authSessionStore.StoreAsync(result).Result;
                    _cookieManager.AppendResponseCookie(
                        context.OwinContext,
                        IdentityHelper.AuthenticationCookieKey,
                        IdentityHelper.TicketDataFormat.Protect(BuildCookiesAuthenticationTicket(sessionId)),
                        new CookieOptions {
                        HttpOnly = true, Secure = true
                    });
                }
            }

            context.SetTicket(result);
        }
예제 #5
0
        /// <summary>
        /// Adds the or update cookie.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        private void AddOrUpdateCookie(string key, string value)
        {
            double minutes;
            var    timeSpan = double.TryParse(_appSetting["CookieSessionTimeout"], out minutes) ?
                              TimeSpan.FromMinutes(minutes) : TimeSpan.FromMinutes(525600);

            _cookieManager.AppendResponseCookie(System.Web.HttpContext.Current, key, EncryptValue(value),
                                                HttpOnly: true,
                                                Secure: true,
                                                Path: "/",
                                                Expires: DateTime.Now.Add(timeSpan)
                                                );
        }
 public void AppendResponseCookie(IOwinContext context, string key, string value,
                                  CookieOptions options)
 {
     CheckSameSite(context, options);
     _innerManager.AppendResponseCookie(context, key, value, options);
 }
예제 #7
0
        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.");
            }

            // Construct protector with purposes
            var protector = this.protectionProvider.Create(PURPOSE_SID);

            // Get cookie value
            var sidCookieValue = cookieManager.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 CorruptedCsrfTokenException("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);
                cookieManager.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 void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options)
 {
     SetupDomain(context, options);
     _defaultCookieManager.AppendResponseCookie(context, key, value, options);
 }
예제 #9
0
        public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options)
        {
            var siteContext = context.RequestServices.GetRequiredService <ITenantContext>();

            _concreteManager.AppendResponseCookie(context, $"{key}{siteContext.SiteContext.IdentityCookieName}", value, options);
        }
예제 #10
0
        public static async Task <bool> ValidateSessionAsync(
            TimeSpan validateInterval,
            IOwinContext owinCtx,
            ICookieManager cookieManager,
            ISystemClock systemClock,
            DateTimeOffset?authTicketIssueDate,
            ClaimsIdentity currentIdentity,
            IGlobalSettings globalSettings)
        {
            if (owinCtx == null)
            {
                throw new ArgumentNullException("owinCtx");
            }
            if (cookieManager == null)
            {
                throw new ArgumentNullException("cookieManager");
            }
            if (systemClock == null)
            {
                throw new ArgumentNullException("systemClock");
            }

            DateTimeOffset?issuedUtc  = null;
            var            currentUtc = systemClock.UtcNow;

            //read the last checked time from a custom cookie
            var lastCheckedCookie = cookieManager.GetRequestCookie(owinCtx, CookieName);

            if (lastCheckedCookie.IsNullOrWhiteSpace() == false)
            {
                DateTimeOffset parsed;
                if (DateTimeOffset.TryParse(lastCheckedCookie, out parsed))
                {
                    issuedUtc = parsed;
                }
            }

            //no cookie, use the issue time of the auth ticket
            if (issuedUtc.HasValue == false)
            {
                issuedUtc = authTicketIssueDate;
            }

            // Only validate if enough time has elapsed
            var validate = issuedUtc.HasValue == false;

            if (issuedUtc.HasValue)
            {
                var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
                validate = timeElapsed > validateInterval;
            }

            if (validate == false)
            {
                return(true);
            }

            var manager = owinCtx.GetUserManager <BackOfficeUserManager>();

            if (manager == null)
            {
                return(false);
            }

            var userId = currentIdentity.GetUserId <int>();
            var user   = await manager.FindByIdAsync(userId);

            if (user == null)
            {
                return(false);
            }

            var sessionId = currentIdentity.FindFirstValue(Constants.Security.SessionIdClaimType);

            if (await manager.ValidateSessionIdAsync(userId, sessionId) == false)
            {
                return(false);
            }

            //we will re-issue the cookie last checked cookie
            cookieManager.AppendResponseCookie(
                owinCtx,
                CookieName,
                DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz"),
                new CookieOptions
            {
                HttpOnly = true,
                Secure   = globalSettings.UseHttps || owinCtx.Request.IsSecure,
                Path     = "/"
            });

            return(true);
        }
예제 #11
0
 public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options)
 {
     options.Domain = RemoveSubdomain(context.Request.Host.Host);  //Set the Cookie Domain using the request from host
     _concreteManager.AppendResponseCookie(context, key, value, options);
 }
예제 #12
0
    private async Task <bool> ValidateSessionAsync(
        TimeSpan validateInterval,
        HttpContext httpContext,
        ICookieManager cookieManager,
        ISystemClock systemClock,
        DateTimeOffset?authTicketIssueDate,
        ClaimsIdentity?currentIdentity)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }

        if (cookieManager == null)
        {
            throw new ArgumentNullException(nameof(cookieManager));
        }

        if (systemClock == null)
        {
            throw new ArgumentNullException(nameof(systemClock));
        }

        if (currentIdentity == null)
        {
            return(false);
        }

        DateTimeOffset?issuedUtc  = null;
        DateTimeOffset currentUtc = systemClock.UtcNow;

        // read the last checked time from a custom cookie
        var lastCheckedCookie = cookieManager.GetRequestCookie(httpContext, CookieName);

        if (lastCheckedCookie.IsNullOrWhiteSpace() == false)
        {
            if (DateTimeOffset.TryParse(lastCheckedCookie, out DateTimeOffset parsed))
            {
                issuedUtc = parsed;
            }
        }

        // no cookie, use the issue time of the auth ticket
        if (issuedUtc.HasValue == false)
        {
            issuedUtc = authTicketIssueDate;
        }

        // Only validate if enough time has elapsed
        var validate = issuedUtc.HasValue == false;

        if (issuedUtc.HasValue)
        {
            TimeSpan timeElapsed = currentUtc.Subtract(issuedUtc.Value);
            validate = timeElapsed > validateInterval;
        }

        if (validate == false)
        {
            return(true);
        }

        var userId = currentIdentity.GetUserId();
        BackOfficeIdentityUser?user = await _userManager.FindByIdAsync(userId);

        if (user == null)
        {
            return(false);
        }

        var sessionId = currentIdentity.FindFirstValue(Constants.Security.SessionIdClaimType);

        if (await _userManager.ValidateSessionIdAsync(userId, sessionId) == false)
        {
            return(false);
        }

        // we will re-issue the cookie last checked cookie
        cookieManager.AppendResponseCookie(
            httpContext,
            CookieName,
            DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz"),
            new CookieOptions
        {
            HttpOnly = true,
            Secure   = _globalSettings.UseHttps || httpContext.Request.IsHttps,
            Path     = "/"
        });

        return(true);
    }
예제 #13
0
        public static async Task Apply(
            this CommandResult commandResult,
            HttpContext httpContext,
            IDataProtector dataProtector,
            ICookieManager cookieManager,
            string signInScheme,
            string signOutScheme,
            bool emitSameSiteNone)
        {
            httpContext.Response.StatusCode = (int)commandResult.HttpStatusCode;

            if (commandResult.Location != null)
            {
                httpContext.Response.Headers["Location"] = commandResult.Location.OriginalString;
            }

            if (!string.IsNullOrEmpty(commandResult.SetCookieName))
            {
                var cookieData = HttpRequestData.ConvertBinaryData(
                    dataProtector.Protect(commandResult.GetSerializedRequestState()));

                cookieManager.AppendResponseCookie(
                    httpContext,
                    commandResult.SetCookieName,
                    cookieData,
                    new CookieOptions()
                {
                    HttpOnly = true,
                    Secure   = commandResult.SetCookieSecureFlag,
                    // We are expecting a different site to POST back to us,
                    // so the ASP.Net Core default of Lax is not appropriate in this case
                    SameSite    = emitSameSiteNone ? SameSiteMode.None : (SameSiteMode)(-1),
                    IsEssential = true
                });
            }

            foreach (var h in commandResult.Headers)
            {
                httpContext.Response.Headers.Add(h.Key, h.Value);
            }

            if (!string.IsNullOrEmpty(commandResult.ClearCookieName))
            {
                cookieManager.DeleteCookie(
                    httpContext,
                    commandResult.ClearCookieName,
                    new CookieOptions
                {
                    Secure = commandResult.SetCookieSecureFlag
                });
            }

            if (!string.IsNullOrEmpty(commandResult.Content))
            {
                var buffer = Encoding.UTF8.GetBytes(commandResult.Content);
                httpContext.Response.ContentType = commandResult.ContentType;
                await httpContext.Response.Body.WriteAsync(buffer, 0, buffer.Length);
            }

            if (commandResult.Principal != null)
            {
                var authProps = new AuthenticationProperties(commandResult.RelayData)
                {
                    RedirectUri = commandResult.Location.OriginalString
                };
                await httpContext.SignInAsync(signInScheme, commandResult.Principal, authProps);
            }

            if (commandResult.TerminateLocalSession)
            {
                await httpContext.SignOutAsync(signOutScheme ?? signInScheme);
            }
        }