Skip to content

Allow a default ITokenRequestCustomizer to be registered#300

Merged
pgermishuys merged 1 commit into
mainfrom
pg/http-request-context
Nov 21, 2025
Merged

Allow a default ITokenRequestCustomizer to be registered#300
pgermishuys merged 1 commit into
mainfrom
pg/http-request-context

Allow a default ITokenRequestCustomizer to be registered

a48ed81
Select commit
Loading
Failed to load commit list.
Sign in for the full log view
GitHub Actions / Test Report - AccessTokenManagement.Tests succeeded Nov 21, 2025 in 0s

178 passed, 0 failed and 1 skipped

Tests passed successfully

✅ AccessTokenManagement.Tests.trx

179 tests were completed in 66s with 178 passed, 0 failed and 1 skipped.

Test suite Passed Failed Skipped Time
Duende.AccessTokenManagement.AccessTokenHandler.AccessTokenHandlerTests 20✅ 1⚪ 24s
Duende.AccessTokenManagement.BackChannelClientTests 14✅ 17s
Duende.AccessTokenManagement.ClientTokenManagementTests 18✅ 20s
Duende.AccessTokenManagement.ConventionTests 8✅ 139ms
Duende.AccessTokenManagement.DPoPExtensionTests 3✅ 1ms
Duende.AccessTokenManagement.HttpRequestContextTests 2✅ 3ms
Duende.AccessTokenManagement.HybridCacheClientTokenManagementApiTests 15✅ 30s
Duende.AccessTokenManagement.HybridCacheExplorationTests 3✅ 62ms
Duende.AccessTokenManagement.PublicApiVerificationTests 4✅ 1s
Duende.AccessTokenManagement.StoreTokensInAuthenticationPropertiesTests 7✅ 7s
Duende.AccessTokenManagement.TokenRequestCustomizer.AddHandlerTests 3✅ 1ms
Duende.AccessTokenManagement.TokenRequestCustomizer.ClientAccessTokenRequestCustomizerTests 5✅ 17s
Duende.AccessTokenManagement.TokenRequestCustomizer.ClientCredentialsTokenRequestCustomizerTests 5✅ 7s
Duende.AccessTokenManagement.TokenRequestCustomizer.GetClientAccessTokenAsyncTests 3✅ 3s
Duende.AccessTokenManagement.TokenRequestCustomizer.GetUserAccessTokenAsyncTests 3✅ 5s
Duende.AccessTokenManagement.TokenRequestCustomizer.RevokeRefreshTokenAsyncTests 3✅ 5s
Duende.AccessTokenManagement.TokenRequestCustomizer.ScenarioTests 1✅ 9s
Duende.AccessTokenManagement.TokenRequestCustomizer.UserAccessTokenRequestCustomizerTests 5✅ 14s
Duende.AccessTokenManagement.TokenRetrieverTests 3✅ 3s
Duende.AccessTokenManagement.Types.AccessTokenTypeTests 1✅ 0ms
Duende.AccessTokenManagement.Types.ClientCredentialsCacheKeyTests 4✅ 14ms
Duende.AccessTokenManagement.Types.ScopeTests 20✅ 3ms
Duende.AccessTokenManagement.Types.TokenResultTests 2✅ 52ms
Duende.AccessTokenManagement.Types.ValidationRulesTests 10✅ 7ms
Duende.AccessTokenManagement.UserTokenManagementTests 13✅ 17s
Duende.AccessTokenManagement.UserTokenManagementWithDPoPTests 3✅ 5s

✅ Duende.AccessTokenManagement.AccessTokenHandler.AccessTokenHandlerTests

