예제 #1
0
        public void Equals_Null_ReturnsFalse()
        {
            // Arrange
            object blobA = new BinaryBlob(32);
            object blobB = null;

            // Act & assert
            Assert.NotEqual(blobA, blobB);
        }
예제 #2
0
        public void Equals_DifferentData_ReturnsFalse()
        {
            // Arrange
            object blobA = new BinaryBlob(32, new byte[] { 0x01, 0x02, 0x03, 0x04 });
            object blobB = new BinaryBlob(32, new byte[] { 0x04, 0x03, 0x02, 0x01 });

            // Act & assert
            Assert.NotEqual(blobA, blobB);
        }
예제 #3
0
        public void Equals_NotABlob_ReturnsFalse()
        {
            // Arrange
            object blobA = new BinaryBlob(32);
            object blobB = "hello";

            // Act & assert
            Assert.NotEqual(blobA, blobB);
        }
예제 #4
0
        public void Ctor_BitLength_ProducesDifferentValues()
        {
            // Act
            var blobA = new BinaryBlob(bitLength: 64);
            var blobB = new BinaryBlob(bitLength: 64);

            // Assert
            Assert.NotEqual(blobA.GetData(), blobB.GetData());
        }
예제 #5
0
        public void Equals_SameData_ReturnsTrue()
        {
            // Arrange
            object blobA = new BinaryBlob(32, new byte[] { 0x01, 0x02, 0x03, 0x04 });
            object blobB = new BinaryBlob(32, new byte[] { 0x01, 0x02, 0x03, 0x04 });

            // Act & assert
            Assert.Equal(blobA, blobB);
        }
예제 #6
0
        public void Ctor_BitLength()
        {
            // Act
            var blob = new BinaryBlob(bitLength: 64);
            var data = blob.GetData();

            // Assert
            Assert.Equal(64, blob.BitLength);
            Assert.Equal(64 / 8, data.Length);
            Assert.NotEqual(new byte[64 / 8], data); // should not be a zero-filled array
        }
예제 #7
0
        public void Ctor_Data()
        {
            // Arrange
            var expectedData = new byte[] { 0x01, 0x02, 0x03, 0x04 };

            // Act
            var blob = new BinaryBlob(32, expectedData);

            // Assert
            Assert.Equal(32, blob.BitLength);
            Assert.Equal(expectedData, blob.GetData());
        }
예제 #8
0
        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);
        }
예제 #9
0
        public void GetHashCodeTest()
        {
            // Arrange
            var blobData         = new byte[] { 0x01, 0x02, 0x03, 0x04 };
            var expectedHashCode = BitConverter.ToInt32(blobData, 0);

            var blob = new BinaryBlob(32, blobData);

            // Act
            var actualHashCode = blob.GetHashCode();

            // Assert
            Assert.Equal(expectedHashCode, actualHashCode);
        }
예제 #10
0
        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);
        }
예제 #11
0
        public void GenerateFormToken_ClaimsBasedIdentity()
        {
            // Arrange
            var cookieToken = new AntiforgeryToken()
            {
                IsSessionToken = true
            };

            var identity    = GetAuthenticatedIdentity("some-identity");
            var httpContext = new DefaultHttpContext();

            httpContext.User = new ClaimsPrincipal(identity);

            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 DefaultAntiforgeryTokenGenerator(
                optionsAccessor: new TestOptionsManager(),
                claimUidExtractor: mockClaimUidExtractor.Object,
                additionalDataProvider: null);

            // Act
            var fieldToken = tokenProvider.GenerateFormToken(httpContext, 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);
        }
예제 #12
0
        public void ValidateTokens_ClaimUidMismatch()
        {
            // Arrange
            var httpContext = new DefaultHttpContext();
            var identity    = GetAuthenticatedIdentity("the-user");

            httpContext.User = new ClaimsPrincipal(identity);

            var sessionToken = new AntiforgeryToken()
            {
                IsSessionToken = true
            };
            var fieldtoken = new AntiforgeryToken()
            {
                SecurityToken  = sessionToken.SecurityToken,
                IsSessionToken = false,
                ClaimUid       = new BinaryBlob(256)
            };

            var differentToken        = new BinaryBlob(256);
            var mockClaimUidExtractor = new Mock <IClaimUidExtractor>();

            mockClaimUidExtractor.Setup(o => o.ExtractClaimUid(identity))
            .Returns(Convert.ToBase64String(differentToken.GetData()));

            var tokenProvider = new DefaultAntiforgeryTokenGenerator(
                optionsAccessor: new TestOptionsManager(),
                claimUidExtractor: mockClaimUidExtractor.Object,
                additionalDataProvider: null);

            // Act & assert
            var exception = Assert.Throws <InvalidOperationException>(
                () => tokenProvider.ValidateTokens(httpContext, sessionToken, fieldtoken));

            Assert.Equal(
                @"The provided antiforgery token was meant for a different claims-based user than the current user.",
                exception.Message);
        }
예제 #13
0
        public void ValidateTokens(
            HttpContext httpContext,
            AntiforgeryToken sessionToken,
            AntiforgeryToken fieldToken)
        {
            // Were the tokens even present at all?
            if (sessionToken == null)
            {
                throw new InvalidOperationException(
                          Resources.FormatAntiforgeryToken_CookieMissing(_options.CookieName));
            }
            if (fieldToken == null)
            {
                throw new InvalidOperationException(
                          Resources.FormatAntiforgeryToken_FormFieldMissing(_options.FormFieldName));
            }

            // Do the tokens have the correct format?
            if (!sessionToken.IsSessionToken || fieldToken.IsSessionToken)
            {
                throw new InvalidOperationException(
                          Resources.FormatAntiforgeryToken_TokensSwapped(_options.CookieName, _options.FormFieldName));
            }

            // Are the security tokens embedded in each incoming token identical?
            if (!Equals(sessionToken.SecurityToken, fieldToken.SecurityToken))
            {
                throw new InvalidOperationException(Resources.AntiforgeryToken_SecurityTokenMismatch);
            }

            // Is the incoming token meant for the current user?
            var        currentUsername = string.Empty;
            BinaryBlob currentClaimUid = null;

            var identity = httpContext.User?.Identity as ClaimsIdentity;

            if (identity != null && identity.IsAuthenticated)
            {
                currentClaimUid = GetClaimUidBlob(_claimUidExtractor.ExtractClaimUid(identity));
                if (currentClaimUid == null)
                {
                    currentUsername = identity.Name ?? string.Empty;
                }
            }

            // OpenID and other similar authentication schemes use URIs for the username.
            // These should be treated as case-sensitive.
            var useCaseSensitiveUsernameComparison =
                currentUsername.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
                currentUsername.StartsWith("https://", StringComparison.OrdinalIgnoreCase);

            if (!string.Equals(fieldToken.Username,
                               currentUsername,
                               (useCaseSensitiveUsernameComparison) ?
                               StringComparison.Ordinal :
                               StringComparison.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException(
                          Resources.FormatAntiforgeryToken_UsernameMismatch(fieldToken.Username, currentUsername));
            }

            if (!Equals(fieldToken.ClaimUid, currentClaimUid))
            {
                throw new InvalidOperationException(Resources.AntiforgeryToken_ClaimUidMismatch);
            }

            // Is the AdditionalData valid?
            if (_additionalDataProvider != null &&
                !_additionalDataProvider.ValidateAdditionalData(httpContext, fieldToken.AdditionalData))
            {
                throw new InvalidOperationException(Resources.AntiforgeryToken_AdditionalDataCheckFailed);
            }
        }