public void ValidateTokens_Success_AuthenticatedUserWithUsername() { // Arrange var httpContext = new Mock<HttpContext>().Object; var identity = GetAuthenticatedIdentity("the-user"); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, Username = "******", IsSessionToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock<IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(true); var config = new AntiForgeryOptions(); var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: new Mock<IClaimUidExtractor>().Object, additionalDataProvider: mockAdditionalDataProvider.Object); // Act tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken); // Assert // Nothing to assert - if we got this far, success! }
public void ChecksSSL_Validate_Throws() { // Arrange var mockHttpContext = new Mock<HttpContext>(); mockHttpContext.Setup(o => o.Request.IsHttps) .Returns(false); var config = new AntiForgeryOptions() { RequireSSL = true }; var worker = new AntiForgeryWorker( config: config, serializer: null, tokenStore: null, generator: null, validator: null, htmlEncoder: new HtmlEncoder()); // Act & assert var ex = Assert.Throws<InvalidOperationException>( () => worker.Validate(mockHttpContext.Object, cookieToken: null, formToken: null)); Assert.Equal( @"The anti-forgery system has the configuration value AntiForgeryOptions.RequireSsl = true, " + "but the current request is not an SSL request.", ex.Message); }
public void ValidateTokens_Success_AuthenticatedUserWithUsername() { // Arrange var httpContext = new Mock <HttpContext>().Object; ClaimsIdentity identity = new GenericIdentity("the-user"); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, Username = "******", IsSessionToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock <IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(true); var config = new AntiForgeryOptions(); var tokenProvider = new TokenProvider( config: config, claimUidExtractor: new Mock <IClaimUidExtractor>().Object, additionalDataProvider: mockAdditionalDataProvider.Object); // Act tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken); // Assert // Nothing to assert - if we got this far, success! }
public void ValidateTokens_Success_ClaimsBasedUser() { // Arrange var httpContext = new Mock <HttpContext>().Object; ClaimsIdentity identity = new GenericIdentity("the-user"); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, IsSessionToken = false, ClaimUid = new BinaryBlob(256) }; var mockClaimUidExtractor = new Mock <IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(identity)) .Returns(Convert.ToBase64String(fieldtoken.ClaimUid.GetData())); var config = new AntiForgeryOptions(); var tokenProvider = new TokenProvider( config: config, claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); // Act tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken); // Assert // Nothing to assert - if we got this far, success! }
public void GenerateFormToken_AuthenticatedWithoutUsernameAndNoAdditionalData_NoAdditionalData() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock <HttpContext>().Object; ClaimsIdentity identity = new MyAuthenticatedIdentityWithoutUsername(); var config = new AntiForgeryOptions(); IClaimUidExtractor claimUidExtractor = new Mock <IClaimUidExtractor>().Object; var tokenProvider = new TokenProvider( config: config, claimUidExtractor: claimUidExtractor, additionalDataProvider: null); // Act & assert var ex = Assert.Throws <InvalidOperationException>( () => tokenProvider.GenerateFormToken(httpContext, identity, cookieToken)); Assert.Equal( "The provided identity of type " + "'Microsoft.AspNet.Mvc.Core.Test.TokenProviderTest+MyAuthenticatedIdentityWithoutUsername' " + "is marked IsAuthenticated = true but does not have a value for Name. " + "By default, the anti-forgery system requires that all authenticated identities have a unique Name. " + "If it is not possible to provide a unique Name for this identity, " + "consider extending IAdditionalDataProvider by overriding the DefaultAdditionalDataProvider " + "or a custom type that can provide some form of unique identifier for the current user.", ex.Message); }
public void GenerateFormToken_AnonymousUser() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock<HttpContext>().Object; var mockIdentity = new Mock<ClaimsIdentity>(); mockIdentity.Setup(o => o.IsAuthenticated) .Returns(false); var config = new AntiForgeryOptions(); var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: null); // Act var fieldToken = tokenProvider.GenerateFormToken(httpContext, mockIdentity.Object, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsSessionToken); Assert.Empty(fieldToken.Username); Assert.Null(fieldToken.ClaimUid); Assert.Empty(fieldToken.AdditionalData); }
public void ValidateTokens_Success_AnonymousUser() { // Arrange var httpContext = new Mock <HttpContext>().Object; var identity = new ClaimsIdentity(); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, Username = String.Empty, IsSessionToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock <IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(true); var config = new AntiForgeryOptions(); var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: mockAdditionalDataProvider.Object); // Act tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken); // Assert // Nothing to assert - if we got this far, success! }
public void GenerateFormToken_AuthenticatedWithoutUsernameAndNoAdditionalData_NoAdditionalData() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock<HttpContext>().Object; ClaimsIdentity identity = new MyAuthenticatedIdentityWithoutUsername(); var config = new AntiForgeryOptions(); IClaimUidExtractor claimUidExtractor = new Mock<IClaimUidExtractor>().Object; var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: claimUidExtractor, additionalDataProvider: null); // Act & assert var ex = Assert.Throws<InvalidOperationException>( () => tokenProvider.GenerateFormToken(httpContext, identity, cookieToken)); Assert.Equal( "The provided identity of type " + "'Microsoft.AspNet.Mvc.Core.Test.TokenProviderTest+MyAuthenticatedIdentityWithoutUsername' " + "is marked IsAuthenticated = true but does not have a value for Name. " + "By default, the anti-forgery system requires that all authenticated identities have a unique Name. " + "If it is not possible to provide a unique Name for this identity, " + "consider extending IAdditionalDataProvider by overriding the DefaultAdditionalDataProvider " + "or a custom type that can provide some form of unique identifier for the current user.", ex.Message); }
public async Task ChecksSSL_ValidateAsync_Throws() { // Arrange var mockHttpContext = new Mock<HttpContext>(); mockHttpContext.Setup(o => o.Request.IsSecure) .Returns(false); var config = new AntiForgeryOptions() { RequireSSL = true }; var worker = new AntiForgeryWorker( config: config, serializer: null, tokenStore: null, generator: null, validator: null); // Act & assert var ex = await Assert.ThrowsAsync<InvalidOperationException>( async () => await worker.ValidateAsync(mockHttpContext.Object)); Assert.Equal( @"The anti-forgery system has the configuration value AntiForgeryOptions.RequireSsl = true, " + "but the current request is not an SSL request.", ex.Message); }
public async Task ChecksSSL_ValidateAsync_Throws() { // Arrange var mockHttpContext = new Mock <HttpContext>(); mockHttpContext.Setup(o => o.Request.IsHttps) .Returns(false); var config = new AntiForgeryOptions() { RequireSSL = true }; var worker = new AntiForgeryWorker( config: config, serializer: null, tokenStore: null, generator: null, validator: null, htmlEncoder: new HtmlEncoder()); // Act & assert var ex = await Assert.ThrowsAsync <InvalidOperationException>( async() => await worker.ValidateAsync(mockHttpContext.Object)); Assert.Equal( @"The anti-forgery system has the configuration value AntiForgeryOptions.RequireSsl = true, " + "but the current request is not an SSL request.", ex.Message); }
public void GetCookieToken_CookieIsMissingInRequest_LooksUpCookieInAntiForgeryContext() { // Arrange var requestCookies = new Mock<IReadableStringCollection>(); requestCookies .Setup(o => o.Get(It.IsAny<string>())) .Returns(string.Empty); var mockHttpContext = new Mock<HttpContext>(); mockHttpContext .Setup(o => o.Request.Cookies) .Returns(requestCookies.Object); var contextAccessor = new ScopedInstance<AntiForgeryContext>(); mockHttpContext.SetupGet(o => o.RequestServices) .Returns(GetServiceProvider(contextAccessor)); // add a cookie explicitly. var cookie = new AntiForgeryToken(); contextAccessor.Value = new AntiForgeryContext() { CookieToken = cookie }; var config = new AntiForgeryOptions() { CookieName = _cookieName }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = tokenStore.GetCookieToken(mockHttpContext.Object); // Assert Assert.Equal(cookie, token); }
private AntiForgeryWorkerContext GetAntiForgeryWorkerContext( AntiForgeryOptions config, bool useOldCookie = false, bool isOldCookieValid = true) { // Arrange var mockHttpContext = GetHttpContext(); var testTokenSet = GetTokenSet(isOldCookieTokenSessionToken: true, isNewCookieSessionToken: true); var mockSerializer = GetTokenSerializer(testTokenSet); var mockTokenStore = GetTokenStore(mockHttpContext.Object, testTokenSet); var mockTokenProvider = GetTokenProvider( mockHttpContext.Object, testTokenSet, useOldCookie: useOldCookie, isOldCookieValid: isOldCookieValid); return(new AntiForgeryWorkerContext() { Options = config, HttpContext = mockHttpContext, TokenProvider = mockTokenProvider, TokenSerializer = mockSerializer, TokenStore = mockTokenStore, TestTokenSet = testTokenSet }); }
public void GetFormInputElement_ExistingInvalidCookieToken_SwallowsExceptions() { // Arrange var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; // Make sure the existing cookie is invalid. var context = GetAntiForgeryWorkerContext(config, isOldCookieValid: false); var worker = GetAntiForgeryWorker(context); // This will cause the cookieToken to be null. context.TokenStore.Setup(o => o.GetCookieToken(context.HttpContext.Object)) .Throws(new Exception("should be swallowed")); // Setup so that the null cookie token returned is treated as invalid. context.TokenProvider.Setup(o => o.IsCookieTokenValid(null)) .Returns(false); // Act var inputElement = worker.GetFormInputElement(context.HttpContext.Object); // Assert Assert.Equal(@"<input name=""form-field-name"" type=""hidden"" value=""serialized-form-token"" />", inputElement.ToString(TagRenderMode.SelfClosing)); context.TokenStore.Verify(); }
public void ValidateTokens_AdditionalDataRejected() { // Arrange var httpContext = new Mock <HttpContext>().Object; ClaimsIdentity identity = new GenericIdentity(String.Empty); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, Username = String.Empty, IsSessionToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock <IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(false); var config = new AntiForgeryOptions(); var tokenProvider = new TokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: mockAdditionalDataProvider.Object); // Act & assert var ex = Assert.Throws <InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken)); Assert.Equal(@"The provided anti-forgery token failed a custom data check.", ex.Message); }
public void GetCookieToken_CookieIsValid_ReturnsToken() { // Arrange var expectedToken = new AntiForgeryToken(); var mockHttpContext = GetMockHttpContext(_cookieName, "valid-value"); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var mockSerializer = new Mock <IAntiForgeryTokenSerializer>(); mockSerializer .Setup(o => o.Deserialize("valid-value")) .Returns(expectedToken); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act AntiForgeryToken retVal = tokenStore.GetCookieToken(mockHttpContext); // Assert Assert.Same(expectedToken, retVal); }
public void GetCookieToken_CookieDoesNotExist_ReturnsNull() { // Arrange var requestCookies = new Mock<IReadableStringCollection>(); requestCookies .Setup(o => o.Get(It.IsAny<string>())) .Returns(string.Empty); var mockHttpContext = new Mock<HttpContext>(); mockHttpContext .Setup(o => o.Request.Cookies) .Returns(requestCookies.Object); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = tokenStore.GetCookieToken(mockHttpContext.Object); // Assert Assert.Null(token); }
public void GenerateFormToken_AuthenticatedWithoutUsername_WithAdditionalData() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock <HttpContext>().Object; ClaimsIdentity identity = new MyAuthenticatedIdentityWithoutUsername(); var mockAdditionalDataProvider = new Mock <IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.GetAdditionalData(httpContext)) .Returns("additional-data"); var config = new AntiForgeryOptions(); IClaimUidExtractor claimUidExtractor = new Mock <IClaimUidExtractor>().Object; var tokenProvider = new TokenProvider( config: config, claimUidExtractor: claimUidExtractor, additionalDataProvider: mockAdditionalDataProvider.Object); // Act var fieldToken = tokenProvider.GenerateFormToken(httpContext, identity, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsSessionToken); Assert.Equal("", fieldToken.Username); Assert.Equal(null, fieldToken.ClaimUid); Assert.Equal("additional-data", fieldToken.AdditionalData); }
public void GenerateFormToken_AnonymousUser() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock <HttpContext>().Object; var mockIdentity = new Mock <ClaimsIdentity>(); mockIdentity.Setup(o => o.IsAuthenticated) .Returns(false); var config = new AntiForgeryOptions(); var tokenProvider = new TokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: null); // Act var fieldToken = tokenProvider.GenerateFormToken(httpContext, mockIdentity.Object, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsSessionToken); Assert.Equal("", fieldToken.Username); Assert.Equal(null, fieldToken.ClaimUid); Assert.Equal("", fieldToken.AdditionalData); }
public void ValidateTokens_FieldTokenMissing() { // Arrange var httpContext = new Mock <HttpContext>().Object; ClaimsIdentity identity = new Mock <ClaimsIdentity>().Object; var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; AntiForgeryToken fieldtoken = null; var config = new AntiForgeryOptions() { FormFieldName = "my-form-field-name" }; var tokenProvider = new TokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: null); // Act & assert var ex = Assert.Throws <InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken)); Assert.Equal(@"The required anti-forgery form field ""my-form-field-name"" is not present.", ex.Message); }
public async Task GetFormToken_FormFieldIsEmpty_ReturnsNull() { // Arrange var mockHttpContext = new Mock <HttpContext>(); var requestContext = new Mock <HttpRequest>(); var formCollection = new Mock <IFormCollection>(); formCollection.Setup(f => f["form-field-name"]).Returns(string.Empty); requestContext.Setup(o => o.ReadFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formCollection.Object)); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = await tokenStore.GetFormTokenAsync(mockHttpContext.Object); // Assert Assert.Null(token); }
public async Task GetFormToken_FormFieldIsEmpty_ReturnsNull() { // Arrange var mockHttpContext = new Mock <HttpContext>(); var requestContext = new Mock <HttpRequest>(); IReadableStringCollection formsCollection = new MockCookieCollection(new Dictionary <string, string>() { { "form-field-name", string.Empty } }); requestContext.Setup(o => o.GetFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formsCollection)); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = await tokenStore.GetFormTokenAsync(mockHttpContext.Object); // Assert Assert.Null(token); }
public void GetCookieToken_CookieDoesNotExist_ReturnsNull() { // Arrange var requestCookies = new Mock <IReadableStringCollection>(); requestCookies .Setup(o => o.Get(It.IsAny <string>())) .Returns(string.Empty); var mockHttpContext = new Mock <HttpContext>(); mockHttpContext .Setup(o => o.Request.Cookies) .Returns(requestCookies.Object); var contextAccessor = new ContextAccessor <AntiForgeryContext>(); mockHttpContext.SetupGet(o => o.RequestServices) .Returns(GetServiceProvider(contextAccessor)); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = tokenStore.GetCookieToken(mockHttpContext.Object); // Assert Assert.Null(token); }
public void GetCookieToken_CookieIsInvalid_PropagatesException() { // Arrange var mockHttpContext = GetMockHttpContext(_cookieName, "invalid-value"); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var expectedException = new InvalidOperationException("some exception"); var mockSerializer = new Mock <IAntiForgeryTokenSerializer>(); mockSerializer .Setup(o => o.Deserialize("invalid-value")) .Throws(expectedException); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act & assert var ex = Assert.Throws <InvalidOperationException>(() => tokenStore.GetCookieToken(mockHttpContext)); Assert.Same(expectedException, ex); }
public void ChecksSSL_GetFormInputElement_Throws() { // Arrange var mockHttpContext = new Mock <HttpContext>(); mockHttpContext.Setup(o => o.Request.IsSecure) .Returns(false); var config = new AntiForgeryOptions() { RequireSSL = true }; var worker = new AntiForgeryWorker( config: config, serializer: null, tokenStore: null, generator: null, validator: null); // Act & assert var ex = Assert.Throws <InvalidOperationException>(() => worker.GetFormInputElement(mockHttpContext.Object)); Assert.Equal( @"The anti-forgery system has the configuration value AntiForgeryOptions.RequireSsl = true, " + "but the current request is not an SSL request.", ex.Message); }
public void FormFieldName_SettingNullValue_Throws() { // Arrange var options = new AntiForgeryOptions(); // Act & Assert var ex = Assert.Throws<ArgumentNullException>(() => options.FormFieldName = null); Assert.Equal("The 'FormFieldName' property of 'Microsoft.AspNet.Mvc.AntiForgeryOptions' must not be null." + Environment.NewLine + "Parameter name: value", ex.Message); }
public void FormFieldName_SettingNullValue_Throws() { // Arrange var options = new AntiForgeryOptions(); // Act & Assert var ex = Assert.Throws <ArgumentNullException>(() => options.FormFieldName = null); Assert.Equal("The 'FormFieldName' property of 'Microsoft.AspNet.Mvc.AntiForgeryOptions' must not be null." + Environment.NewLine + "Parameter name: value", ex.Message); }
/// <summary> /// Configures the anti-forgery tokens for better security. See: /// http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages /// </summary> /// <param name="antiForgeryOptions">The anti-forgery token options.</param> private static void ConfigureAntiforgeryTokens(AntiForgeryOptions antiForgeryOptions) { // Rename the Anti-Forgery cookie from "__RequestVerificationToken" to "f". This adds a little security // through obscurity and also saves sending a few characters over the wire. antiForgeryOptions.CookieName = "f"; // Rename the form input name from "__RequestVerificationToken" to "f" for the same reason above e.g. // <input name="__RequestVerificationToken" type="hidden" value="..." /> antiForgeryOptions.FormFieldName = "f"; // If you have enabled SSL/TLS. Uncomment this line to ensure that the Anti-Forgery cookie requires SSL/TLS // to be sent across the wire. // antiForgeryOptions.RequireSSL = true; }
public void SaveCookieToken(bool requireSsl, bool?expectedCookieSecureFlag) { // Arrange var token = new AntiForgeryToken(); var mockCookies = new Mock <IResponseCookies>(); // TODO : Once we decide on where to pick this value from enable this. bool defaultCookieSecureValue = expectedCookieSecureFlag ?? false; // pulled from config; set by ctor var cookies = new MockResponseCookieCollection(); cookies.Count = 0; var mockHttpContext = new Mock <HttpContext>(); mockHttpContext.Setup(o => o.Response.Cookies) .Returns(cookies); var contextAccessor = new ContextAccessor <AntiForgeryContext>(); mockHttpContext.SetupGet(o => o.RequestServices) .Returns(GetServiceProvider(contextAccessor)); var mockSerializer = new Mock <IAntiForgeryTokenSerializer>(); mockSerializer.Setup(o => o.Serialize(token)) .Returns("serialized-value"); var config = new AntiForgeryOptions() { CookieName = _cookieName, RequireSSL = requireSsl }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act tokenStore.SaveCookieToken(mockHttpContext.Object, token); // Assert Assert.Equal(1, cookies.Count); Assert.NotNull(contextAccessor.Value.CookieToken); Assert.NotNull(cookies); Assert.Equal(_cookieName, cookies.Key); Assert.Equal("serialized-value", cookies.Value); Assert.True(cookies.Options.HttpOnly); Assert.Equal(defaultCookieSecureValue, cookies.Options.Secure); }
public void ValidateTokens_FieldAndSessionTokensSwapped() { // Arrange var httpContext = new Mock <HttpContext>().Object; ClaimsIdentity identity = new Mock <ClaimsIdentity>().Object; var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { IsSessionToken = false }; var config = new AntiForgeryOptions() { CookieName = "my-cookie-name", FormFieldName = "my-form-field-name" }; var tokenProvider = new TokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: null); // Act & assert var ex1 = Assert.Throws <InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, fieldtoken, fieldtoken)); Assert.Equal( "Validation of the provided anti-forgery token failed. " + @"The cookie ""my-cookie-name"" and the form field ""my-form-field-name"" were swapped.", ex1.Message); var ex2 = Assert.Throws <InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, sessionToken, sessionToken)); Assert.Equal( "Validation of the provided anti-forgery token failed. " + @"The cookie ""my-cookie-name"" and the form field ""my-form-field-name"" were swapped.", ex2.Message); }
public void GetFormInputElement_ExistingValidCookieToken_GeneratesAnAntiForgeryToken() { // Arrange var options = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; // Make sure the existing cookie is valid and use the same cookie for the mock Token Provider. var context = GetAntiForgeryWorkerContext(options, useOldCookie: true, isOldCookieValid: true); var worker = GetAntiForgeryWorker(context); // Act var inputElement = worker.GetFormInputElement(context.HttpContext.Object); // Assert Assert.Equal(@"<input name=""form-field-name"" type=""hidden"" value=""serialized-form-token"" />", inputElement.ToString(TagRenderMode.SelfClosing)); }
public async Task GetFormToken_FormFieldIsInvalid_PropagatesException() { // Arrange IReadableStringCollection formsCollection = new MockCookieCollection(new Dictionary <string, string>() { { "form-field-name", "invalid-value" } }); var requestContext = new Mock <HttpRequest>(); requestContext.Setup(o => o.GetFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formsCollection)); var mockHttpContext = new Mock <HttpContext>(); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var expectedException = new InvalidOperationException("some exception"); var mockSerializer = new Mock <IAntiForgeryTokenSerializer>(); mockSerializer.Setup(o => o.Deserialize("invalid-value")) .Throws(expectedException); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act & assert var ex = await Assert.ThrowsAsync <InvalidOperationException>( async() => await tokenStore.GetFormTokenAsync(mockHttpContext.Object)); Assert.Same(expectedException, ex); }
public void GetFormInputElement_ExistingInvalidCookieToken_GeneratesANewCookieAndAnAntiForgeryToken() { // Arrange var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; // Make sure the existing cookie is invalid. var context = GetAntiForgeryWorkerContext(config, isOldCookieValid: false); var worker = GetAntiForgeryWorker(context); // Act var inputElement = worker.GetFormInputElement(context.HttpContext.Object); // Assert Assert.Equal(@"<input name=""form-field-name"" type=""hidden"" value=""serialized-form-token"" />", inputElement.ToString(TagRenderMode.SelfClosing)); context.TokenStore.Verify(); }
public void GetCookieToken_CookieIsEmpty_ReturnsNull() { // Arrange var mockHttpContext = GetMockHttpContext(_cookieName, string.Empty); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = tokenStore.GetCookieToken(mockHttpContext); // Assert Assert.Null(token); }
public void SetCookieTokenAndHeader_AddsXFrameOptionsHeader(bool suppressXFrameOptions, string expectedHeaderValue) { // Arrange var options = new AntiForgeryOptions() { SuppressXFrameOptionsHeader = suppressXFrameOptions }; // Genreate a new cookie. var context = GetAntiForgeryWorkerContext(options, useOldCookie: false, isOldCookieValid: false); var worker = GetAntiForgeryWorker(context); // Act worker.SetCookieTokenAndHeader(context.HttpContext.Object); // Assert var xFrameOptions = context.HttpContext.Object.Response.Headers["X-Frame-Options"]; Assert.Equal(expectedHeaderValue, xFrameOptions); }
public void GenerateFormToken_ClaimsBasedIdentity() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock <HttpContext>().Object; var identity = GetAuthenticatedIdentity("some-identity"); var config = new AntiForgeryOptions(); byte[] data = new byte[256 / 8]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(data); } var base64ClaimUId = Convert.ToBase64String(data); var expectedClaimUid = new BinaryBlob(256, data); var mockClaimUidExtractor = new Mock <IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(identity)) .Returns(base64ClaimUId); var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); // Act var fieldToken = tokenProvider.GenerateFormToken(httpContext, identity, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsSessionToken); Assert.Equal("", fieldToken.Username); Assert.Equal(expectedClaimUid, fieldToken.ClaimUid); Assert.Equal("", fieldToken.AdditionalData); }
public void GetCookieToken_CookieIsMissingInRequest_LooksUpCookieInAntiForgeryContext() { // Arrange var requestCookies = new Mock <IReadableStringCollection>(); requestCookies .Setup(o => o.Get(It.IsAny <string>())) .Returns(string.Empty); var mockHttpContext = new Mock <HttpContext>(); mockHttpContext .Setup(o => o.Request.Cookies) .Returns(requestCookies.Object); var contextAccessor = new ContextAccessor <AntiForgeryContext>(); mockHttpContext.SetupGet(o => o.RequestServices) .Returns(GetServiceProvider(contextAccessor)); // add a cookie explicitly. var cookie = new AntiForgeryToken(); contextAccessor.SetValue(new AntiForgeryContext() { CookieToken = cookie }); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = tokenStore.GetCookieToken(mockHttpContext.Object); // Assert Assert.Equal(cookie, token); }
public async Task GetFormToken_FormFieldIsValid_ReturnsToken() { // Arrange var expectedToken = new AntiForgeryToken(); // Arrange var mockHttpContext = new Mock <HttpContext>(); var requestContext = new Mock <HttpRequest>(); IReadableStringCollection formsCollection = new MockCookieCollection(new Dictionary <string, string>() { { "form-field-name", "valid-value" } }); requestContext.Setup(o => o.GetFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formsCollection)); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var mockSerializer = new Mock <IAntiForgeryTokenSerializer>(); mockSerializer.Setup(o => o.Deserialize("valid-value")) .Returns(expectedToken); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act var retVal = await tokenStore.GetFormTokenAsync(mockHttpContext.Object); // Assert Assert.Same(expectedToken, retVal); }
public void GetCookieToken_CookieIsInvalid_PropagatesException() { // Arrange var mockHttpContext = GetMockHttpContext(_cookieName, "invalid-value"); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var expectedException = new InvalidOperationException("some exception"); var mockSerializer = new Mock<IAntiForgeryTokenSerializer>(); mockSerializer .Setup(o => o.Deserialize("invalid-value")) .Throws(expectedException); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act & assert var ex = Assert.Throws<InvalidOperationException>(() => tokenStore.GetCookieToken(mockHttpContext)); Assert.Same(expectedException, ex); }
private AntiForgeryWorkerContext GetAntiForgeryWorkerContext(AntiForgeryOptions config, bool useOldCookie = false, bool isOldCookieValid = true) { // Arrange var mockHttpContext = GetHttpContext(); var testTokenSet = GetTokenSet(isOldCookieTokenSessionToken: true, isNewCookieSessionToken: true); var mockSerializer = GetTokenSerializer(testTokenSet); var mockTokenStore = GetTokenStore(mockHttpContext.Object, testTokenSet); var mockTokenProvider = GetTokenProvider(mockHttpContext.Object, testTokenSet, useOldCookie: useOldCookie, isOldCookieValid: isOldCookieValid); return new AntiForgeryWorkerContext() { Options = config, HttpContext = mockHttpContext, TokenProvider = mockTokenProvider, TokenSerializer = mockSerializer, TokenStore = mockTokenStore, TestTokenSet = testTokenSet }; }
public async Task GetFormToken_FormFieldIsEmpty_ReturnsNull() { // Arrange var mockHttpContext = new Mock<HttpContext>(); var requestContext = new Mock<HttpRequest>(); var formCollection = new Mock<IFormCollection>(); formCollection.Setup(f => f["form-field-name"]).Returns(string.Empty); requestContext.Setup(o => o.ReadFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formCollection.Object)); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = await tokenStore.GetFormTokenAsync(mockHttpContext.Object); // Assert Assert.Null(token); }
public void ValidateTokens_Success_AnonymousUser() { // Arrange var httpContext = new Mock<HttpContext>().Object; var identity = new ClaimsIdentity(); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, Username = String.Empty, IsSessionToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock<IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(true); var config = new AntiForgeryOptions(); var tokenProvider = new TokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: mockAdditionalDataProvider.Object); // Act tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken); // Assert // Nothing to assert - if we got this far, success! }
public void GetCookieToken_CookieIsValid_ReturnsToken() { // Arrange var expectedToken = new AntiForgeryToken(); var mockHttpContext = GetMockHttpContext(_cookieName, "valid-value"); var config = new AntiForgeryOptions() { CookieName = _cookieName }; var mockSerializer = new Mock<IAntiForgeryTokenSerializer>(); mockSerializer .Setup(o => o.Deserialize("valid-value")) .Returns(expectedToken); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act AntiForgeryToken retVal = tokenStore.GetCookieToken(mockHttpContext); // Assert Assert.Same(expectedToken, retVal); }
public void ValidateTokens_FieldTokenMissing() { // Arrange var httpContext = new Mock<HttpContext>().Object; ClaimsIdentity identity = new Mock<ClaimsIdentity>().Object; var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; AntiForgeryToken fieldtoken = null; var config = new AntiForgeryOptions() { FormFieldName = "my-form-field-name" }; var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: null); // Act & assert var ex = Assert.Throws<InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken)); Assert.Equal(@"The required anti-forgery form field ""my-form-field-name"" is not present.", ex.Message); }
public void GenerateFormToken_ClaimsBasedIdentity() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock<HttpContext>().Object; var identity = GetAuthenticatedIdentity("some-identity"); var config = new AntiForgeryOptions(); byte[] data = new byte[256 / 8]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(data); } var base64ClaimUId = Convert.ToBase64String(data); var expectedClaimUid = new BinaryBlob(256, data); var mockClaimUidExtractor = new Mock<IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(identity)) .Returns(base64ClaimUId); var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); // Act var fieldToken = tokenProvider.GenerateFormToken(httpContext, identity, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsSessionToken); Assert.Equal("", fieldToken.Username); Assert.Equal(expectedClaimUid, fieldToken.ClaimUid); Assert.Equal("", fieldToken.AdditionalData); }
public void SaveCookieToken(bool requireSsl, bool? expectedCookieSecureFlag) { // Arrange var token = new AntiForgeryToken(); var mockCookies = new Mock<IResponseCookies>(); // TODO : Once we decide on where to pick this value from enable this. bool defaultCookieSecureValue = expectedCookieSecureFlag ?? false; // pulled from config; set by ctor var cookies = new MockResponseCookieCollection(); cookies.Count = 0; var mockHttpContext = new Mock<HttpContext>(); mockHttpContext.Setup(o => o.Response.Cookies) .Returns(cookies); var mockSerializer = new Mock<IAntiForgeryTokenSerializer>(); mockSerializer.Setup(o => o.Serialize(token)) .Returns("serialized-value"); var config = new AntiForgeryOptions() { CookieName = _cookieName, RequireSSL = requireSsl }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act tokenStore.SaveCookieToken(mockHttpContext.Object, token); // Assert Assert.Equal(1, cookies.Count); Assert.NotNull(cookies); Assert.Equal(_cookieName, cookies.Key); Assert.Equal("serialized-value", cookies.Value); Assert.True(cookies.Options.HttpOnly); Assert.Equal(defaultCookieSecureValue, cookies.Options.Secure); }
public void ValidateTokens_FieldAndSessionTokensSwapped() { // Arrange var httpContext = new Mock<HttpContext>().Object; ClaimsIdentity identity = new Mock<ClaimsIdentity>().Object; var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { IsSessionToken = false }; var config = new AntiForgeryOptions() { CookieName = "my-cookie-name", FormFieldName = "my-form-field-name" }; var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: null); // Act & assert var ex1 = Assert.Throws<InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, fieldtoken, fieldtoken)); Assert.Equal( "Validation of the provided anti-forgery token failed. " + @"The cookie ""my-cookie-name"" and the form field ""my-form-field-name"" were swapped.", ex1.Message); var ex2 = Assert.Throws<InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, sessionToken, sessionToken)); Assert.Equal( "Validation of the provided anti-forgery token failed. " + @"The cookie ""my-cookie-name"" and the form field ""my-form-field-name"" were swapped.", ex2.Message); }
public async Task GetFormToken_FormFieldIsValid_ReturnsToken() { // Arrange var expectedToken = new AntiForgeryToken(); // Arrange var mockHttpContext = new Mock<HttpContext>(); var requestContext = new Mock<HttpRequest>(); IReadableStringCollection formsCollection = new MockCookieCollection(new Dictionary<string, string>() { { "form-field-name", "valid-value" } }); requestContext.Setup(o => o.GetFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formsCollection)); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var mockSerializer = new Mock<IAntiForgeryTokenSerializer>(); mockSerializer.Setup(o => o.Deserialize("valid-value")) .Returns(expectedToken); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act var retVal = await tokenStore.GetFormTokenAsync(mockHttpContext.Object); // Assert Assert.Same(expectedToken, retVal); }
public void ValidateTokens_AdditionalDataRejected() { // Arrange var httpContext = new Mock<HttpContext>().Object; var identity = new ClaimsIdentity(); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, Username = String.Empty, IsSessionToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock<IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(false); var config = new AntiForgeryOptions(); var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: null, additionalDataProvider: mockAdditionalDataProvider.Object); // Act & assert var ex = Assert.Throws<InvalidOperationException>( () => tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken)); Assert.Equal(@"The provided anti-forgery token failed a custom data check.", ex.Message); }
public async Task GetFormToken_FormFieldIsInvalid_PropagatesException() { // Arrange IReadableStringCollection formsCollection = new MockCookieCollection(new Dictionary<string, string>() { { "form-field-name", "invalid-value" } }); var requestContext = new Mock<HttpRequest>(); requestContext.Setup(o => o.GetFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formsCollection)); var mockHttpContext = new Mock<HttpContext>(); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var expectedException = new InvalidOperationException("some exception"); var mockSerializer = new Mock<IAntiForgeryTokenSerializer>(); mockSerializer.Setup(o => o.Deserialize("invalid-value")) .Throws(expectedException); var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act & assert var ex = await Assert.ThrowsAsync<InvalidOperationException>( async () => await tokenStore.GetFormTokenAsync(mockHttpContext.Object)); Assert.Same(expectedException, ex); }
public void ValidateTokens_Success_ClaimsBasedUser() { // Arrange var httpContext = new Mock<HttpContext>().Object; var identity = GetAuthenticatedIdentity("the-user"); var sessionToken = new AntiForgeryToken() { IsSessionToken = true }; var fieldtoken = new AntiForgeryToken() { SecurityToken = sessionToken.SecurityToken, IsSessionToken = false, ClaimUid = new BinaryBlob(256) }; var mockClaimUidExtractor = new Mock<IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(identity)) .Returns(Convert.ToBase64String(fieldtoken.ClaimUid.GetData())); var config = new AntiForgeryOptions(); var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); // Act tokenProvider.ValidateTokens(httpContext, identity, sessionToken, fieldtoken); // Assert // Nothing to assert - if we got this far, success! }
public async Task GetFormToken_FormFieldIsEmpty_ReturnsNull() { // Arrange var mockHttpContext = new Mock<HttpContext>(); var requestContext = new Mock<HttpRequest>(); IReadableStringCollection formsCollection = new MockCookieCollection(new Dictionary<string, string>() { { "form-field-name", string.Empty } }); requestContext.Setup(o => o.GetFormAsync(CancellationToken.None)) .Returns(Task.FromResult(formsCollection)); mockHttpContext.Setup(o => o.Request) .Returns(requestContext.Object); var config = new AntiForgeryOptions() { FormFieldName = "form-field-name" }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: null); // Act var token = await tokenStore.GetFormTokenAsync(mockHttpContext.Object); // Assert Assert.Null(token); }
public void GenerateFormToken_AuthenticatedWithoutUsername_WithAdditionalData() { // Arrange var cookieToken = new AntiForgeryToken() { IsSessionToken = true }; var httpContext = new Mock<HttpContext>().Object; ClaimsIdentity identity = new MyAuthenticatedIdentityWithoutUsername(); var mockAdditionalDataProvider = new Mock<IAntiForgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.GetAdditionalData(httpContext)) .Returns("additional-data"); var config = new AntiForgeryOptions(); IClaimUidExtractor claimUidExtractor = new Mock<IClaimUidExtractor>().Object; var tokenProvider = new AntiForgeryTokenProvider( config: config, claimUidExtractor: claimUidExtractor, additionalDataProvider: mockAdditionalDataProvider.Object); // Act var fieldToken = tokenProvider.GenerateFormToken(httpContext, identity, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsSessionToken); Assert.Empty(fieldToken.Username); Assert.Null(fieldToken.ClaimUid); Assert.Equal("additional-data", fieldToken.AdditionalData); }
public void SaveCookieToken(bool requireSsl, bool? expectedCookieSecureFlag) { // Arrange var token = new AntiForgeryToken(); var mockCookies = new Mock<IResponseCookies>(); bool defaultCookieSecureValue = expectedCookieSecureFlag ?? false; // pulled from config; set by ctor var cookies = new MockResponseCookieCollection(); cookies.Count = 0; var mockHttpContext = new Mock<HttpContext>(); mockHttpContext.Setup(o => o.Response.Cookies) .Returns(cookies); var contextAccessor = new ScopedInstance<AntiForgeryContext>(); mockHttpContext.SetupGet(o => o.RequestServices) .Returns(GetServiceProvider(contextAccessor)); var mockSerializer = new Mock<IAntiForgeryTokenSerializer>(); mockSerializer.Setup(o => o.Serialize(token)) .Returns("serialized-value"); var config = new AntiForgeryOptions() { CookieName = _cookieName, RequireSSL = requireSsl }; var tokenStore = new AntiForgeryTokenStore( config: config, serializer: mockSerializer.Object); // Act tokenStore.SaveCookieToken(mockHttpContext.Object, token); // Assert Assert.Equal(1, cookies.Count); Assert.NotNull(contextAccessor.Value.CookieToken); Assert.NotNull(cookies); Assert.Equal(_cookieName, cookies.Key); Assert.Equal("serialized-value", cookies.Value); Assert.True(cookies.Options.HttpOnly); Assert.Equal(defaultCookieSecureValue, cookies.Options.Secure); }