✅ Access_tokens_are_cached(type: ClientCredentials)
✅ Access_tokens_are_cached(type: OidcClient)
✅ Access_tokens_are_cached(type: OidcUser)
✅ Can_get_access_token(type: ClientCredentials)
✅ Can_get_access_token(type: OidcClient)
✅ Can_get_access_token(type: OidcUser)
✅ ForceTokenRenewal_should_bypass_cache_and_get_new_token(type: ClientCredentials)
✅ ForceTokenRenewal_should_bypass_cache_and_get_new_token(type: OidcClient)
✅ ForceTokenRenewal_should_bypass_cache_and_get_new_token(type: OidcUser)
⚪ Uses_auto_tuning_in_cache_expiration
✅ Will_normalize_case_for_scheme_values(tokenType: "beareR", expectedScheme: "Bearer")
✅ Will_normalize_case_for_scheme_values(tokenType: "dpoP", expectedScheme: "DPoP")
✅ Will_only_retry_once(type: ClientCredentials)
✅ Will_only_retry_once(type: OidcClient)
✅ Will_only_retry_once(type: OidcUser)
✅ Will_refresh_token_when_access_token_is_rejected(type: ClientCredentials)
✅ Will_refresh_token_when_access_token_is_rejected(type: OidcClient)
✅ Will_refresh_token_when_access_token_is_rejected(type: OidcUser)
✅ Will_use_DPop_on_api_requests(type: ClientCredentials)
✅ Will_use_DPop_on_api_requests(type: OidcClient)
✅ Will_use_DPop_on_api_requests(type: OidcUser)

✅ Duende.AccessTokenManagement.BackChannelClientTests

✅ Can_delete_entries_for_entire_atm(clientName: "Duende.AccessTokenManagement")
✅ Can_delete_entries_for_entire_atm(clientName: "some_client_name")
✅ Can_delete_token_from_cache
✅ Can_use_custom_cache_implementation
✅ Can_use_custom_encryption
✅ Can_use_custom_key_generator
✅ Can_use_custom_serializer
✅ Get_access_token_uses_custom_backchannel_client_from_factory
✅ Get_access_token_uses_default_backchannel_client_from_factory
✅ Get_access_token_uses_specific_http_client_instance
✅ Getting_a_token_with_different_parameters_twice_concurrently_will_result_two_calls
✅ Getting_a_token_with_different_scope_twice_concurrently_will_result_two_calls
✅ Getting_a_token_with_different_scope_twice_sequentially_will_result_in_two_calls
✅ Will_use_cache

✅ Duende.AccessTokenManagement.ClientTokenManagementTests

✅ Cache_auto_tuning_should_persist_across_transient_manager_instances
✅ client_should_use_nonce_when_sending_dpop_proof
✅ client_with_dpop_key_should_send_proof_token
✅ Explicit_expires_in_response_should_create_token_with_expiration
✅ Missing_client_id_throw_exception
✅ Missing_client_secret_throw_exception
✅ Missing_expires_in_response_should_create_long_lived_token
✅ Missing_tokenEndpoint_throw_exception
✅ Request_assertion_should_take_precedence_over_service_assertion
✅ Request_assertions_should_be_sent_correctly
✅ Request_parameters_should_take_precedence_over_configuration
✅ Service_assertions_should_be_sent_correctly
✅ Service_should_always_hit_network_with_force_renewal
✅ Service_should_hit_network_only_once_and_then_use_cache
✅ Service_should_hit_network_when_cache_throws_exception
✅ Token_request_and_response_should_have_expected_values(style: AuthorizationHeader)
✅ Token_request_and_response_should_have_expected_values(style: PostBody)
✅ Unknown_client_should_throw_exception

✅ Duende.AccessTokenManagement.ConventionTests

✅ All_async_methods_should_end_with_Async_and_have_cancellation_token_as_last_parameter
✅ All_strongly_typed_strings_are_readonly_struct
✅ All_strongly_typed_strings_have_internal_create_method
✅ All_strongly_typed_strings_Have_private_value
✅ All_strongly_typed_strings_should_have_only_expected_constructors
✅ All_strongly_typed_strings_should_have_public_constructor_that_throws
✅ All_types_in_Internal_namespace_should_be_internal
✅ All_types_not_in_Internal_namespace_should_be_sealed_or_static

✅ Duende.AccessTokenManagement.DPoPExtensionTests

✅ GetDPoPNonceIsCaseInsensitive(headerName: "dpop-nonce")
✅ GetDPoPNonceIsCaseInsensitive(headerName: "DPoP-Nonce")
✅ GetDPoPNonceIsCaseInsensitive(headerName: "DPOP-NONCE")

✅ Duende.AccessTokenManagement.HttpRequestContextTests

✅ HttpRequestContext_can_be_mapped_from_HttpRequest
✅ HttpRequestMessageContext_can_be_mapped_from_HttpRequestMessage

✅ Duende.AccessTokenManagement.HybridCacheClientTokenManagementApiTests

