{"id":20139425,"url":"https://github.com/adolfok3/authorizationinterceptor","last_synced_at":"2026-02-12T22:04:56.427Z","repository":{"id":230898267,"uuid":"778539700","full_name":"Adolfok3/AuthorizationInterceptor","owner":"Adolfok3","description":"A simple and lightweight .NET package designed to streamline HttpClient authenticated requests","archived":false,"fork":false,"pushed_at":"2025-09-18T18:32:50.000Z","size":218,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-06T12:11:45.141Z","etag":null,"topics":["api","auth","authentication","authorization","cache","chsarp","distributed","dotnet","dotnet-core","headers","httpclient","interceptor","memory","request","response","rest"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Adolfok3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-03-27T22:56:45.000Z","updated_at":"2025-11-24T15:55:37.000Z","dependencies_parsed_at":"2024-04-24T12:27:27.171Z","dependency_job_id":"496bf8d2-3d70-4273-9eba-fe93a8a566b2","html_url":"https://github.com/Adolfok3/AuthorizationInterceptor","commit_stats":null,"previous_names":["adolfok3/authorizationinterceptor"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/Adolfok3/AuthorizationInterceptor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Adolfok3%2FAuthorizationInterceptor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Adolfok3%2FAuthorizationInterceptor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Adolfok3%2FAuthorizationInterceptor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Adolfok3%2FAuthorizationInterceptor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Adolfok3","download_url":"https://codeload.github.com/Adolfok3/AuthorizationInterceptor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Adolfok3%2FAuthorizationInterceptor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29382901,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T20:34:40.886Z","status":"ssl_error","status_checked_at":"2026-02-12T20:23:00.490Z","response_time":55,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","auth","authentication","authorization","cache","chsarp","distributed","dotnet","dotnet-core","headers","httpclient","interceptor","memory","request","response","rest"],"created_at":"2024-11-13T21:45:16.648Z","updated_at":"2026-02-12T22:04:56.410Z","avatar_url":"https://github.com/Adolfok3.png","language":"C#","readme":"![AuthorizationInterceptor Icon](./resources/icon.png)\n\n# Authorization Interceptor: A simple and lightweight .NET package designed to streamline HttpClient authenticated requests\n[![GithubActions](https://github.com/Adolfok3/authorizationinterceptor/actions/workflows/main.yml/badge.svg)](https://github.com/Adolfok3/AuthorizationInterceptor/actions)\n[![License](https://img.shields.io/badge/license-MIT-green)](./LICENSE)\n[![Codecov](https://codecov.io/github/Adolfok3/AuthorizationInterceptor/graph/badge.svg?token=PHBV20RCQK)](https://codecov.io/github/Adolfok3/AuthorizationInterceptor)\n[![NuGet Version](https://img.shields.io/nuget/vpre/AuthorizationInterceptor)](https://www.nuget.org/packages/AuthorizationInterceptor)\n\n## What is Authorization Interceptor?\nAuthorization Interceptor is a custom handler added to your HttpClient builder. With it, there's no need to worry about the expiration time and management of the authorization headers of your requests. Offering the possibility to use OAuth2 with RefreshToken or custom headers, whenever a request is sent and its response is a status code 401 (Unauthorized), the Interceptor will update the authorization headers and resend the same request with the updated authorization headers.\n\nAuthorization Interceptor can use MemoryCache to store authorization headers according to their expiration time, thus, it's not necessary to login or generate authorization every time you need to send a request to the API.\n\nAuthorization Interceptor can also share the same authorization headers with other instances of the application (if your application runs in a dockerized environment with Kubernetes) using the idea of distributed cache, avoiding concurrency among instances to log in or generate authorization headers with the API by reusing the authorization generated by the primary instance.\n\n## Getting started\n\n### Installation\nAuthorization Interceptor is installed [from NuGet](https://nuget.org/packages/authorizationinterceptor). Just run the following command in package manager console:\n```\nPM\u003e Install-Package AuthorizationInterceptor\n```\n\nOr from the .NET CLI as:\n```\ndotnet add package AuthorizationInterceptor\n```\n### Setup\nWhen adding a new HttpClient, call the extension method `AddAuthorizationInterceptorHandler`, passing in the authentication class for the target API:\n```csharp\nservices.AddHttpClient(\"TargetApi\")\n        .AddAuthorizationInterceptorHandler\u003cTargetApiAuthClass\u003e();\n```\n\nIf you have different authentication options for the same integration within the same project, you can use the overload method by passing an implementation invoker for the authentication class, like this:\n```csharp\nservices.AddHttpClient(\"TargetApi\")\n        .AddAuthorizationInterceptorHandler((provider) =\u003e ActivatorUtilities.CreateInstance\u003cTargetApiAuthClass\u003e(provider, someOtherDependency));\n```\n\nThis will make the `TargetApi` HttpClient use the Authorization Interceptor handler to generate and manage authorization headers.\n\nThe `TargetApiAuthClass` must implement the `IAuthenticationHandler` interface, so that the package can perform the necessary dependency and know where and when to generate the authorization headers. An example implementation of the class would look like this:\n\n```csharp\npublic class TargetApiAuthClass : IAuthenticationHandler\n{\n    public async ValueTask\u003cAuthorizationHeaders?\u003e AuthenticateAsync(AuthorizationHeaders? expiredHeaders, CancellationToken cancellation)\n    {\n        HttpResponseMessage? response = null;\n\n        if (expiredHeaders == null)\n        {\n            // Generate the login for the first time and return the authorization headers\n            response = await _client.PostAsync(\"auth\", null, cancellation);\n        }\n        else\n        {\n            // If a previous login was made, the expiredHeaders will be passed and you can reuse to reauthenticate. It is most commonly used for integrations with APIs that use RefreshToken.\n            // If the target API does not have the refresh token functionality, you will not need to implement this if condition e you can ignore the parameter 'expiredHeaders' performing always a new login\n            response = await _client.PostAsync($\"refresh?refresh={expiredHeaders.OAuthHeaders!.RefreshToken}\", null, cancellation);\n        }\n\n        var content = await response.Content.ReadAsStringAsync(cancellation);\n        var newHeaders = JsonSerializer.Deserialize\u003cUser\u003e(content)!;\n\n        return new OAuthHeaders(newHeaders.AccessToken, newHeaders.TokenType, newHeaders.ExpiresIn, newHeaders.RefreshToken, newHeaders.RefreshTokenExpiresIn);\n    }\n}\n```\n\nIn the example above, we showed the `TargetApiAuthClass` class, which must implement the authentication methods with the target API. Initially, the authorization headers do not exist, so the package will call the `AuthenticateAsync` method just once and will store the authorization in memory cache (if the MemoryCache package was installed and configured), always consulting it from there. However, if there is a response with status code 401 (unauthorized), the package will call the `AuthenticateAsync` again, passing the old/expired authorization and will return the new authorization.\n\n\u003e Note that in the `AuthenticateAsync` method the return type is `AuthorizationHeaders` but in the example above an `OAuthHeaders` is returned, because in this example we are assuming that the target API uses the OAuth2 authentication mechanism. However, if your target API does not have this functionality you can return a new object of type `AuthorizationHeaders` that inherits from a class `Dictionary\u003cstring, string\u003e`. In practice, it would look like this:\n\n```csharp\npublic async ValueTask\u003cAuthorizationHeaders?\u003e AuthenticateAsync(AuthorizationHeaders? expiredHeaders, CancellationToken cancellation)\n    {\n        return new AuthorizationHeaders\n        {\n            { \"MyCustomAuthorizationHeader\", \"MytokenValue\" },\n            { \"SomeOtherAuthorizationHeader\", \"OtherValue\" }\n        };\n    }\n```\n\n### Custom Options\nAssuming that your target API is legacy and it returns not only the status code 401 (unauthorized) for requests without authorization or with expired authorization but also returns 403 (forbidden). For this situation, there is a property in the options class called `UnauthenticatedPredicate` that customizes the type of predicate the package should evaluate for unauthorized requests.\n\nIn the extension method `AddAuthorizationInterceptorHandler`, pass this custom configuration in the following way:\n```csharp\nservices.AddHttpClient(\"TargetApi\")\n        .AddAuthorizationInterceptorHandler\u003cTargetApiAuthClass\u003e(options =\u003e\n        {\n            opts.UnauthenticatedPredicate = response =\u003e response.StatusCode == System.Net.HttpStatusCode.Forbidden ||\n                                                        response.StatusCode == System.Net.HttpStatusCode.Unauthorized;\n        })\n```\n\nNow, whenever there is a response with status code 401 or 403, the package will consider the authorization to be expired and will perform a new authentication.\n\n### Interceptors\nBy default, no interceptors is configured so the recommendation is to use at least [AuthorizationInterceptor.Extensions.MemoryCache](https://nuget.org/packages/AuthorizationInterceptor.Extensions.MemoryCache) package to store and manage the authorization headers lifecycle in a memory cache system.\n\nAfter install it, its simple to use:\n\n```csharp\nservices.AddHttpClient(\"TargetApi\")\n        .AddAuthorizationInterceptorHandler\u003cTargetApiAuthClass\u003e(options =\u003e\n        {\n            options.UseMemoryCacheInterceptor();\n        })\n```\n\n#### Available Interceptors\n\n- [AuthorizationInterceptor.Extensions.MemoryCache](https://nuget.org/packages/AuthorizationInterceptor.Extensions.MemoryCache)\n- [AuthorizationInterceptor.Extensions.DistributedCache](https://nuget.org/packages/AuthorizationInterceptor.Extensions.DistributedCache)\n- [AuthorizationInterceptor.Extensions.HybridCache](https://nuget.org/packages/AuthorizationInterceptor.Extensions.HybridCache)\n\n\u003e If you need an specific interceptor integration and doesnt exists here, checkout the [AuthorizationInterceptor.Extensions.Abstractions](https://nuget.org/packages/AuthorizationInterceptor.Extensions.Abstractions) to create your own interceptor.\n\n#### Concurrency\nWhen we have a scalable application running in a dockerized environment with Kubernetes, there can be more than one instance of the same application. This can lead to authentication concurrency issues between instances and divergent authorization headers among them. To solve this, it is recommended to use a custom interceptor that implements the idea of distributed cache. Therefore, in addition to saving the authorization headers in memory, the application will also save them in a distributed cache so that other instances of the application can reuse the authorization already generated by a primary instance. This avoids multiple authentication calls and divergent authorizations.\n\nIn practice, you need to configure some library already available for .Net that uses the DistributedCache abstraction. Please check the official documentation of [Distributed caching in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/distributed)\n\nLet's assume you have configured some package that uses the DistributedCache abstraction (Redis, NCache, etc), then you should install the [AuthorizationInterceptor.Extensions.DistributedCache](https://nuget.org/packages/AuthorizationInterceptor.Extensions.DistributedCache) extension package. In the options of the Authorization Interceptor, call the respective extension method `UseDistributedCacheInterceptor`.\n\n```csharp\nservices.AddHttpClient(\"TargetApi\")\n        .AddAuthorizationInterceptorHandler\u003cTargetApiAuthClass\u003e(options =\u003e\n        {\n            options.UseMemoryCacheInterceptor();\n            options.UseDistributedCacheInterceptor();\n        })\n        .ConfigureHttpClient(opt =\u003e opt.BaseAddress = new Uri(\"https://targetapi.com\"));\n```\n\nAdding a MemoryCache with a DistributedCache is a perfect match and recommended way to perform the authorized requests nicely. With this configuration, the Authorization Interceptor will create a sequence with: `MemoryCache \u003e DistributedCache \u003e AuthenticationHandler \u003e DistributedCache \u003e MemoryCache`.\n\n### Custom Interceptors\n\nIt's possible to add custom interceptors in the sequence of interceptors. Create your Interceptor class and have it inherit from the interface `IAuthorizationInterceptor`. After that, add it to the constructor of the Authorization Interceptor through the method `UseCustomInterceptor\u003cT\u003e`, e.g.:\n\n```csharp\nservices.AddHttpClient(\"TargetApi\")\n        .AddAuthorizationInterceptorHandler\u003cTargetApiAuthClass\u003e(options =\u003e\n        {\n            options.UseMemoryCacheInterceptor();\n            options.UseDistributedCacheInterceptor();\n            options.UseCustomInterceptor\u003cMyCustomInterceptor\u003e();\n        })\n        .ConfigureHttpClient(opt =\u003e opt.BaseAddress = new Uri(\"https://targetapi.com\"));\n```\n\n`MyCustomInterceptor` class:\n\n```csharp\npublic class MyCustomInterceptor : IAuthorizationInterceptor\n{\n    public ValueTask\u003cAuthorizationHeaders?\u003e GetHeadersAsync(string name, CancellationToken cancellationToken)\n    {\n        //Do something and return the headers if exists in this context\n    }\n\n    public ValueTask UpdateHeadersAsync(string name, AuthorizationHeaders? expiredHeaders, AuthorizationHeaders? newHeaders, CancellationToken cancellationToken)\n    {\n        //Do something with expired headers if necessary and update with newHeaders\n    }\n}\n```\n\nWith this configuration, the Authorization Interceptor will create a sequence of: `MemoryCache \u003e DistributedCache \u003e MyCustomInterceptor \u003e AuthenticationHandler \u003e DistributedCache \u003e MyCustomInterceptor \u003e MemoryCache`.\n\n\u003e The 'name' parameter refers to the name of the configured HttpClient. With this parameter you can differentiate between multiple httpclients configured using the same interceptor.\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadolfok3%2Fauthorizationinterceptor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadolfok3%2Fauthorizationinterceptor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadolfok3%2Fauthorizationinterceptor/lists"}