public void GenerateRequestToken_AnonymousUser() { // Arrange var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); Assert.False(httpContext.User.Identity.IsAuthenticated); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: null); // Act var fieldToken = tokenProvider.GenerateRequestToken(httpContext, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsCookieToken); Assert.Empty(fieldToken.Username); Assert.Null(fieldToken.ClaimUid); Assert.Empty(fieldToken.AdditionalData); }
public void GenerateRequestToken_RegularUserWithUsername() { // Arrange var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var httpContext = new DefaultHttpContext(); var mockIdentity = new Mock <ClaimsIdentity>(); mockIdentity.Setup(o => o.IsAuthenticated) .Returns(true); mockIdentity.Setup(o => o.Name) .Returns("my-username"); httpContext.User = new ClaimsPrincipal(mockIdentity.Object); var claimUidExtractor = new Mock <IClaimUidExtractor>().Object; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: claimUidExtractor, additionalDataProvider: null); // Act var fieldToken = tokenProvider.GenerateRequestToken(httpContext, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsCookieToken); Assert.Equal("my-username", fieldToken.Username); Assert.Null(fieldToken.ClaimUid); Assert.Empty(fieldToken.AdditionalData); }
public void TryValidateTokenSet_FieldAndCookieTokensSwapped_CookieDuplicated() { // Arrange var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var fieldtoken = new AntiforgeryToken() { IsCookieToken = false }; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: null); string expectedMessage = "Validation of the provided antiforgery token failed. " + "The cookie token and the request token were swapped."; // Act string message; var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, cookieToken, out message); // Assert Assert.False(result); Assert.Equal(expectedMessage, message); }
public void GenerateRequestToken_AuthenticatedWithoutUsernameAndNoAdditionalData_NoAdditionalData() { // Arrange var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new MyAuthenticatedIdentityWithoutUsername()); var options = new AntiforgeryOptions(); var claimUidExtractor = new Mock <IClaimUidExtractor>().Object; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: claimUidExtractor, additionalDataProvider: null); // Act & assert var exception = Assert.Throws <InvalidOperationException>( () => tokenProvider.GenerateRequestToken(httpContext, cookieToken)); Assert.Equal( "The provided identity of type " + $"'{typeof(MyAuthenticatedIdentityWithoutUsername).FullName}' " + "is marked IsAuthenticated = true but does not have a value for Name. " + "By default, the antiforgery 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 IAntiforgeryAdditionalDataProvider by overriding the " + "DefaultAntiforgeryAdditionalDataProvider " + "or a custom type that can provide some form of unique identifier for the current user.", exception.Message); }
private void DeserializeTokens( HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet, out AntiforgeryToken cookieToken, out AntiforgeryToken requestToken) { var antiforgeryFeature = GetAntiforgeryFeature(httpContext); if (antiforgeryFeature.HaveDeserializedCookieToken) { cookieToken = antiforgeryFeature.CookieToken !; } else { cookieToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.CookieToken !); antiforgeryFeature.CookieToken = cookieToken; antiforgeryFeature.HaveDeserializedCookieToken = true; } if (antiforgeryFeature.HaveDeserializedRequestToken) { requestToken = antiforgeryFeature.RequestToken !; } else { requestToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.RequestToken !); antiforgeryFeature.RequestToken = requestToken; antiforgeryFeature.HaveDeserializedRequestToken = true; } }
public void GenerateRequestToken_AuthenticatedWithoutUsername_WithAdditionalData() { // Arrange var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new MyAuthenticatedIdentityWithoutUsername()); var mockAdditionalDataProvider = new Mock <IAntiforgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.GetAdditionalData(httpContext)) .Returns("additional-data"); var claimUidExtractor = new Mock <IClaimUidExtractor>().Object; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: claimUidExtractor, additionalDataProvider: mockAdditionalDataProvider.Object); // Act var fieldToken = tokenProvider.GenerateRequestToken(httpContext, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsCookieToken); Assert.Empty(fieldToken.Username); Assert.Null(fieldToken.ClaimUid); Assert.Equal("additional-data", fieldToken.AdditionalData); }
public void Serialize_FieldToken_WithClaimUid_TokenRoundTripSuccessful() { // Arrange var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool); //"01" // Version //+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken //+ "00" // IsCookieToken //+ "01" // IsClaimsBased //+ "6F1648E97249AA58754036A67E248CF044F07ECFB0ED387556CE029A4F9A40E0" // ClaimUid //+ "05" // AdditionalData length header //+ "E282AC3437"; // AdditionalData ("€47") as UTF8 var token = new AntiforgeryToken() { SecurityToken = _securityToken, IsCookieToken = false, ClaimUid = _claimUid, AdditionalData = "€47" }; // Act var actualSerializedData = testSerializer.Serialize(token); var deserializedToken = testSerializer.Deserialize(actualSerializedData); // Assert AssertTokensEqual(token, deserializedToken); _dataProtector.Verify(); }
public void Serialize_FieldToken_WithUsername_TokenRoundTripSuccessful() { // Arrange var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool); //"01" // Version //+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken //+ "00" // IsCookieToken //+ "00" // IsClaimsBased //+ "08" // Username length header //+ "4AC3A972C3B46D65" // Username ("Jérôme") as UTF8 //+ "05" // AdditionalData length header //+ "E282AC3437"; // AdditionalData ("€47") as UTF8 var token = new AntiforgeryToken() { SecurityToken = _securityToken, IsCookieToken = false, Username = "******", AdditionalData = "€47" }; // Act var actualSerializedData = testSerializer.Serialize(token); var deserializedToken = testSerializer.Deserialize(actualSerializedData); // Assert AssertTokensEqual(token, deserializedToken); _dataProtector.Verify(); }
public void TryValidateTokenSet_FieldAndCookieTokensHaveDifferentSecurityKeys() { // Arrange var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var fieldtoken = new AntiforgeryToken() { IsCookieToken = false }; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: null); string expectedMessage = "The antiforgery cookie token and request token do not match."; // Act string message; var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message); // Assert Assert.False(result); Assert.Equal(expectedMessage, message); }
private static void AssertTokensEqual(AntiforgeryToken expected, AntiforgeryToken actual) { Assert.NotNull(expected); Assert.NotNull(actual); Assert.Equal(expected.AdditionalData, actual.AdditionalData); Assert.Equal(expected.ClaimUid, actual.ClaimUid); Assert.Equal(expected.IsCookieToken, actual.IsCookieToken); Assert.Equal(expected.SecurityToken, actual.SecurityToken); Assert.Equal(expected.Username, actual.Username); }
public string Serialize(AntiforgeryToken token) { if (token == null) { throw new ArgumentNullException(nameof(token)); } var serializationContext = _pool.Get(); try { var writer = serializationContext.Writer; writer.Write(TokenVersion); writer.Write(token.SecurityToken !.GetData()); writer.Write(token.IsCookieToken); if (!token.IsCookieToken) { if (token.ClaimUid != null) { writer.Write(true /* isClaimsBased */); writer.Write(token.ClaimUid.GetData()); } else { writer.Write(false /* isClaimsBased */); writer.Write(token.Username !); } writer.Write(token.AdditionalData); } writer.Flush(); var stream = serializationContext.Stream; var bytes = _cryptoSystem.Protect(stream.ToArray()); var count = bytes.Length; var charsRequired = WebEncoders.GetArraySizeRequiredToEncode(count); var chars = serializationContext.GetChars(charsRequired); var outputLength = WebEncoders.Base64UrlEncode( bytes, offset: 0, output: chars, outputOffset: 0, count: count); return(new string(chars, startIndex : 0, length : outputLength)); } finally { _pool.Return(serializationContext); } }
public void SecurityTokenProperty_PropertySetter_DoesNotUseDefaults() { // Arrange var token = new AntiforgeryToken(); // Act var securityToken = new BinaryBlob(64); token.SecurityToken = securityToken; // Assert Assert.Equal(securityToken, token.SecurityToken); }
public void IsCookieTokenValid_NullToken_ReturnsFalse() { // Arrange AntiforgeryToken cookieToken = null; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: null); // Act var isValid = tokenProvider.IsCookieTokenValid(cookieToken); // Assert Assert.False(isValid); }
public void SecurityTokenProperty_GetsAutopopulated() { // Arrange var token = new AntiforgeryToken(); // Act var securityToken = token.SecurityToken; // Assert Assert.NotNull(securityToken); Assert.Equal(AntiforgeryToken.SecurityTokenBitLength, securityToken !.BitLength); // check that we're not making a new one each property call Assert.Equal(securityToken, token.SecurityToken); }
public void AdditionalDataProperty() { // Arrange var token = new AntiforgeryToken(); // Act & assert - 1 Assert.Equal("", token.AdditionalData); // Act & assert - 2 token.AdditionalData = "additional data"; Assert.Equal("additional data", token.AdditionalData); // Act & assert - 3 token.AdditionalData = null !; Assert.Equal("", token.AdditionalData); }
public void UsernameProperty() { // Arrange var token = new AntiforgeryToken(); // Act & assert - 1 Assert.Equal("", token.Username); // Act & assert - 2 token.Username = "******"; Assert.Equal("my username", token.Username); // Act & assert - 3 token.Username = null; Assert.Equal("", token.Username); }
public void IsCookieTokenProperty() { // Arrange var token = new AntiforgeryToken(); // Act & assert - 1 Assert.False(token.IsCookieToken); // Act & assert - 2 token.IsCookieToken = true; Assert.True(token.IsCookieToken); // Act & assert - 3 token.IsCookieToken = false; Assert.False(token.IsCookieToken); }
public void SecurityTokenProperty_PropertySetter_DoesNotAllowNulls() { // Arrange var token = new AntiforgeryToken(); // Act token.SecurityToken = null; var securityToken = token.SecurityToken; // Assert Assert.NotNull(securityToken); Assert.Equal(AntiforgeryToken.SecurityTokenBitLength, securityToken !.BitLength); // check that we're not making a new one each property call Assert.Equal(securityToken, token.SecurityToken); }
public void ClaimUidProperty() { // Arrange var token = new AntiforgeryToken(); // Act & assert - 1 Assert.Null(token.ClaimUid); // Act & assert - 2 BinaryBlob blob = new BinaryBlob(32); token.ClaimUid = blob; Assert.Equal(blob, token.ClaimUid); // Act & assert - 3 token.ClaimUid = null; Assert.Null(token.ClaimUid); }
public void IsCookieTokenValid_ValidToken_ReturnsTrue() { // Arrange var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: null); // Act var isValid = tokenProvider.IsCookieTokenValid(cookieToken); // Assert Assert.True(isValid); }
/* The serialized format of the anti-XSRF token is as follows: * Version: 1 byte integer * SecurityToken: 16 byte binary blob * IsCookieToken: 1 byte Boolean * [if IsCookieToken != true] * +- IsClaimsBased: 1 byte Boolean * | [if IsClaimsBased = true] * | `- ClaimUid: 32 byte binary blob * | [if IsClaimsBased = false] * | `- Username: UTF-8 string with 7-bit integer length prefix * `- AdditionalData: UTF-8 string with 7-bit integer length prefix */ private static AntiforgeryToken?Deserialize(BinaryReader reader) { // we can only consume tokens of the same serialized version that we generate var embeddedVersion = reader.ReadByte(); if (embeddedVersion != TokenVersion) { return(null); } var deserializedToken = new AntiforgeryToken(); var securityTokenBytes = reader.ReadBytes(AntiforgeryToken.SecurityTokenBitLength / 8); deserializedToken.SecurityToken = new BinaryBlob(AntiforgeryToken.SecurityTokenBitLength, securityTokenBytes); deserializedToken.IsCookieToken = reader.ReadBoolean(); if (!deserializedToken.IsCookieToken) { var isClaimsBased = reader.ReadBoolean(); if (isClaimsBased) { var claimUidBytes = reader.ReadBytes(AntiforgeryToken.ClaimUidBitLength / 8); deserializedToken.ClaimUid = new BinaryBlob(AntiforgeryToken.ClaimUidBitLength, claimUidBytes); } else { deserializedToken.Username = reader.ReadString(); } deserializedToken.AdditionalData = reader.ReadString(); } // if there's still unconsumed data in the stream, fail if (reader.BaseStream.ReadByte() != -1) { return(null); } // success return(deserializedToken); }
public void TryValidateTokenSet_ClaimUidMismatch() { // Arrange var httpContext = new DefaultHttpContext(); var identity = GetAuthenticatedIdentity("the-user"); httpContext.User = new ClaimsPrincipal(identity); var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var fieldtoken = new AntiforgeryToken() { SecurityToken = cookieToken.SecurityToken, IsCookieToken = false, ClaimUid = new BinaryBlob(256) }; var differentToken = new BinaryBlob(256); var mockClaimUidExtractor = new Mock <IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(It.Is <ClaimsPrincipal>(c => c.Identity == identity))) .Returns(Convert.ToBase64String(differentToken.GetData())); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); string expectedMessage = "The provided antiforgery token was meant for a different " + "claims-based user than the current user."; // Act string message; var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message); // Assert Assert.False(result); Assert.Equal(expectedMessage, message); }
public void TryValidateTokenSet_AdditionalDataRejected() { // Arrange var httpContext = new DefaultHttpContext(); var identity = new ClaimsIdentity(); httpContext.User = new ClaimsPrincipal(identity); var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var fieldtoken = new AntiforgeryToken() { SecurityToken = cookieToken.SecurityToken, Username = String.Empty, IsCookieToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock <IAntiforgeryAdditionalDataProvider>(); mockAdditionalDataProvider .Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(false); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: mockAdditionalDataProvider.Object); string expectedMessage = "The provided antiforgery token failed a custom data check."; // Act string message; var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message); // Assert Assert.False(result); Assert.Equal(expectedMessage, message); }
public void TryValidateTokenSet_UsernameMismatch(string identityUsername, string embeddedUsername) { // Arrange var httpContext = new DefaultHttpContext(); var identity = GetAuthenticatedIdentity(identityUsername); httpContext.User = new ClaimsPrincipal(identity); var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var fieldtoken = new AntiforgeryToken() { SecurityToken = cookieToken.SecurityToken, Username = embeddedUsername, IsCookieToken = false }; var mockClaimUidExtractor = new Mock <IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(It.Is <ClaimsPrincipal>(c => c.Identity == identity))) .Returns((string)null); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); string expectedMessage = $"The provided antiforgery token was meant for user \"{embeddedUsername}\", " + $"but the current user is \"{identityUsername}\"."; // Act string message; var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message); // Assert Assert.False(result); Assert.Equal(expectedMessage, message); }
public void Serialize_CookieToken_TokenRoundTripSuccessful() { // Arrange var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool); //"01" // Version //+ "705EEDCC7D42F1D6B3B98A593625BB4C" // SecurityToken //+ "01"; // IsCookieToken var token = new AntiforgeryToken() { SecurityToken = _securityToken, IsCookieToken = true }; // Act string actualSerializedData = testSerializer.Serialize(token); var deserializedToken = testSerializer.Deserialize(actualSerializedData); // Assert AssertTokensEqual(token, deserializedToken); _dataProtector.Verify(); }
public void GenerateRequestToken_InvalidCookieToken() { // Arrange var cookieToken = new AntiforgeryToken() { IsCookieToken = false }; var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); Assert.False(httpContext.User.Identity.IsAuthenticated); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: null); // Act & Assert ExceptionAssert.ThrowsArgument( () => tokenProvider.GenerateRequestToken(httpContext, cookieToken), "cookieToken", "The antiforgery cookie token is invalid."); }
public void GenerateRequestToken_ClaimsBasedIdentity() { // Arrange var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var identity = GetAuthenticatedIdentity("some-identity"); var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(identity); byte[] data = new byte[256 / 8]; RandomNumberGenerator.Fill(data); var base64ClaimUId = Convert.ToBase64String(data); var expectedClaimUid = new BinaryBlob(256, data); var mockClaimUidExtractor = new Mock <IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(It.Is <ClaimsPrincipal>(c => c.Identity == identity))) .Returns(base64ClaimUId); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); // Act var fieldToken = tokenProvider.GenerateRequestToken(httpContext, cookieToken); // Assert Assert.NotNull(fieldToken); Assert.Equal(cookieToken.SecurityToken, fieldToken.SecurityToken); Assert.False(fieldToken.IsCookieToken); Assert.Equal("", fieldToken.Username); Assert.Equal(expectedClaimUid, fieldToken.ClaimUid); Assert.Equal("", fieldToken.AdditionalData); }
public void TryValidateTokenSet_CookieTokenMissing() { // Arrange var httpContext = new DefaultHttpContext(); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); var fieldtoken = new AntiforgeryToken() { IsCookieToken = false }; var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: null, additionalDataProvider: null); // Act & Assert string message; var ex = Assert.Throws <ArgumentNullException>( () => tokenProvider.TryValidateTokenSet(httpContext, null, fieldtoken, out message)); Assert.StartsWith(@"The required antiforgery cookie token must be provided.", ex.Message); }
public void TryValidateTokenSet_Success_AuthenticatedUserWithUsername() { // Arrange var httpContext = new DefaultHttpContext(); var identity = GetAuthenticatedIdentity("the-user"); httpContext.User = new ClaimsPrincipal(identity); var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var fieldtoken = new AntiforgeryToken() { SecurityToken = cookieToken.SecurityToken, Username = "******", IsCookieToken = false, AdditionalData = "some-additional-data" }; var mockAdditionalDataProvider = new Mock <IAntiforgeryAdditionalDataProvider>(); mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) .Returns(true); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: new Mock <IClaimUidExtractor>().Object, additionalDataProvider: mockAdditionalDataProvider.Object); // Act string message; var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message); // Assert Assert.True(result); Assert.Null(message); }
public void TryValidateTokenSet_Success_ClaimsBasedUser() { // Arrange var httpContext = new DefaultHttpContext(); var identity = GetAuthenticatedIdentity("the-user"); httpContext.User = new ClaimsPrincipal(identity); var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var fieldtoken = new AntiforgeryToken() { SecurityToken = cookieToken.SecurityToken, IsCookieToken = false, ClaimUid = new BinaryBlob(256) }; var mockClaimUidExtractor = new Mock <IClaimUidExtractor>(); mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(It.Is <ClaimsPrincipal>(c => c.Identity == identity))) .Returns(Convert.ToBase64String(fieldtoken.ClaimUid.GetData())); var tokenProvider = new DefaultAntiforgeryTokenGenerator( claimUidExtractor: mockClaimUidExtractor.Object, additionalDataProvider: null); // Act string message; var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message); // Assert Assert.True(result); Assert.Null(message); }