✅ api_returning_401_should_send_new_access_token
✅ dpop_clients_GetAccessTokenAsync_should_obtain_token_with_cnf
✅ dpop_tokens_should_be_passed_to_api
✅ HybridCache_should_be_registered
✅ using_different_ec_keys_for_dpop_should_obtain_token_with_cnf(alg: "ES256")
✅ using_different_ec_keys_for_dpop_should_obtain_token_with_cnf(alg: "ES384")
✅ using_different_ec_keys_for_dpop_should_obtain_token_with_cnf(alg: "ES512")
✅ using_different_rsa_keys_for_dpop_should_obtain_token_with_cnf(alg: "PS256")
✅ using_different_rsa_keys_for_dpop_should_obtain_token_with_cnf(alg: "PS384")
✅ using_different_rsa_keys_for_dpop_should_obtain_token_with_cnf(alg: "PS512")
✅ using_different_rsa_keys_for_dpop_should_obtain_token_with_cnf(alg: "RS256")
✅ using_different_rsa_keys_for_dpop_should_obtain_token_with_cnf(alg: "RS384")
✅ using_different_rsa_keys_for_dpop_should_obtain_token_with_cnf(alg: "RS512")
✅ when_additional_proof_payload_claims_are_defined_they_should_be_included_in_dpop_proof
✅ when_api_issues_nonce_api_request_should_be_retried_with_new_nonce

✅ Duende.AccessTokenManagement.HybridCacheExplorationTests

✅ Can_mock_time_provider_in_hybrid_cache
✅ Exception_is_not_written_to_cache
✅ Mocking_l2_cache

✅ Duende.AccessTokenManagement.PublicApiVerificationTests

✅ GetAllPublicTypes
✅ GetAllPublicTypes_OpenIdConnect
✅ VerifyPublicApi
✅ VerifyPublicApi_OpenIdConnect

✅ Duende.AccessTokenManagement.StoreTokensInAuthenticationPropertiesTests

✅ Removing_all_tokens_in_a_challenge_scheme_should_remove_items_shared_in_that_scheme
✅ Should_be_able_to_remove_tokens
✅ Should_be_able_to_remove_tokens_for_multiple_schemes_and_resources_at_the_same_time
✅ Should_be_able_to_store_and_retrieve_tokens
✅ Should_be_able_to_store_and_retrieve_tokens_for_multiple_challenge_schemes
✅ Should_be_able_to_store_and_retrieve_tokens_for_multiple_resources
✅ Should_be_able_to_store_and_retrieve_tokens_for_multiple_schemes_and_resources_at_the_same_time

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.AddHandlerTests

✅ AddClientAccessTokenHandler_throws_when_factory_is_null
✅ AddClientCredentialsTokenHandler_throws_when_factory_is_null
✅ AddUserAccessTokenHandler_throws_when_factory_is_null

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.ClientAccessTokenRequestCustomizerTests

✅ Can_use_default_token_request_customizer
✅ Can_use_token_request_customizer
✅ Can_use_token_request_customizer_factory
✅ Customizer_can_use_http_request_header
✅ Customizer_can_use_http_request_uri

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.ClientCredentialsTokenRequestCustomizerTests

✅ Can_use_default_token_request_customizer
✅ Can_use_token_request_customizer
✅ Can_use_token_request_customizer_factory
✅ Customizer_can_use_http_request_header
✅ Customizer_can_use_http_request_uri

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.GetClientAccessTokenAsyncTests

✅ GetClientAccessTokenAsync_can_use_http_request_header_in_registered_token_request_customizer
✅ GetClientAccessTokenAsync_can_use_http_request_uri_in_registered_token_request_customizer
✅ GetClientAccessTokenAsync_can_use_registered_token_request_customizer

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.GetUserAccessTokenAsyncTests

✅ GetClientAccessTokenAsync_can_use_http_request_header_in_registered_token_request_customizer
✅ GetClientAccessTokenAsync_can_use_http_request_uri_in_registered_token_request_customizer
✅ GetClientAccessTokenAsync_can_use_registered_token_request_customizer

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.RevokeRefreshTokenAsyncTests

✅ RevokeRefreshTokenAsync_can_use_http_request_header
✅ RevokeRefreshTokenAsync_can_use_http_request_uri
✅ RevokeRefreshTokenAsync_can_use_registered_token_request_customizer

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.ScenarioTests

