{"id":21296869,"url":"https://github.com/reddec/token-login","last_synced_at":"2025-07-11T17:32:03.569Z","repository":{"id":162208192,"uuid":"635847809","full_name":"reddec/token-login","owner":"reddec","description":"The forward-auth server for API keys authorization","archived":false,"fork":false,"pushed_at":"2024-05-15T04:48:44.000Z","size":234,"stargazers_count":14,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-02T11:02:04.203Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reddec.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}},"created_at":"2023-05-03T15:23:02.000Z","updated_at":"2024-07-06T00:22:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"6093f42d-e53a-439b-9619-6c64acbef50a","html_url":"https://github.com/reddec/token-login","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/reddec/token-login","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Ftoken-login","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Ftoken-login/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Ftoken-login/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Ftoken-login/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reddec","download_url":"https://codeload.github.com/reddec/token-login/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reddec%2Ftoken-login/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264862470,"owners_count":23674980,"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","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":[],"created_at":"2024-11-21T14:30:17.029Z","updated_at":"2025-07-11T17:32:03.195Z","avatar_url":"https://github.com/reddec.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Token-login\n\n![logo](docs/logo.svg)\n\nThe authorization system based on tokens.\n\nToken-login is a server that functions as a [forward auth](https://doc.traefik.io/traefik/middlewares/http/forwardauth/)\nserver and provides an authorization flow for requests based\non [API keys](https://swagger.io/docs/specification/authentication/api-keys/).\nThe server is [designed](#architecture) with security as the top priority and offers a clean administrative UI,\nhigh-performance\nvalidation flow, and various [configuration options](#configuration).\n\nUsers can use [pre-built packages](https://github.com/reddec/token-login/releases/latest) available for all major\noperating systems, as well as [docker containers](https://github.com/reddec/token-login/pkgs/container/token-login) for\nboth arm64 and AMD64 architectures. The system is resource-efficient, making it easy to deploy on a wide range of\ndevices, from Raspberry Pi to Xeon multi-core cloud servers.\n\nAll components of Token-login are designed to work in a cloud-native environment, allowing users to utilize it as a\nstandalone application, as part of container deployment (e.g., docker-compose), or as part of a Kubernetes cluster.\n\nSince 1.2.0 token-login offers a comprehensive secure [API](openapi.yaml) with full parity to UI.\n\n**main page**\n\n![main](https://github.com/reddec/token-login/assets/6597086/4d73e838-f135-4c47-9ed2-39c06e572341)\n\n**details**\n\n![details](https://github.com/reddec/token-login/assets/6597086/d8b06c71-23b1-4684-a034-1ad72c27d1a3)\n\n## Installation\n\nQuick \u0026 dirty run for local environment (UI will be available on http://127.0.0.1:8080, `admin/admin`)\n\n    docker run --rm -p 8080:8080 -p 8081:8081 ghcr.io/reddec/token-login\n\n### Binary\n\nPre-built binary releases for most major platforms (Linux/Windows/Mac) for AMD64 and ARM64 platforms can be found in\n[releases](https://github.com/reddec/token-login/releases/latest) section.\n\n## From source\n\nRequires Go 1.20+\n\n    go install github.com/reddec/token-login/cmd/...@latest\n\n### Docker\n\nDocker images are built for AMD64 and ARM64 and stored\nin [Github Container repository](https://github.com/reddec/token-login/pkgs/container/token-login) and available as:\n\n- tagged version with exact release version (`major.minor.patch`) - use it if you want to freeze current setup\n- tagged version with minor version (`major.minor`) - use it if you want to get updates but no new features, recommended\n  for high-risk production setup\n- tagged version with major version (`major`) - use it you want to get updates and new features, recommended for most\n  cases\n- latest version with tag `latest` - use it if you don't care, not recommended in production\n\nThe token-login doesn't require any high privileged permissions and should support rootless setups (such as `podman`),\nhowever, this mode is not under our regular test cases.\n\n#### Complete examples\n\nAll examples are serving:\n\n- http://127.0.0.1:8080 - backend simulation\n- http://127.0.0.1:8080/tokens/ - admin UI\n\nTo test backend, create token and add it to the request url `?token=\u003ctoken\u003e` or to header `X-Token`\n\n    curl -v http://127.0.0.1:8080?token\u003ctoken\u003e\n    curl -v -H 'X-Token: \u003ctoken\u003e' http://127.0.0.1:8080\n\n**Minimal with Caddy**. See [example](examples/caddy)\n\n    docker compose -f examples/caddy/docker-compose.yaml up\n\n**Minimal with Nginx**. See [example](examples/nginx)\n\n    docker compose -f examples/nginx/docker-compose.yaml up\n\n**Minimal with traefik**. See [example](examples/traefik)\n\n    docker compose -f examples/traefik/docker-compose.yaml up\n\n**Caddy + Postgres**. See [example](examples/caddy-postgres)\n\n    docker compose -f examples/caddy-postgres/docker-compose.yaml up\n\n**Caddy + Postgres + Redis + OIDC**. See [example](examples/caddy-postgres-redis)\n\n\u003e This example requires changes in docker-compose file: set your OIDC credentials here before start.\n\n    docker compose -f examples/caddy-postgres/docker-compose.yaml up\n\n**Kubernetes Ingress Nginx**\n\n```yaml\nannotations:\n  # put any other headers you want to copy from response\n  nginx.ingress.kubernetes.io/auth-response-headers: x-user\n  nginx.ingress.kubernetes.io/auth-url: http://tokens.tokens.svc.cluster.local\n  nginx.ingress.kubernetes.io/auth-snippet: |\n    proxy_set_header X-Forwarded-Uri $request_uri;\n```\n\n**Kustomization** - [example here](./examples/kustomize)\n\n## Versioning\n\nThe Token login follows a classic semantic versioning approach, where the major version indicates forward compatibility\nguarantees, the minor version indicates new features, and the patch version indicates patches without new features. All\nforward migrations, i.e., increasing the release version, are performed automatically during the application startup.\nHowever, backward migrations are possible but not recommended, as they pose a risk, and should be carried out at your\nown discretion.\n\n## License\n\nThe server is licensed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license using Exhibit A. This means\nthat the software is available for all kinds of usage, including commercial usage, as long as the source code is not\nmodified. However, if the source code is modified, it is required to be shared. In essence, you are free to use the\nsoftware however you wish but share any changes.\n\n# Configuration\n\nThe token-login tool offers a range of configurable options that can be fine-tuned to suit a wide variety of use cases.\nNonetheless, its default settings are optimized for general usage, making plain `token-login` with no arguments a\nreliable\nchoice for development purposes.\n\nFor production use, it's strongly recommended to configure at least the [authorization](#authorization) setting.\n\nAll configuration parameters can be set via command line arguments and/or environment variables.\n\n```\nUsage:\n  token-login [OPTIONS]\n\nForward-auth server for tokens\ntoken-login dev, commit none, built at unknown by unknown\nAuthor: Aleksandr Baryshnikov \u003cowner@reddec.net\u003e\n\nApplication Options:\n      --login=[basic|oidc|proxy]   Login method for admin UI (default: basic) [$LOGIN]\n\nAdmin server configuration:\n      --admin.bind=                Bind address (default: :8080) [$ADMIN_BIND]\n      --admin.tls                  Enable TLS [$ADMIN_TLS]\n      --admin.ca=                  Path to CA files. Optional unless IGNORE_SYSTEM_CA set (default: ca.pem) [$ADMIN_CA]\n      --admin.cert=                Server certificate (default: cert.pem) [$ADMIN_CERT]\n      --admin.key=                 Server private key (default: key.pem) [$ADMIN_KEY]\n      --admin.mutual               Enable mutual TLS [$ADMIN_MUTUAL]\n      --admin.ignore-system-ca     Do not load system-wide CA [$ADMIN_IGNORE_SYSTEM_CA]\n      --admin.read-header-timeout= How long to read header from the request (default: 3s) [$ADMIN_READ_HEADER_TIMEOUT]\n      --admin.graceful=            Graceful shutdown timeout (default: 5s) [$ADMIN_GRACEFUL]\n\nAuth server configuration:\n      --auth.bind=                 Bind address (default: :8081) [$AUTH_BIND]\n      --auth.tls                   Enable TLS [$AUTH_TLS]\n      --auth.ca=                   Path to CA files. Optional unless IGNORE_SYSTEM_CA set (default: ca.pem) [$AUTH_CA]\n      --auth.cert=                 Server certificate (default: cert.pem) [$AUTH_CERT]\n      --auth.key=                  Server private key (default: key.pem) [$AUTH_KEY]\n      --auth.mutual                Enable mutual TLS [$AUTH_MUTUAL]\n      --auth.ignore-system-ca      Do not load system-wide CA [$AUTH_IGNORE_SYSTEM_CA]\n      --auth.read-header-timeout=  How long to read header from the request (default: 3s) [$AUTH_READ_HEADER_TIMEOUT]\n      --auth.graceful=             Graceful shutdown timeout (default: 5s) [$AUTH_GRACEFUL]\n\nOIDC login config:\n      --oidc.client-id=            Client ID [$OIDC_CLIENT_ID]\n      --oidc.client-secret=        Client secret [$OIDC_CLIENT_SECRET]\n      --oidc.issuer=               OIDC issuer URL [$OIDC_ISSUER]\n      --oidc.session=[local|redis] Session storage (default: local) [$OIDC_SESSION]\n      --oidc.server-url=           (optional) public server URL for redirects [$OIDC_SERVER_URL]\n      --oidc.emails=               Allowed emails (enabled if at least one set) [$OIDC_EMAILS]\n\nOIDC Redis session configuration:\n      --oidc.redis.url=            Redis URL (default: redis://redis) [$OIDC_REDIS_URL]\n      --oidc.redis.keep-alive=     Keep-alive interval (default: 30s) [$OIDC_REDIS_KEEP_ALIVE]\n      --oidc.redis.timeout=        Read/Write/Connect timeout (default: 5s) [$OIDC_REDIS_TIMEOUT]\n      --oidc.redis.max-conn=       Maximum number of active connections (default: 10) [$OIDC_REDIS_MAX_CONN]\n      --oidc.redis.max-idle=       Maximum number of idle connections (default: 1) [$OIDC_REDIS_MAX_IDLE]\n      --oidc.redis.idle-timeout=   Close connections after remaining idle for this duration (default: 30s) [$OIDC_REDIS_IDLE_TIMEOUT]\n\nBasic login config:\n      --basic.realm=               Realm name (default: token-login) [$BASIC_REALM]\n      --basic.user=                User name (default: admin) [$BASIC_USER]\n      --basic.password=            User password hash from bcrypt (default: $2y$05$d1BT6ay8qzViEGUjo4UDkOatWkFlszDfyzaXxCkM84kVhEJLtkXcu) [$BASIC_PASSWORD]\n\nProxy login config:\n      --proxy.header=              Header which will contain user name (default: X-User) [$PROXY_HEADER]\n      --proxy.logout=              Logout redirect [$PROXY_LOGOUT]\n\nDatabase configuration:\n      --db.url=                    Database URL (default: sqlite://data.sqlite?cache=shared\u0026_fk=1\u0026_pragma=foreign_keys(1)) [$DB_URL]\n      --db.max-conn=               Maximum number of opened connections to database (default: 10) [$DB_MAX_CONN]\n      --db.idle-conn=              Maximum number of idle connections to database (default: 1) [$DB_IDLE_CONN]\n      --db.idle-timeout=           Maximum amount of time a connection may be idle (default: 0) [$DB_IDLE_TIMEOUT]\n      --db.conn-life-time=         Maximum amount of time a connection may be reused (default: 0) [$DB_CONN_LIFE_TIME]\n\nCache configuration:\n      --cache.ttl=                 Maximum live time of token in cache. Also forceful reload time (default: 15s) [$CACHE_TTL]\n\nStats configuration:\n      --stats.buffer=              Buffer size for hits (default: 2048) [$STATS_BUFFER]\n      --stats.interval=            Statistics interval (default: 5s) [$STATS_INTERVAL]\n\nDebug:\n      --debug.enable               Enable debug mode [$DEBUG_ENABLE]\n      --debug.impersonate=         Disable normal auth and use static user name [$DEBUG_IMPERSONATE]\n\nHelp Options:\n  -h, --help                       Show this help message\n```\n\n## Stats\n\ntoken-login has the capability to periodically transfer from the internal in-memory statistics to a persistent\ndatabase. These statistics encompass usage count and last access date. The interval of this transfer is adjustable, and\nserves as a balance between the load on the database and the accuracy/actuality of the statistics.\n\n    Stats configuration:\n\n      --stats.buffer=              Buffer size for hits (default: 2048) [$STATS_BUFFER]\n      --stats.interval=            Statistics interval (default: 5s) [$STATS_INTERVAL]\n\nFor example, dump stats every minute:\n\n    token-login --stats.interval 1m\n\n## HTTP server\n\nToken-login provides two HTTP servers: one for the administrator user interface (Admin UI) and one for forward\nauthentication (Auth). Both servers can be configured in the same way and share the same default values, except for the\nbinding addresses. The default address for Admin UI is `:8080`, while for Auth it is `:8081`.\n\nHTTP servers support TLS, which is enabled by using the `--tls` flag. This feature is disabled by default. There is also\nan option to ignore system certificates by using the `--ignore-system-ca` flag. This can be useful in untrusted or\nminimalistic environments. Additionally, mutual TLS (`--mutual`) can be used for added security between participants.\n\nDuring normal shutdown, the server will be up to `--graceful` timeout, which is set to 5 seconds by default, before\nforcefully killing existing connections.\n\nThe Auth server has an endpoint for health checks (`/health`), which returns a 204 status code. This can be used to\nverify the server's status.\n\n    Admin server configuration:\n      --admin.bind=                Bind address (default: :8080) [$ADMIN_BIND]\n      --admin.tls                  Enable TLS [$ADMIN_TLS]\n      --admin.ca=                  Path to CA files. Optional unless IGNORE_SYSTEM_CA set (default: ca.pem) [$ADMIN_CA]\n      --admin.cert=                Server certificate (default: cert.pem) [$ADMIN_CERT]\n      --admin.key=                 Server private key (default: key.pem) [$ADMIN_KEY]\n      --admin.mutual               Enable mutual TLS [$ADMIN_MUTUAL]\n      --admin.ignore-system-ca     Do not load system-wide CA [$ADMIN_IGNORE_SYSTEM_CA]\n      --admin.graceful=            Graceful shutdown timeout (default: 5s) [$ADMIN_GRACEFUL]\n\n    Auth server configuration:\n      --auth.bind=                 Bind address (default: :8081) [$AUTH_BIND]\n      --auth.tls                   Enable TLS [$AUTH_TLS]\n      --auth.ca=                   Path to CA files. Optional unless IGNORE_SYSTEM_CA set (default: ca.pem) [$AUTH_CA]\n      --auth.cert=                 Server certificate (default: cert.pem) [$AUTH_CERT]\n      --auth.key=                  Server private key (default: key.pem) [$AUTH_KEY]\n      --auth.mutual                Enable mutual TLS [$AUTH_MUTUAL]\n      --auth.ignore-system-ca      Do not load system-wide CA [$AUTH_IGNORE_SYSTEM_CA]\n      --auth.graceful=             Graceful shutdown timeout (default: 5s) [$AUTH_GRACEFUL]\n\nFor example, to increase Auth server graceful shutdown to 1 minute:\n\n    token-login --auth.graceful 1m\n\n## Storage\n\nToken-login can be used with popular databases like SQLite or Postgres, and automatically manages schema migration.\n\nYou can easily specify the database type by including the corresponding schema in the URL. For example, use `sqlite://`\nfor SQLite, `postgres://` for PostgreSQL, and `mysql://` for MySQL.\n\nBy default, token-login uses a SQLite database stored locally in the file `data.sqlite`.\n\nThe default values for advanced parameters should suffice for most use cases, but you can customize the configuration by\nusing the `--help` command to view the available options in the \"Database Configuration\" section.\n\n     Database configuration:\n      --db.url=                    Database URL (default: sqlite://data.sqlite?cache=shared) [$DB_URL]\n      --db.max-conn=               Maximum number of opened connections to database (default: 10) [$DB_MAX_CONN]\n      --db.idle-conn=              Maximum number of idle connections to database (default: 1) [$DB_IDLE_CONN]\n      --db.idle-timeout=           Maximum amount of time a connection may be idle (default: 0) [$DB_IDLE_TIMEOUT]\n      --db.conn-life-time=         Maximum amount of time a connection may be reused (default: 0) [$DB_CONN_LIFE_TIME]\n\nFor example with Postgres (user and password `postgress`, host - `db`):\n\n    token-login --db.url \"postgres://postgres:postgres@db\"\n\n## Cache\n\nTo optimize performance and reduce the load on the database, token-login uses an internal in-memory cache. The cache\nhas a configurable TTL (time-to-live). Although an external cache system may be explored\nin the future, the current approach should be adequate for most use cases. It also eliminates several security and\nlogical concerns that can arise with external caches.\n\nPlease check [Security](#security) section for possible security impact.\n\n    Cache configuration:\n      --cache.ttl=                 Maximum live time of token in cache (default: 15s) [$CACHE_TTL]\n\nFor example, with cache TTL 1 minute:\n\n    token-login --cache.ttl 1m\n\n## Authorization\n\ntoken-login offers several ways to protect the administrator interface (Admin UI):\nBasic Authentication (`--login basic`, which is the default), OpenID Connect (`--login oidc`), and\nProxy (`--login proxy`).\n\nWhile [Basic Authentication](#basic-auth) provides a simple and easy-to-use solution, we highly recommend using OpenID\nConnect or Proxy methods in production environments. [OpenID Connect](#oidc-login) offers more advanced features, such\nas Single Sign-On (SSO), multi-user authentication, and fine-grained access control.\n\nThe Proxy method operates on the principle of pre-service authorization, employing headers to authenticate users. This\napproach is frequently utilized in scenarios such as Single Sign-On (SSO), OAuth2-proxy, Authentik gateway, or Authelia.\nIt ensures that access to services is authenticated before reaching the token-login.\n\n### Basic auth\n\n[Basic Authorization](https://en.wikipedia.org/wiki/Basic_access_authentication) is a method for sending a username and\npassword combination over the internet as part of an HTTP request, typically to access a protected resource.\nThe server then verifies the credentials, and if they are correct, it grants access to the requested resource.\n\nFrom UX point of view, browser will show pop-up native dialog asking username and password.\n\n\u003e Basic auth is very convenient for small setups, but it's less flexible (single user) and slower (due to bcrypt) than\n\u003e OIDC.\n\u003e\n\u003e We highly recommend use [OIDC](#oidc-auth) provider (cloud (Auth0, Okta, Google - dozens of them) or self-hosted such\n\u003e as Keycloak or Authentik) in production.\n\nDefault credentials: `admin/admin`. **CHANGE IT! Never use default credentials in production.**\n\nBasic auth password (`--basic.password / $BASIC_PASSWORD`) should be set in BCrypt hash like this:\n\n    htpasswd -nbB user \u003cpassword\u003e | cut -d ':' -f 2\n\nFor example, with user `test` and password `test`:\n\n    token-login --basic.user test --basic.password '$2y$05$.mUKHq3ANDgcGf2fCBZabOsD9TF94aWIsCQUBvsodocPjf/9lQF12'\n\nOptionally, you may configure authorization scope (brand/instance/title) by changing realm setting\nin `--basic.realm \"my-token-login\"`.\n\n### OIDC login\n\n[OpenID Connect](https://openid.net/connect/) login is a method of authentication that allows users to use their\nexisting\naccounts on other websites to log in to a different website or application.\n\nWhen you use OIDC login, you don't have to create a new username and password for token-login.\nInstead, you can log in using an existing account such as your Google or Okta account.\n\nThe way it works is that the application sends a request to your existing account\nprovider, and you are redirected to their login page. Once you enter your credentials and verify your identity,\ntoken-login receives confirmation of your identity and grants you access.\n\nOIDC login is convenient for users because they don't have to remember multiple usernames and passwords, and it's secure\nbecause the application never sees your actual login information.\n\n\u003e Recommended for production\n\nToken-login supports Authorization Code and Client Credentials flow.\n\nThere is an option to enable email filtering for users who have signed in with OIDC, but it is advised to use\npermission segregation on the IDP level instead.\n\nTo use token-login, you only need to fill in the `client-id`, `client-secret`, and `client-issuer` parameters. However,\nif you're planning to use it for production purposes, we recommend setting the `server-url` parameter for public server\nURL, unless you have control over `X-Forwarded-Host` and `X-Forwarded-Proto` headers through a reverse proxy.\nAdditionally, it's a good idea to use persistent session storage, so make sure to check out the `redis.*` options for\nthat.\n\n```\nOIDC login config:\n      --oidc.client-id=            Client ID [$OIDC_CLIENT_ID]\n      --oidc.client-secret=        Client secret [$OIDC_CLIENT_SECRET]\n      --oidc.issuer=               OIDC issuer URL [$OIDC_ISSUER]\n      --oidc.session=[local|redis] Session storage (default: local) [$OIDC_SESSION]\n      --oidc.server-url=           (optional) public server URL for redirects [$OIDC_SERVER_URL]\n      --oidc.emails=               Allowed emails (enabled if at least one set) [$OIDC_EMAILS]\n\nOIDC Redis session configuration:\n      --oidc.redis.url=            Redis URL (default: redis://redis) [$OIDC_REDIS_URL]\n      --oidc.redis.keep-alive=     Keep-alive interval (default: 30s) [$OIDC_REDIS_KEEP_ALIVE]\n      --oidc.redis.timeout=        Read/Write/Connect timeout (default: 5s) [$OIDC_REDIS_TIMEOUT]\n      --oidc.redis.max-conn=       Maximum number of active connections (default: 10) [$OIDC_REDIS_MAX_CONN]\n      --oidc.redis.max-idle=       Maximum number of idle connections (default: 1) [$OIDC_REDIS_MAX_IDLE]\n      --oidc.redis.idle-timeout=   Close connections after remaining idle for this duration (default: 30s) [$OIDC_REDIS_IDLE_TIMEOUT]\n```\n\nFor example:\n\n    token-login --login oidc --oidc.client-id example-client --oidc.client-secret my-secret --oidc.issuer https://my-idp.example.com\n\n### Proxy login\n\n\nProxy login most commonly used together with [auth sub-request](https://doc.traefik.io/traefik/middlewares/http/forwardauth/)\n\n```\nProxy login config:\n      --proxy.header=              Header which will contain user name (default: X-User) [$PROXY_HEADER]\n      --proxy.logout=              Logout redirect [$PROXY_LOGOUT]\n```\n\n* `proxy.logout` supports relative paths\n\nFor example:\n\n    token-login --login proxy\n\nWith custom header (default is `X-User`):\n\n\n    token-login --login proxy --proxy.header X-Web-User\n\n\nWith custom logout url:\n\n    token-login --login proxy --proxy.logout https://example.com/logout\n\n## Architecture\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant Reverse Proxy\n    participant token-login\nparticipant Service\nClient -\u003e\u003e+ Reverse Proxy: request + token\nReverse Proxy -\u003e\u003e+ token-login: validate request\ntoken-login -\u003e\u003e+ token-login: check token\nalt token and path allowed\ntoken-login -\u003e\u003e+ Reverse Proxy: 204 No Content + headers\nReverse Proxy -\u003e\u003e+ Service: request + headers\nService -\u003e\u003e+ Reverse Proxy: response\nReverse Proxy -\u003e\u003e+ Client: response\nelse token not allowed\ntoken-login -\u003e\u003e+ Reverse Proxy: 401 Unauthorized\nReverse Proxy -\u003e\u003e+ Client: 401 Unauthorized\nend\n```\n\nWhen the client sends a request along with a token to the reverse proxy, the reverse proxy forwards the request to the\ntoken-login server to validate the token. The token-login server checks the token and if the token and path are allowed,\nit returns a 204 No Content response along with headers to the reverse proxy.\n\nThe reverse proxy then forwards the request along with the headers to the service. The service processes the request and\nsends a response to the reverse proxy, which in turn sends the response back to the client.\n\nIf the token is not allowed, the token-login server returns a 401 Unauthorized response to the reverse proxy, which then\nsends the same response to the client.\n\nThe reverse proxy must provide the following headers:\n\n- `X-Forwarded-Uri` original URL, used for extracting `token` query parameter and for path validation\n- (optionally) `X-Token` header from the client request in order to get token. It's up to reverse proxy map other\n  headers to this one (e.g. `X-Api-Key`).\n\nThe token-login will return on success:\n\n- `X-User` user name that created token\n- `X-Token-Hint` unique identifier of the token\n- other headers, defined by user in token.\n\n### Design principles\n\nThe decisions guiding our architecture are based on three core principles: security, simplicity, and flexibility, in\nthat order of priority. Our top priority is to ensure that attackers cannot obtain access to protected resources by\nacquiring tokens.\n\nTo achieve this level of security, we have made certain trade-offs. For instance, we have narrowed the scope of our\nsystem, designed code that is easy to audit. In exchange the system is not 100% DoS proofed, however, even in case of\noverload/crash/whatever it is impossible to retrieve original tokens.\n\nEvery component of our system is designed with security in mind even in small details. For example, all credentials are\nirreversibly hashed, and all tokens are generated using a cryptographic random generator on the server-side. Tokens are\nstored in their original form for only a very short time required for hashing and storage. Moreover, all token\nvalidations are resistant to time-based attacks for the private part of the token.\n\nAdmin authentication can be delegated to an OpenID Connect provider. For local authentication(basic auth), passwords\nmust be hashed via bcrypt2.\n\n### Token generation\n\n    | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |             ....          | 39 |\n    | \u003c--        8 bytes        --\u003e | \u003c--           32 bytes         --\u003e |\n    | \u003c--         key ID        --\u003e | \u003c-- key payload (hashed in DB) --\u003e |\n\nA token consists of two distinct parts. The first part comprises 8 bytes of randomly generated data, which are securely\ngenerated and placed at the beginning of the token. The second part comprises 32 bytes of randomly generated data that\nhave been hashed using the SHA-384 algorithm. The raw value of private part is known only during the token generation\nprocess and is stored irreversibly hashed in both the database and cache. The public part of the token, known as the \"\nkey hint\" or \"key id,\" functions as a unique identifier (think about it as username) that is used to locate the\ncorresponding private key in the database. The key ID is system-wide unique; the uniqueness is checked during the token\ncreation. Further information regarding the security measures can be found in the [security](#security) section.\n\nUser token representation is token encoded in Base32 without padding. Case-**insensitive**.\n\n### Security\n\nThe tokens are irreversibly hashed using SHA-384 for security reasons. Although SHA-384 is not a key derivation\nfunction (KDF), it provides a secure hash of the original token, which is generated from a crypto-secure pure-random\n32-byte source with around 2^256 entropy. This makes it practically impossible to brute force the token within a\nreasonable time frame, without requiring the use of a KDF, which is typically used for key-space limited sources such as\nuser passwords.\n\nBruteforce math:\n\n- 32 bytes token means $X = (2^8)^{32} = 2^{256}$ combinations\n- with birthday paradox and other staff in mind, we can assume, that there is high risk of collisions\n  in $Y = \\sqrt{X} = (2^{256})^{0.5} = 2^{128}$\n- let's assume that one hash can be computed per 1 ns (in real life 300-500ns) per one core, which gives us $p = 10^9$\n  hashes/second\n- let's assume that we are in the future, total population is 100B ($10^{11}$) people, each person has 10000 ($10^4$)\n  cores\n  device,\n  whole population will 24/7 trying to brute-force our hash: $P = p \\cdot 10^{11} \\cdot 10^4 = p \\cdot 10^{15} =\n  10^{24}$ hashes/second.\n- To simplify (and round up): $10^{24} \\lt (2^4)^{24} \\to 2^{96} = W$ hashes/second\n- Total time in seconds: $\\frac{Y}{W} = \\frac{2^{128}}{2^{96}} = 2^{32} (seconds) \\approx 136 (years)$ (A LOT)\n\nIt's worth noting that while the token stored in hashes only, it's still highly recommended to renew all\ntokens in the event of a storage compromise.\n\nTo enhance system performance, tokens are cached locally in a cache with a configurable\ntime-to-live (TTL) for each cached item. The TTL can be adjusted based on system requirements.\nHowever, it's critical to prioritize security considerations when determining these parameters. Increasing the TTL may\nresult in longer latencies for reflecting\nchanges in the token store and local cache. It's important to note that when using authentication tokens with a high\nTTL, there is a risk that a refreshed or removed token may still be available in cache and used for\nauthorization. It's important to maintain an appropriate balance between performance and security when tuning these\nconfigurations.\n\n# Contributing\n\nRequirements:\n\n- go (see version in go.mod)\n- make\n- node + npm LTS (UI only)\n- docker\n\nFor debugging\n\n```\ngo run ./cmd/token-login/main.go --debug.enable --debug.impersonate admin\n```\n\nFor tests\n\n```\nmake test\n```\n\nFor local snapshot\n\n```\nmake snapshot\n```\n\n# Changelog\n\n## 1.2.0\n\n- `--stats-interval` moved to `--stats.interval`\n- `--cache.limit` removed; all keys are cached in memory","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freddec%2Ftoken-login","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freddec%2Ftoken-login","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freddec%2Ftoken-login/lists"}