{"id":21898322,"url":"https://github.com/aetherinox/traefik-api-token-middleware","last_synced_at":"2025-10-07T04:51:32.685Z","repository":{"id":257803430,"uuid":"863862340","full_name":"aetherinox/traefik-api-token-middleware","owner":"aetherinox","description":"Traefik v3 plugin which allows you to pass an API-TOKEN in the header request of the targeted service. Supports whitelisted IP blocks. Logging for each connection.","archived":false,"fork":false,"pushed_at":"2025-06-25T09:24:13.000Z","size":1534,"stargazers_count":10,"open_issues_count":2,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-25T10:34:16.825Z","etag":null,"topics":["traefik","traefik-docker","traefik-plugin","traefik-plugins-catalog"],"latest_commit_sha":null,"homepage":"https://plugins.traefik.io/plugins/66f6ac697dd5a6c3095befd3/api-key-and-token-middleware","language":"Go","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/aetherinox.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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}},"created_at":"2024-09-27T03:55:25.000Z","updated_at":"2025-06-25T09:24:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"e73bef19-6eb0-4ff5-a81b-9b801f284677","html_url":"https://github.com/aetherinox/traefik-api-token-middleware","commit_stats":null,"previous_names":["aetherinox/traefik-api-token-middleware"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/aetherinox/traefik-api-token-middleware","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aetherinox%2Ftraefik-api-token-middleware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aetherinox%2Ftraefik-api-token-middleware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aetherinox%2Ftraefik-api-token-middleware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aetherinox%2Ftraefik-api-token-middleware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aetherinox","download_url":"https://codeload.github.com/aetherinox/traefik-api-token-middleware/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aetherinox%2Ftraefik-api-token-middleware/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278722769,"owners_count":26034461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["traefik","traefik-docker","traefik-plugin","traefik-plugins-catalog"],"created_at":"2024-11-28T14:25:47.229Z","updated_at":"2025-10-07T04:51:32.654Z","avatar_url":"https://github.com/aetherinox.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\u003ch6\u003eTraefik v3 middleware which allows for you to protect certain aspects of your site with an API token.\u003c/h6\u003e\n\u003ch2\u003e♾️ Traefik API Key \u0026 Token Middleware ♾️\u003c/h1\u003e\n\n\u003cbr /\u003e\n\n\u003cp\u003e\n\nThis Traefik middleware allows you to secure certain routes behind a request header API token. Users who have not successfully authenticated will be greeted with a **403 Forbidden Error**. Also displays information about each connection including IP address and URL that the user is trying to access.\n\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n\u003cimg src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/.assets/plugin_traefik_apikey_middleware.png\" height=\"230\"\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n\u003c!-- prettier-ignore-start --\u003e\n[![Version][github-version-img]][github-version-uri]\n[![Downloads][github-downloads-img]][github-downloads-uri]\n[![Build Status][github-build-img]][github-build-uri]\n[![Size][github-size-img]][github-size-img]\n[![Last Commit][github-commit-img]][github-commit-img]\n[![Contributors][contribs-all-img]](#contributors-)\n\n[![Built with Material for MkDocs](https://img.shields.io/badge/Powered_by_Material_for_MkDocs-526CFE?style=for-the-badge\u0026logo=MaterialForMkDocs\u0026logoColor=white)](https://aetherinox.github.io/traefik-api-token-middleware/)\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n- [How It Works](#how-it-works)\n- [Configuration](#configuration)\n  - [Static File](#static-file)\n    - [File (YAML)](#file-yaml)\n    - [File (TOML)](#file-toml)\n    - [CLI](#cli)\n  - [Dynamic File](#dynamic-file)\n    - [File (YAML)](#file-yaml-1)\n    - [File (TOML)](#file-toml-1)\n    - [Kubernetes Custom Resource Definition](#kubernetes-custom-resource-definition)\n- [Parameters](#parameters)\n  - [authenticationHeader](#authenticationheader)\n  - [authenticationErrorMsg](#authenticationerrormsg)\n  - [bearerHeader](#bearerheader)\n  - [tokens](#tokens)\n  - [removeHeadersOnSuccess](#removeheadersonsuccess)\n  - [removeTokenNameOnFailure](#removetokennameonfailure)\n  - [timestampUnix](#timestampunix)\n  - [whitelistIPs](#whitelistips)\n  - [agentDeny](#agentdeny)\n  - [agentAllow](#agentallow)\n  - [permissiveMode](#permissivemode)\n  - [debugLogs](#debuglogs)\n- [Full Examples](#full-examples)\n- [Browser Plugins](#browser-plugins)\n  - [Firefox](#firefox)\n    - [Extension: Header Editor](#extension-header-editor)\n    - [Extension: Modify Header Value](#extension-modify-header-value)\n- [Verifying Modified Headers](#verifying-modified-headers)\n- [Local Install](#local-install)\n  - [Static File](#static-file-1)\n    - [File (YAML)](#file-yaml-2)\n    - [File (TOML)](#file-toml-2)\n  - [Dynamic File](#dynamic-file-1)\n    - [File (YAML)](#file-yaml-3)\n    - [File (TOML)](#file-toml-3)\n- [Contributors ✨](#contributors-)\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## How It Works\nThis middleware offers you the ability to restrict certain containers being routed through Traefik. You can restrict a container to be inaccessible unless a user does one of the following:\n- Has a whitelisted IP address\n- Provides a valid request header value: `X-API-TOKEN`\n- Uses a valid useragent when accessing that container through their browser.\n\n\u003cbr /\u003e\n\nWhen enabling multiple ways to access the container, remember that the options are _**One OR the other**_. \n\n\u003cbr /\u003e\n\nThis means that if you whitelist a user's IP address, and also specify a useragent which is allowed to access your container; the user does NOT need to satisfy both requirements. \n\n\u003cbr /\u003e\n\nThey either need to be using a whitelisted IP when making their connection, OR their useragent must be a particular value.\n\n\u003cbr /\u003e\n\nIn other words, meeting one of multiple provided options, satisfies ALL options and grants the user permission to the container.\n\n\u003cbr /\u003e\n\nThis ensures that if you have a vital container behind your security measures and you have an incident where your whitelisted IP address changes; you have a backup method to re-gain access.\n\n\u003cbr /\u003e\n\nIf you opt to require a request header for `X-API-TOKEN`, you should change the default header name to something else and not the default value. This ensures that outside users cannot start guessing your token.\n\n```yml\n   authenticationHeaderName: X-CUSTOM-TOKEN-NAME\n```\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Configuration\nThe following provides examples for usage scenarios.\n\n\u003cbr /\u003e\n\n### Static File\nIf you are utilizing a Traefik **Static File**, review the following examples:\n\n\u003cbr /\u003e\n\n#### File (YAML)\n\n```yaml\n## Static configuration\nexperimental:\n  plugins:\n    traefik-api-token-middleware:\n      moduleName: \"github.com/Aetherinox/traefik-api-token-middleware\"\n      version: \"v0.1.4\"\n```\n\n\u003cbr /\u003e\n\n#### File (TOML)\n\n```toml\n## Static configuration\n[experimental.plugins.traefik-api-token-middleware]\n  moduleName = \"github.com/Aetherinox/traefik-api-token-middleware\"\n  version = \"v0.1.4\"\n```\n\n\u003cbr /\u003e\n\n#### CLI\n\n```bash\n## Static configuration\n--experimental.plugins.traefik-api-token-middleware.modulename=github.com/Aetherinox/traefik-api-token-middleware\n--experimental.plugins.traefik-api-token-middleware.version=v0.1.4\n```\n\n\u003cbr /\u003e\n\n### Dynamic File\nIf you are utilizing a Traefik **Dynamic File**, review the following examples:\n\n\u003cbr /\u003e\n\n#### File (YAML)\n\n```yaml\n# Dynamic configuration\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          authenticationErrorMsg: \"Invalid token\"\n          bearerHeader: true\n          bearerHeaderName: Authorization\n          removeHeadersOnSuccess: true\n          removeTokenNameOnFailure: false\n          timestampUnix: false\n          permissiveMode: false\n          debugLogs: false\n          agentDeny:\n            - '\\buseragent1\\b'\n          agentAllow:\n            - '\\buseragent2\\b'\n          tokens:\n            - your-api-token\n          whitelistIPs:\n            - '66.85.101.2'\n            - '10.10.0.7/32'\n```\n\n\u003cbr /\u003e\n\n#### File (TOML)\n\n```toml\n# Dynamic configuration\n[http]\n  [http.middlewares]\n    [http.middlewares.api-token]\n      [http.middlewares.api-token.plugin]\n        [http.middlewares.api-token.plugin.traefik-api-token-middleware]\n          authenticationHeader = true\n          authenticationHeaderName = \"X-API-TOKEN\"\n          authenticationErrorMsg = \"Invalid token\"\n          bearerHeader = true\n          bearerHeaderName = \"Authorization\"\n          removeHeadersOnSuccess = true\n          removeTokenNameOnFailure = false\n          timestampUnix = false\n          permissiveMode = false\n          debugLogs = false\n          agentDeny = [\"\\buseragent1\\b\"]\n          agentAllow = [\"\\buseragent2\\b\"]\n          tokens = [\"your-api-token\"]\n          whitelistIPs = [\"66.85.101.2\", \"10.10.0.7/32\"]\n```\n\n\u003cbr /\u003e\n\n#### Kubernetes Custom Resource Definition\n\n```yaml\n# Dynamic configuration\napiVersion: traefik.containo.us/v1alpha1\nkind: Middleware\nmetadata:\n  name: api-token\nspec:\n  plugin:\n    traefik-api-token-middleware:\n      authenticationHeader: true\n      authenticationHeaderName: X-API-TOKEN\n      authenticationErrorMsg: \"Invalid token\"\n      bearerHeader: true\n      bearerHeaderName: Authorization\n      removeHeadersOnSuccess: true\n      removeTokenNameOnFailure: false\n      timestampUnix: false\n      permissiveMode: false\n      debugLogs: false\n      agentDeny:\n        - '\\buseragent1\\b'\n      agentAllow:\n        - '\\buseragent2\\b'\n      tokens:\n        - your-api-token\n```\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Parameters\nThis plugin accepts the following parameters:\n\n\u003cbr /\u003e\n\n| Parameter | Description | Default | Type | Required |\n| --- | --- | --- | --- | --- |\n| \u003csub\u003e`authenticationHeader`\u003c/sub\u003e | \u003csub\u003ePass token using Authentication Header\u003c/sub\u003e | \u003csub\u003etrue\u003c/sub\u003e | \u003csub\u003ebool\u003c/sub\u003e | \u003csub\u003e⚠️ Note\u003c/sub\u003e | \n| \u003csub\u003e`authenticationHeaderName`\u003c/sub\u003e | \u003csub\u003eAuthentication header name\u003c/sub\u003e | \u003csub\u003e'X-API-TOKEN'\u003c/sub\u003e | \u003csub\u003estring\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e | \n| \u003csub\u003e`authenticationErrorMsg`\u003c/sub\u003e | \u003csub\u003eError message to display on unsuccessful authentication\u003c/sub\u003e | \u003csub\u003e'Access Denied'\u003c/sub\u003e | \u003csub\u003estring\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`bearerHeader`\u003c/sub\u003e | \u003csub\u003ePass token using Authentication Header Bearer Key\u003c/sub\u003e | \u003csub\u003etrue\u003c/sub\u003e | \u003csub\u003ebool\u003c/sub\u003e | \u003csub\u003e⚠️ Note\u003c/sub\u003e |\n| \u003csub\u003e`bearerHeaderName`\u003c/sub\u003e | \u003csub\u003eAuthentication bearer header name\u003c/sub\u003e | \u003csub\u003e'Authorization'\u003c/sub\u003e | \u003csub\u003estring\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`tokens`\u003c/sub\u003e | \u003csub\u003eList of API tokens\u003c/sub\u003e | \u003csub\u003e[]\u003c/sub\u003e | \u003csub\u003e[]string\u003c/sub\u003e | \u003csub\u003e✔️ Required\u003c/sub\u003e |\n| \u003csub\u003e`removeHeadersOnSuccess`\u003c/sub\u003e | \u003csub\u003eIf `true`; remove header on successful authentication\u003c/sub\u003e | \u003csub\u003etrue\u003c/sub\u003e | \u003csub\u003ebool\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`removeTokenNameOnFailure`\u003c/sub\u003e | \u003csub\u003eDon't display name of token in unsuccessful error message\u003c/sub\u003e | \u003csub\u003efalse\u003c/sub\u003e | \u003csub\u003ebool\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`timestampUnix`\u003c/sub\u003e | \u003csub\u003eDisplay datetime in Unix timestamp instead of UnixDate\u003c/sub\u003e | \u003csub\u003efalse\u003c/sub\u003e | \u003csub\u003ebool\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`whitelistIPs`\u003c/sub\u003e | \u003csub\u003eA list of IP blocks that will bypass the api-token check\u003c/sub\u003e | \u003csub\u003e[]\u003c/sub\u003e | \u003csub\u003e[]string\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`agentDeny`\u003c/sub\u003e | \u003csub\u003eBlacklist list of useragents from accessing routes\u003cbr\u003eStacks on top of the authorization token\u003c/sub\u003e | \u003csub\u003e[]\u003c/sub\u003e | \u003csub\u003e[]string\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`agentAllow`\u003c/sub\u003e | \u003csub\u003eWhitelist list of useragents to access routes\u003cbr\u003eStacks on top of the authorization token\u003c/sub\u003e | \u003csub\u003e[]\u003c/sub\u003e | \u003csub\u003e[]string\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`permissiveMode`\u003c/sub\u003e | \u003csub\u003eExecute a dry-run, allows access even if a token is invalid\u003c/sub\u003e | \u003csub\u003efalse\u003c/sub\u003e | \u003csub\u003ebool\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n| \u003csub\u003e`debugLogs`\u003c/sub\u003e | \u003csub\u003eShows debug logs in console\u003c/sub\u003e | \u003csub\u003efalse\u003c/sub\u003e | \u003csub\u003ebool\u003c/sub\u003e | \u003csub\u003e⭕ Optional\u003c/sub\u003e |\n\n\u003cbr /\u003e\n\n- ⚠️: Plugin requires that you enable either `authenticationHeader` OR `bearerHeader`. One of the two **MUST** be enabled.\n\n\u003cbr /\u003e\n\n### authenticationHeader\nIf enabled, will use an **Authentication Header** to pass a token. If you set this to `true`, you must ensure the following are also configured:\n- `authenticationHeaderName`\n- `tokens`\n\n\u003cbr /\u003e\n\nIf you do not wish to use the authentication header, you can alternatively use the [bearerHeader](#bearerheader).\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### authenticationErrorMsg\nThis setting changes the text at the beginning of an error message when an invalid token is specified.\n\n\u003cbr /\u003e\n\n`authenticationErrorMsg: `\n```json\n\n{\n  \"message\": \"Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token\",\n  \"status_code\": 403,\n  \"user-agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0\",\n  \"ip\": \"XX.XX.XX.XX\",\n  \"host\": \"sub.domain.lan\",\n  \"uri\": \"/\",\n  \"timestamp\": \"Fri Sep 27 03:24:27 UTC 2024\"\n}\n```\n\n\u003cbr /\u003e\n\n`authenticationErrorMsg: \"You cannot access this API\"`\n```json\n{\n  \"message\": \"You cannot access this API. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token\",\n  \"status_code\": 403,\n  \"user-agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0\",\n  \"ip\": \"XX.XX.XX.XX\",\n  \"host\": \"sub.domain.lan\",\n  \"uri\": \"/\",\n  \"timestamp\": \"Fri Sep 27 03:24:27 UTC 2024\"\n}\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### bearerHeader\nIf enabled, will use an **Bearer Header** to pass a token. If you set this to `true`, you must ensure the following are also configured:\n- `bearerHeaderName`\n- `tokens`\n\n\u003cbr /\u003e\n\nIf you do not wish to use the authentication header, you can alternatively use the [authenticationHeader](#authenticationHeader).\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### tokens\nA list of tokens that will accepted for each authentication.\n\n\u003cbr /\u003e\n\n```yml\n# Dynamic configuration\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          tokens:\n            - your-api-token\n            - second-api-token\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### removeHeadersOnSuccess\nIf set `true`, the authentication / bearer header will be removed upon successful authentication. Works with both the [authenticationHeader](#authenticationHeader) and [bearerHeader](#bearerHeader).\n\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### removeTokenNameOnFailure\nThis setting changes how error messages are displayed to a user who doesn't provide a correct token. If `enabled`, it will keep the name of your token private.\n\n\u003cbr /\u003e\n\n`removeTokenNameOnFailure: true`\n```json\n{\n  \"message\": \"Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token\",\n  \"status_code\": 403,\n  \"user-agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0\",\n  \"ip\": \"XX.XX.XX.XX\",\n  \"host\": \"sub.domain.lan\",\n  \"uri\": \"/\",\n  \"timestamp\": \"1727432498\"\n}\n```\n\n\u003cbr /\u003e\n\n`removeTokenNameOnFailure: false`\n```json\n{\n  \"message\": \"Access Denied.\",\n  \"status_code\": 403,\n  \"user-agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0\",\n  \"ip\": \"XX.XX.XX.XX\",\n  \"host\": \"sub.domain.lan\",\n  \"uri\": \"/\",\n  \"timestamp\": \"1727432498\"\n}\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### timestampUnix\nThis setting changes how the date / time will be displayed in your API callback / output.\n\n\u003cbr /\u003e\n\n`timestampUnix: true`\n```json\n{\n  \"message\": \"Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token\",\n  \"status_code\": 403,\n  \"user-agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0\",\n  \"ip\": \"XX.XX.XX.XX\",\n  \"host\": \"sub.domain.lan\",\n  \"uri\": \"/\",\n  \"timestamp\": \"1727432498\"\n}\n```\n\n\u003cbr /\u003e\n\n`timestampUnix: false`\n```json\n{\n  \"message\": \"Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token\",\n  \"status_code\": 403,\n  \"user-agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0\",\n  \"ip\": \"XX.XX.XX.XX\",\n  \"host\": \"sub.domain.lan\",\n  \"uri\": \"/\",\n  \"timestamp\": \"Fri Sep 27 03:24:27 UTC 2024\"\n}\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### whitelistIPs\nAllows you to specify a list of whitelisted IP addresses that will not have the API-token checked. \n\n\u003cbr /\u003e\n\n```yml\n# Dynamic configuration\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          authenticationErrorMsg: 'Invalid token'\n          tokens:\n            - your-api-token\n          whitelistIPs:\n            - '66.85.101.2'\n            - '10.10.0.7/32'\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### agentDeny\nSpecifies a list of useragents that are **NOT** allowed to access your protected routes. This setting stacks on top of the `Authentication` or `Bearer Token`. If the user has the correct token, but is listed in this deny list; they will be blocked from accessing anything. Utilizes Golang regex rules.\n\n\u003cbr /\u003e\n\n```yml\n# Dynamic configuration\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          agentDeny:\n              - '\\buseragent1\\b'\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### agentAllow\nSpecifies a list of useragents that are allowed to access your protected routes. This setting stacks on top of the `Authentication` or `Bearer Token`. If the user has the correct token, but is not in this allow list; they will be blocked from accessing anything. Utilizes Golang regex rules.\n\n\u003cbr /\u003e\n\n```yml\n# Dynamic configuration\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          agentAllow:\n              - '\\buseragent2\\b'\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### permissiveMode\nAllows to execute a dry-run on a request. The request will pass successfully even if the API token is invalid. Used for testing.\n\n```yml\n# Dynamic configuration\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          permissiveMode: true\n```\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n### debugLogs\nIf set `true`, gives you a more detailed outline of what is going on behind the scenes in your console. \n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Full Examples\nA few extra examples have been provided.\n\n\u003cbr /\u003e\n\n```yml\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          authenticationErrorMsg: \"Invalid token\"\n          bearerHeader: true\n          bearerHeaderName: Authorization\n          removeHeadersOnSuccess: true\n          removeTokenNameOnFailure: false\n          timestampUnix: false\n          permissiveMode: false\n          debugLogs: true\n          tokens:\n            - your-api-token\n\n    routers:\n        traefik-http:\n            service: \"traefik\"\n            rule: \"Host(`yourdomain.com`)\"\n            entryPoints:\n                - http\n            middlewares:\n                - https-redirect@file\n\n        traefik-https:\n            service: \"traefik\"\n            rule: \"Host(`yourdomain.com`)\"\n            entryPoints:\n                - https\n            middlewares:\n                - api-token@file\n            tls:\n                certResolver: cloudflare\n                domains:\n                    - main: \"yourdomain.com\"\n                      sans:\n                          - \"*.yourdomain.com\"\n```\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Browser Plugins\nIf you do not want to specify an API token using conventional means (such as by using `curl`), you can utilize a front-end browser extension. This allows you to supply a modified request header with your specific API token which will grant you access to your desired location.\n\n\u003cbr /\u003e\n\n### Firefox\nIf you are using Firefox, install the plugin(s) below. ( Pick **One** ):\n\n- [Extension: Header Editor](#extension-header-editor)\n- [Extension: Modify Header Value](#modify-header-value)\n\n\u003cbr /\u003e\n\n#### Extension: Header Editor  \nWith this extension, you can modify the request header and response header, cancel a request and redirect a request.\n**Please do not write regular expressions that begin with `(. *), (. *?), (. +)`, such regular expressions may cause problems with Firefox**  \n\n\u003cbr /\u003e\n\nOnce you install the browser extension above, open the **settings**.\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg style=\"width: 50%;text-align: center;\" src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/docs/img/browser-plugins/1.gif\"\u003e\u003c/p\u003e\n\n\u003cbr /\u003e\n\nCreate a new rule\n- Name: `API Token`\n- Rule Type: `Modify request header`\n- Match Type: `Domain`\n    - Match Rules: `subdomain.domain.com`\n    - Exclude Rule: `none`\n- Execute Type: `normal`\n    - Header Name: `x-api-token`\n    - Header Value: `your-api-token`\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg style=\"width: 80%;text-align: center;\" src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/docs/img/browser-plugins/2.png\"\u003e\u003c/p\u003e\n\n\u003cbr /\u003e\n\nOnce you have your modified header added to the browser extension, verify it by reading the section [Verifying Modified Headers](#verifying-modified-headers).\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n#### Extension: Modify Header Value\n[Modify Header Value](https://prod.outgoing.prod.webservices.mozgcp.net/v1/6eb6158dedc247c12e9010ccc61bb16738f844da3ac6765a5f43f7eb5ebace6f/https%3A//mybrowseraddon.com/modify-header-value.html) can add, modify or remove an HTTP-request-header for all requests on a desired website or URL. This Firefox add-on is very useful if you are an App developer, website designer, or if you want to test a particular header for a request on a website.\n\n\u003cbr /\u003e\n\nOnce you install the browser extension above, open the **settings**.\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg style=\"width: 50%;text-align: center;\" src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/docs/img/browser-plugins/3.gif\"\u003e\u003c/p\u003e\n\n\u003cbr /\u003e\n\nYou need to add a new rule which injects your modified header into the specified domain.\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg style=\"width: 100%;text-align: center;\" src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/docs/img/browser-plugins/4.png\"\u003e\u003c/p\u003e\n\n\u003cbr /\u003e\n\nOnce you have your modified header added to the browser extension, verify it by reading the section [Verifying Modified Headers](#verifying-modified-headers).\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Verifying Modified Headers\nThis section explains how you can verify that your modified request header is being received by your server.\n\nAccess the subdomain where you have applied an API-TOKEN. Once the page loads, open the **Developer Console**.\n\n- Firefox: `SHIFT + CTRL + I`\n- Chrome: `SHIFT + CTRL + I`\n- Safari: `Option + ⌘ + C`\n\n\u003cbr /\u003e\n\nA box should appear either on the right or bottom. Within the **Console** tab, ensure you have `Errors`, `Warnings`, `Logs`, `Info`, and `Debug` selected. They will have lines under them when enabled.\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg style=\"width: 100%;text-align: center;\" src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/docs/img/verify-headers/1.png\"\u003e\u003c/p\u003e\n\n\u003cbr /\u003e\n\nNext, refresh your browser's page.\n\n- Firefox: `SHIFT + F5`\n- Chrome: `SHIFT + F5`\n- Safari: `OPTION + ⌘ + E`\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg style=\"width: 100%;text-align: center;\" src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/docs/img/verify-headers/2.png\"\u003e\u003c/p\u003e\n\n\u003cbr /\u003e\n\nIn the bottom box, you should see a list of actions, which display your domain name, a status code, and the number of milliseconds it took to perform the action.\n\n```\n01:00:25.139        GET https://sub.yourdomain.com                     [HTTP/2 403  1ms]\n```\n\n\u003cbr /\u003e\n\n- `403` status: API-TOKEN was not accepted.\n- `200` status: API-TOKEN was accepted. (along with being able to actually see your site)\n\n\u003cbr /\u003e\n\nTypically with a `403` status, you can click the box that contains the status code with your domain, which will expand a box and show you the headers that were passed to the site, including your `API-TOKEN`.\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg style=\"width: 100%;text-align: center;\" src=\"https://raw.githubusercontent.com/Aetherinox/traefik-api-token-middleware/refs/heads/main/docs/img/verify-headers/3.png\"\u003e\u003c/p\u003e\n\n\u003cbr /\u003e\n\nIn the example above, we've passed `BadToken` which can be seen in the header response.\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Local Install\nTraefik comes with the ability to install this plugin locally without fetching it from Github. \n\n\u003cbr /\u003e\n\nDownload a local copy of this plugin to your server within your Traefik installation folder.\n```shell\ngit clone https://github.com/Aetherinox/traefik-api-token-middleware.git\n```\n\n\u003cbr /\u003e\n\nIf you are running **Docker**, you need to mount a new volume:\n\n\u003cbr /\u003e\n\n\u003e [!WARNING]\n\u003e The path to the plugin is **case sensitive**, do not change the casing of the folders, or the plugin will fail to load.\n\n\u003cbr /\u003e\n\n```yml\nservices:\n    traefik:\n        container_name: traefik\n        image: traefik:latest\n        restart: unless-stopped\n        volumes:\n            - ./traefik-api-token-middleware:/plugins-local/src/github.com/Aetherinox/traefik-api-token-middleware/\n```\n\n\u003cbr /\u003e\n\n### Static File\nOpen your **Traefik Static File** and change `plugins` to `localPlugins`.\n\n\u003cbr /\u003e\n\n#### File (YAML)\n\n```yaml\n# Static configuration\nexperimental:\n  localPlugins:\n    traefik-api-token-middleware:\n      moduleName: \"github.com/Aetherinox/traefik-api-token-middleware\"\n      version: \"v0.1.4\"\n```\n\n\u003cbr /\u003e\n\n#### File (TOML)\n\n```toml\n# Static configuration\n[experimental.localPlugins.traefik-api-token-middleware]\n  moduleName = \"github.com/Aetherinox/traefik-api-token-middleware\"\n  version = \"v0.1.4\"\n```\n\n\u003cbr /\u003e\n\n### Dynamic File\nFor local installation, your dynamic file will contain the same contents as it would if you installed the plugin normally.\n\n\u003cbr /\u003e\n\n#### File (YAML)\n\n```yaml\n# Dynamic configuration\nhttp:\n  middlewares:\n    api-token:\n      plugin:\n        traefik-api-token-middleware:\n          authenticationHeader: true\n          authenticationHeaderName: X-API-TOKEN\n          authenticationErrorMsg: \"Invalid token\"\n          bearerHeader: true\n          bearerHeaderName: Authorization\n          removeHeadersOnSuccess: true\n          removeTokenNameOnFailure: false\n          timestampUnix: false\n          tokens:\n            - your-api-token\n```\n\n\u003cbr /\u003e\n\n#### File (TOML)\n\n```toml\n# Dynamic configuration\n[http]\n  [http.middlewares]\n    [http.middlewares.api-token]\n      [http.middlewares.api-token.plugin]\n        [http.middlewares.api-token.plugin.traefik-api-token-middleware]\n          authenticationHeader = true\n          authenticationHeaderName = \"X-API-TOKEN\"\n          authenticationErrorMsg = \"Invalid token\"\n          bearerHeader = true\n          bearerHeaderName = \"Authorization\"\n          removeHeadersOnSuccess = true\n          removeTokenNameOnFailure = false\n          timestampUnix = false\n          tokens = [\"your-api-token\"]\n```\n\n\n\u003cbr /\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Contributors ✨\nWe are always looking for contributors. If you feel that you can provide something useful to Gistr, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources:\n\n- [Pull Request Procedure](.github/PULL_REQUEST_TEMPLATE.md)\n- [Contributor Policy](CONTRIBUTING.md)\n\n\u003cbr /\u003e\n\nWant to help but can't write code?\n- Review [active questions by our community](https://github.com/Aetherinox/traefik-api-token-middleware/labels/help%20wanted) and answer the ones you know.\n\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n![Alt](https://repobeats.axiom.co/api/embed/3a528b94b5433fa1f9763340435c6071716e7dca.svg \"analytics image\")\n\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\nThe following people have helped get this project going:\n\n\u003cbr /\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --\u003e\n[![Contributors][contribs-all-img]](#contributors-)\n\u003c!-- ALL-CONTRIBUTORS-BADGE:END --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\"\u003e\u003ca href=\"https://gitlab.com/Aetherinox\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/118329232?v=4?s=40\" width=\"80px;\" alt=\"Aetherinox\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAetherinox\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/Aetherinox/traefik-api-token-middleware/commits?author=Aetherinox\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#projectManagement-Aetherinox\" title=\"Project Management\"\u003e📆\u003c/a\u003e \u003ca href=\"#fundingFinding-Aetherinox\" title=\"Funding Finding\"\u003e🔍\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\n\u003c!-- BADGE \u003e GENERAL --\u003e\n  [general-npmjs-uri]: https://npmjs.com\n  [general-nodejs-uri]: https://nodejs.org\n  [general-npmtrends-uri]: http://npmtrends.com/traefik-api-token-middleware\n\n\u003c!-- BADGE \u003e VERSION \u003e GITHUB --\u003e\n  [github-version-img]: https://img.shields.io/github/v/tag/Aetherinox/traefik-api-token-middleware?logo=GitHub\u0026label=Version\u0026color=ba5225\n  [github-version-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/releases\n\n\u003c!-- BADGE \u003e VERSION \u003e NPMJS --\u003e\n  [npm-version-img]: https://img.shields.io/npm/v/traefik-api-token-middleware?logo=npm\u0026label=Version\u0026color=ba5225\n  [npm-version-uri]: https://npmjs.com/package/traefik-api-token-middleware\n\n\u003c!-- BADGE \u003e VERSION \u003e PYPI --\u003e\n  [pypi-version-img]: https://img.shields.io/pypi/v/traefik-api-token-middleware-plugin\n  [pypi-version-uri]: https://pypi.org/project/traefik-api-token-middleware-plugin/\n\n\u003c!-- BADGE \u003e LICENSE \u003e MIT --\u003e\n  [license-mit-img]: https://img.shields.io/badge/MIT-FFF?logo=creativecommons\u0026logoColor=FFFFFF\u0026label=License\u0026color=9d29a0\n  [license-mit-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/blob/main/LICENSE\n\n\u003c!-- BADGE \u003e GITHUB \u003e DOWNLOAD COUNT --\u003e\n  [github-downloads-img]: https://img.shields.io/github/downloads/Aetherinox/traefik-api-token-middleware/total?logo=github\u0026logoColor=FFFFFF\u0026label=Downloads\u0026color=376892\n  [github-downloads-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/releases\n\n\u003c!-- BADGE \u003e NPMJS \u003e DOWNLOAD COUNT --\u003e\n  [npmjs-downloads-img]: https://img.shields.io/npm/dw/%40aetherinox%2Ftraefik-api-token-middleware?logo=npm\u0026\u0026label=Downloads\u0026color=376892\n  [npmjs-downloads-uri]: https://npmjs.com/package/traefik-api-token-middleware\n\n\u003c!-- BADGE \u003e GITHUB \u003e DOWNLOAD SIZE --\u003e\n  [github-size-img]: https://img.shields.io/github/repo-size/Aetherinox/traefik-api-token-middleware?logo=github\u0026label=Size\u0026color=59702a\n  [github-size-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/releases\n\n\u003c!-- BADGE \u003e NPMJS \u003e DOWNLOAD SIZE --\u003e\n  [npmjs-size-img]: https://img.shields.io/npm/unpacked-size/traefik-api-token-middleware/latest?logo=npm\u0026label=Size\u0026color=59702a\n  [npmjs-size-uri]: https://npmjs.com/package/traefik-api-token-middleware\n\n\u003c!-- BADGE \u003e CODECOV \u003e COVERAGE --\u003e\n  [codecov-coverage-img]: https://img.shields.io/codecov/c/github/Aetherinox/traefik-api-token-middleware?token=MPAVASGIOG\u0026logo=codecov\u0026logoColor=FFFFFF\u0026label=Coverage\u0026color=354b9e\n  [codecov-coverage-uri]: https://codecov.io/github/Aetherinox/traefik-api-token-middleware\n\n\u003c!-- BADGE \u003e ALL CONTRIBUTORS --\u003e\n  [contribs-all-img]: https://img.shields.io/github/all-contributors/Aetherinox/traefik-api-token-middleware?logo=contributorcovenant\u0026color=de1f6f\u0026label=contributors\n  [contribs-all-uri]: https://github.com/all-contributors/all-contributors\n\n\u003c!-- BADGE \u003e GITHUB \u003e BUILD \u003e NPM --\u003e\n  [github-build-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/traefik-api-token-middleware/release.yml?logo=github\u0026logoColor=FFFFFF\u0026label=Build\u0026color=%23278b30\n  [github-build-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/actions/workflows/release.yml\n\n\u003c!-- BADGE \u003e GITHUB \u003e BUILD \u003e Pypi --\u003e\n  [github-build-pypi-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/traefik-api-token-middleware/release-pypi.yml?logo=github\u0026logoColor=FFFFFF\u0026label=Build\u0026color=%23278b30\n  [github-build-pypi-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/actions/workflows/pypi-release.yml\n\n\u003c!-- BADGE \u003e GITHUB \u003e TESTS --\u003e\n  [github-tests-img]: https://img.shields.io/github/actions/workflow/status/Aetherinox/traefik-api-token-middleware/tests.yml?logo=github\u0026label=Tests\u0026color=2c6488\n  [github-tests-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/actions/workflows/tests.yml\n\n\u003c!-- BADGE \u003e GITHUB \u003e COMMIT --\u003e\n  [github-commit-img]: https://img.shields.io/github/last-commit/Aetherinox/traefik-api-token-middleware?logo=conventionalcommits\u0026logoColor=FFFFFF\u0026label=Last%20Commit\u0026color=313131\n  [github-commit-uri]: https://github.com/Aetherinox/traefik-api-token-middleware/commits/main/\n\n\u003c!-- prettier-ignore-end --\u003e\n\u003c!-- markdownlint-restore --\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faetherinox%2Ftraefik-api-token-middleware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faetherinox%2Ftraefik-api-token-middleware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faetherinox%2Ftraefik-api-token-middleware/lists"}