✅ OpenIdConnectUserAccessTokenRetriever_and_GetClientAccessTokenExtensionMethod_can_use_the_same_token_request_customizer

✅ Duende.AccessTokenManagement.TokenRequestCustomizer.UserAccessTokenRequestCustomizerTests

✅ Can_use_default_token_request_customizer
✅ Can_use_token_request_customizer
✅ Can_use_token_request_customizer_factory
✅ Customizer_can_use_http_request_header
✅ Customizer_can_use_http_request_uri

✅ Duende.AccessTokenManagement.TokenRetrieverTests

✅ Customizer_can_modify_parameters_when_called_in_client_credentials_token_retriever
✅ Customizer_can_modify_parameters_when_called_in_open_id_client_access_token_retriever
✅ Customizer_can_modify_parameters_when_called_in_open_id_user_access_token_retriever

✅ Duende.AccessTokenManagement.Types.AccessTokenTypeTests

✅ Can_change_to_scheme

✅ Duende.AccessTokenManagement.Types.ClientCredentialsCacheKeyTests

✅ Parse_InvalidValue_ThrowsException
✅ Parse_ValidValue_ReturnsCacheKey
✅ TryParse_InvalidValue_ReturnsFalseAndErrors
✅ TryParse_ValidValue_ReturnsTrueAndCacheKey

✅ Duende.AccessTokenManagement.Types.ScopeTests

✅ Scope_with_invalid_value_should_throw(scopeValue: " ")
✅ Scope_with_invalid_value_should_throw(scopeValue: " leadingspace")
✅ Scope_with_invalid_value_should_throw(scopeValue: "")
✅ Scope_with_invalid_value_should_throw(scopeValue: "\"")
✅ Scope_with_invalid_value_should_throw(scopeValue: "\\")
✅ Scope_with_invalid_value_should_throw(scopeValue: "\n")
✅ Scope_with_invalid_value_should_throw(scopeValue: "\t")
✅ Scope_with_invalid_value_should_throw(scopeValue: "trailingspace ")
✅ Scope_with_valid_value_should_not_throw(scopeValue: ":foo.v1.baz.{{bar}}.*")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "!")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "[")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "[word]")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "]")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "{foo:bar}")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "#")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "^")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "<tag>")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "~")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "$")
✅ Scope_with_valid_value_should_not_throw(scopeValue: "path/to/resource")

✅ Duende.AccessTokenManagement.Types.TokenResultTests

✅ Can_convert_failed_result_to_result
✅ Can_implicitly_convert_success_result_to_result

✅ Duende.AccessTokenManagement.Types.ValidationRulesTests

✅ AlphaNumeric_InvalidString_ReturnsFalse
✅ AlphaNumeric_ValidString_ReturnsTrue
✅ Authority_InvalidAuthority_ReturnsFalse
✅ Authority_ValidAuthority_ReturnsTrue
✅ MaxLength_InvalidString_ReturnsFalse
✅ MaxLength_ValidString_ReturnsTrue
✅ Regex_InvalidString_ReturnsFalse
✅ Regex_ValidString_ReturnsTrue
✅ Uri_InvalidUri_ReturnsFalse
✅ Uri_ValidUri_ReturnsTrue

✅ Duende.AccessTokenManagement.UserTokenManagementTests

✅ Anonymous_user_should_return_client_token
✅ Anonymous_user_should_return_user_token_error
✅ Can_implement_custom_user_principal_transform
✅ Can_request_user_token_using_client_assertions
✅ Logout_should_revoke_refresh_tokens
✅ Missing_expires_in_should_result_in_long_lived_token
✅ Missing_initial_refresh_token_and_expired_access_token_should_return_initial_access_token
✅ Missing_initial_refresh_token_response_should_return_access_token
✅ Multiple_users_have_distinct_tokens_across_refreshes
✅ Refresh_responses_without_refresh_token_use_old_refresh_token
✅ Resources_get_distinct_tokens
✅ Short_token_lifetime_should_trigger_refresh
✅ Standard_initial_token_response_should_return_expected_values

✅ Duende.AccessTokenManagement.UserTokenManagementWithDPoPTests

✅ dpop_jtk_is_attached_to_authorize_requests
✅ dpop_nonce_is_respected_during_code_exchange
✅ dpop_token_refresh_should_succeed