/// <inheritdoc />
    public bool TryValidateTokenSet(
        HttpContext httpContext,
        AntiforgeryToken cookieToken,
        AntiforgeryToken requestToken,
        [NotNullWhen(false)] out string?message)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }

        if (cookieToken == null)
        {
            throw new ArgumentNullException(
                      nameof(cookieToken),
                      Resources.Antiforgery_CookieToken_MustBeProvided_Generic);
        }

        if (requestToken == null)
        {
            throw new ArgumentNullException(
                      nameof(requestToken),
                      Resources.Antiforgery_RequestToken_MustBeProvided_Generic);
        }

        // Do the tokens have the correct format?
        if (!cookieToken.IsCookieToken || requestToken.IsCookieToken)
        {
            message = Resources.AntiforgeryToken_TokensSwapped;
            return(false);
        }

        // Are the security tokens embedded in each incoming token identical?
        if (!object.Equals(cookieToken.SecurityToken, requestToken.SecurityToken))
        {
            message = Resources.AntiforgeryToken_SecurityTokenMismatch;
            return(false);
        }

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

        var authenticatedIdentity = GetAuthenticatedIdentity(httpContext.User);

        if (authenticatedIdentity != null)
        {
            currentClaimUid = GetClaimUidBlob(_claimUidExtractor.ExtractClaimUid(httpContext.User));
            if (currentClaimUid == null)
            {
                currentUsername = authenticatedIdentity.Name ?? string.Empty;
            }
        }

        // OpenID and other similar authentication schemes use URIs for the username.
        // These should be treated as case-sensitive.
        var comparer = StringComparer.OrdinalIgnoreCase;

        if (currentUsername.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
            currentUsername.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
        {
            comparer = StringComparer.Ordinal;
        }

        if (!comparer.Equals(requestToken.Username, currentUsername))
        {
            message = Resources.FormatAntiforgeryToken_UsernameMismatch(requestToken.Username, currentUsername);
            return(false);
        }

        if (!object.Equals(requestToken.ClaimUid, currentClaimUid))
        {
            message = Resources.AntiforgeryToken_ClaimUidMismatch;
            return(false);
        }

        // Is the AdditionalData valid?
        if (_additionalDataProvider != null &&
            !_additionalDataProvider.ValidateAdditionalData(httpContext, requestToken.AdditionalData))
        {
            message = Resources.AntiforgeryToken_AdditionalDataCheckFailed;
            return(false);
        }

        message = null;
        return(true);
    }
예제 #2
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);
            }
        }