protected override void Act()
            {
                _contextStorage = new HashtableContextStorage();

                var settingProvider = new ApiKeyContextProvider(_contextStorage);

                settingProvider.SetApiKeyContext(
                    new ApiKeyContext(
                        SuppliedApiKey,
                        SuppliedClaimsetName,
                        _suppliedEducationOrganizationIds,
                        _suppliedNamespacePrefixes,
                        _suppliedProfiles,
                        SuppliedStudentIdentificationSystemDescriptor,
                        _suppliedCreatorOwnershipTokenId,
                        _suppliedOwnershipTokenIds));

                var gettingProvider = new ApiKeyContextProvider(_contextStorage);

                _actualApiKey = gettingProvider.GetApiKeyContext()
                                .ApiKey;

                _actualClaimsetName = gettingProvider.GetApiKeyContext()
                                      .ClaimSetName;

                _actualEducationOrganizationIds = gettingProvider.GetApiKeyContext()
                                                  .EducationOrganizationIds;

                _actualNamespacePrefixes = gettingProvider.GetApiKeyContext()
                                           .NamespacePrefixes;

                _actualProfiles = gettingProvider.GetApiKeyContext()
                                  .Profiles;

                _actualStudentIdentificationSystemDescriptor =
                    gettingProvider.GetApiKeyContext().StudentIdentificationSystemDescriptor;

                _actualCreatorOwnershipTokenId = gettingProvider.GetApiKeyContext().CreatorOwnershipTokenId;

                _actualOwnershipTokenIds = gettingProvider.GetApiKeyContext().OwnershipTokenIds;

                settingProvider.SetApiKeyContext(_suppliedApiKeyContext);

                _actualApiKeyContext = gettingProvider.GetApiKeyContext();
            }
        public async Task Authenticate(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            // 1. Look for credentials in the request.
            HttpRequestMessage        request       = context.Request;
            AuthenticationHeaderValue authorization = request.Headers.Authorization;

            // 2. If there are no credentials, do nothing.
            if (authorization == null)
            {
                context.ErrorResult = new AuthenticationFailureResult("Missing credentials", request);
                return;
            }

            // 3. If there are credentials but the filter does not recognize the
            //    authentication scheme, do nothing.
            if (!authorization.Scheme.EqualsIgnoreCase(AuthenticationScheme))
            {
                return;
            }

            // 4. If there are credentials that the filter understands, try to validate them.
            // 5. If the credentials are bad, set the error result.
            if (string.IsNullOrEmpty(authorization.Parameter))
            {
                context.ErrorResult = new AuthenticationFailureResult("Missing parameter", request);
                return;
            }

            // Validate the token and get the corresponding API key details
            var apiClientDetails = await OAuthTokenValidator.GetClientDetailsForTokenAsync(authorization.Parameter);

            if (!apiClientDetails.IsTokenValid)
            {
                context.ErrorResult = new AuthenticationFailureResult("Invalid token", request);
                return;
            }

            if (_expectedUseSandboxValue.Value.HasValue &&
                apiClientDetails.IsSandboxClient != _expectedUseSandboxValue.Value.Value)
            {
                var message = apiClientDetails.IsSandboxClient
                    ? "Sandbox credentials used in call to Production API"
                    : "Production credentials used in call to Sandbox API";

                context.ErrorResult = new AuthenticationFailureResult(message, request);
                return;
            }

            // Store API key details into context
            ApiKeyContextProvider.SetApiKeyContext(
                new ApiKeyContext(
                    apiClientDetails.ApiKey,
                    apiClientDetails.ClaimSetName,
                    apiClientDetails.EducationOrganizationIds,
                    apiClientDetails.NamespacePrefixes,
                    apiClientDetails.Profiles,
                    apiClientDetails.StudentIdentificationSystemDescriptor,
                    apiClientDetails.CreatorOwnershipTokenId,
                    apiClientDetails.OwnershipTokenIds));

            var claimsIdentity = ClaimsIdentityProvider.GetClaimsIdentity(
                apiClientDetails.EducationOrganizationIds,
                apiClientDetails.ClaimSetName,
                apiClientDetails.NamespacePrefixes,
                apiClientDetails.Profiles.ToList());

            context.Principal = new ClaimsPrincipal(claimsIdentity);
        }