{"id":29146424,"url":"https://github.com/colstrom/niftygate","last_synced_at":"2025-06-30T21:11:45.088Z","repository":{"id":43424960,"uuid":"359929382","full_name":"colstrom/niftygate","owner":"colstrom","description":"Drop-in Access Control via NFT Ownership","archived":false,"fork":false,"pushed_at":"2022-07-06T22:42:08.000Z","size":3135,"stargazers_count":72,"open_issues_count":1,"forks_count":14,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-06-29T00:42:33.820Z","etag":null,"topics":["decentralized-identity","digital-signature","erc1155","erc20","erc721","ethereum-contract","ethereum-token","nft","proxy","proxy-server","signature-verification","token-gating","web3"],"latest_commit_sha":null,"homepage":"","language":"Rust","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/colstrom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-20T19:29:01.000Z","updated_at":"2025-04-01T09:26:53.000Z","dependencies_parsed_at":"2022-09-02T14:10:49.813Z","dependency_job_id":null,"html_url":"https://github.com/colstrom/niftygate","commit_stats":null,"previous_names":["colstrom/sig-proxy"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/colstrom/niftygate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colstrom%2Fniftygate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colstrom%2Fniftygate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colstrom%2Fniftygate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colstrom%2Fniftygate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/colstrom","download_url":"https://codeload.github.com/colstrom/niftygate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/colstrom%2Fniftygate/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262850282,"owners_count":23374359,"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":["decentralized-identity","digital-signature","erc1155","erc20","erc721","ethereum-contract","ethereum-token","nft","proxy","proxy-server","signature-verification","token-gating","web3"],"created_at":"2025-06-30T21:11:44.219Z","updated_at":"2025-06-30T21:11:45.071Z","avatar_url":"https://github.com/colstrom.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# niftygate - Drop-in Access Control via NFT Ownership\n\n## The Pitch\n\nGate access to anything on the web, using any smart contract, deployed to any blockchain, without modifying your code.\n\n## Overview\n\nIf you think of a token like a ticket to your club, NiftyGate would be the bouncer at the door.\n\n- Compatible with the typical token standards, both fungible and not (ERC20, ERC721, ERC777, and ERC1155).\n- Plays nice with any blockchain that speaks Web3 via WebSockets.\n- Sits in front of anything that speaks HTTP.\n- Has an embedded mode for use with client applications.\n- Integrates with any auth system that supports HTTP headers.\n- Comes with tools for choosing, deploying, debugging, and auditing compatible smart contracts.\n- All shipped as single, self-contained binary.\n\n- Cross-platform (tested on Linux and macOS, should work elsewhere).\n- Open Source (MIT licensed), and written in Rust.\n\n## What is it?\n\n`niftygate` is a proxy for HTTP services, that validates signatures, providing\nan AuthN layer for those services. It also has functionality for clients,\nautomatically injecting signatures into requests.\n\n## What could I use this for?\n\nAs of `0.2`, Smart Contracts are supported. These allow using tokens as transferrable licenses to gated services.\n\nSome examples:\n\n- An OCI Registry that allowed licensed users to download an asset.\n- An Issue Tracker that allowed project supporters to get priority support.\n- A Project Roadmap that allowed customers proportional voting rights on feature development.\n- A Deployment Pipeline that required at N-of-M authorized users to release to production.\n- An App Store with decentralized licenses, where authors retain licensing control, not platforms.\n- A Digital Library where lending is managed by tokens, and returns are enforced by Smart Contracts.\n\n## Why does this exist?\n\nThis is really two questions, so let's break that down...\n\n### Why is this concept useful?\n\nSignature-based authentication avoids many of the pitfalls of password-based\nauthentication. The server only needs to know public keys, and if those are\nleaked... who cares? They're _public_ keys.\n\nAssuming a reasonable UI in both cases, users can rotate keys just as easily as\npasswords. They can delegate a subset of permissions to other keys (just as we\ndo with access tokens elsewhere).\n\nKeys are things users _generate_, not things users _memorize_. This removes\nproblems like password reuse entirely.\n\n### Why is this approach practical?\n\nImplementing this in the form of a proxy allows it to be applied to most existing\nHTTP(S) applications without modification.\n\nSeparating the signing from the verification allows more fine-grained control\nover what has access to private keys. It also means the proxy can be used only\nwhere needed. If a client application can handle signing natively, then it should.\n\nImplementing this as a set of composable middleware makes it simple to extend,\nand (responsibly) experiment with new features.\n\nIt can be deployed as a sidecar container, if you're into that sort of thing.\n\n## How do I obtain this majestic tool?\n\n```shell\ncargo install niftygate\n```\n\nOr, if you prefer Docker:\n\n```shell\ndocker pull colstrom/niftygate:0.8.0\n```\n\n## How do I use it?\n\nFirst, you'll need some sort of service you want to put the proxy in front of.\n\nFor demonstration and development purposes, `niftygate` includes an embedded\nsample service that prints the request headers in the response body.\n\n```shell\n$ niftygate demo\ntide::log Logger started\n    level DEBUG\ntide::server Server listening on http://127.0.0.1:8080\n```\n\nNext, you'll need to have an Ethereum JSON-RPC (Web3) service available for\n`niftygate` to interact with. [Ganache](https://www.trufflesuite.com/ganache)\nis an excellent option for local use, so the rest of this document assumes that.\n\nFirst, pick the address you want to use for signing requests:\n![screenshot showing how to choose an address in Ganache](assets/ganache-address.png)\n\nThen, find the private key for this address:\n![screenshot showing where to find a private key in Ganache](assets/ganache-private-key.png)\n\nAdd this private key to the environment:\n\nUsing `fish`:\n\n```shell\nset -x SECRET_KEY_DATA PUT_THE_DATA_HERE\n```\n\nUsing vintage shells like `bash`:\n\n```shell\nexport SECRET_KEY_DATA=PUT_THE_DATA_HERE\n```\n\nNow you're ready to run it! Let's have a look at the help:\n\n```shell\n$ niftygate web3 --help\n\nniftygate-web3 0.1.0\nRuns the proxy service\n\nUSAGE:\n    niftygate web3 [FLAGS] [OPTIONS]\n\nFLAGS:\n    -h, --help                             Prints help information\n    -V, --provides-account-verification    verify signatures and provide account addresses\n    -B, --provides-balances                provide account balances\n    -S, --provides-signatures              provide signatures\n        --version                          Prints version information\n\nOPTIONS:\n        --address-header \u003cname\u003e        [env: ADDRESS_HEADER=]    [default: X-Web3-Account-Address]\n    -b, --backend \u003curl\u003e                [env: BACKEND=]           [default: http://127.0.0.1:8080]\n        --balance-header \u003cname\u003e        [env: BALANCE_HEADER=]    [default: X-Web3-Account-Balance]\n        --balance-maximum \u003camount\u003e     [env: BALANCE_MAXIMUM=]\n        --balance-minimum \u003camount\u003e     [env: BALANCE_MINIMUM=]\n    -u, --balance-scale \u003cunit\u003e         [env: BALANCE_SCALE=]     [default: Wei]\n    -c, --challenge \u003cphrase\u003e           [env: CHALLENGE=]         [default: totes-legit]\n    -l, --listen \u003caddress\u003e             [env: LISTEN=]            [default: 0.0.0.0:8000]\n    -K, --secret-key-data \u003chex\u003e        [env: SECRET_KEY_DATA=]\n    -k, --secret-key-file \u003cpath\u003e       [env: SECRET_KEY_FILE=]\n        --signature-header \u003cname\u003e      [env: SIGNATURE_HEADER=]  [default: X-Web3-Signature]\n    -w, --web3-rpc-url \u003curl\u003e           [env: WEB3_RPC_URL=]      [default: ws://127.0.0.1:7545]\n```\n\nAll of those options are optional, though it doesn't **do** anything unless you\nenable at least one of them. Let's focus on two scenarios.\n\n### Scenario 1 - Providing Signatures\n\nIn this mode, `niftygate` adds a signature to every request it handles.\n\n```shell\n$ niftygate web3 --provides-signatures\ntide::log Logger started\n    level DEBUG\ntracing::span new\ntracing::span build\nisahc::agent agent waker listening on 127.0.0.1:61558\nisahc::agent agent_thread; port=61558\nisahc::agent agent took 409.705µs to start up\ntide::server Server listening on http://0.0.0.0:8000\n```\n\nA secret (private) key is needed to sign these requests, though. It can be given\nas a file (`--secret-key-file`), or a hex string (`--secret-key-data`). If both\nare given, `--secret-key-file` is ignored. These can also be given via\nenvironment, which is exactly what we did above.\n\nThis key is used to sign a challenge phrase (currently given by `--challenge`),\nwhich should be known to both client and server. It does not need to be private.\n\nThis signature is added to the request using the header given by `--signature-header`.\n\n### Scenario 2 - Providing Account Verification\n\nIn this mode, `niftygate` expects requests to contain a signature header, and\nwill reject requests that do not contain one. These headers will be verified,\nand the address used to sign them will be added to each request it handles.\n\nNote that the client does not explicitly provide an address. They sign a\nchallenge phrase that is known to both signer and verifier, and the signing\naddress is recoverable from a valid signature.\n\n```shell\n$ niftygate web3 --provides-account-verification\ntide::log Logger started\n    level DEBUG\ntracing::span new\ntracing::span build\nisahc::agent agent waker listening on 127.0.0.1:56181\nisahc::agent agent_thread; port=56181\nisahc::agent agent took 312.747µs to start up\ntide::server Server listening on http://0.0.0.0:8000\n```\n\nIf the signature is valid, the address is added to the request using the header\ngiven by `--address-header`. It is assumed that the backend knows what to do\nwith this header. For instance, you could use the `X-Remote-User` header to\nintegrate `niftygate` with [Dex](https://dexidp.io/docs/connectors/authproxy/).\n\n### Scenario 3 - Providing Account Balances\n\nIn this mode, `niftygate` expects requests to contain an account header, and\nwill reject requests that to not contain one. The balance of the address given\nin this header will be added to each request it handles.\n\n```shell\n$ niftygate web3 --provides-balances\ntide::log Logger started\n    level DEBUG\ntracing::span new\ntracing::span build\nisahc::agent agent waker listening on 127.0.0.1:54608\nisahc::agent agent_thread; port=54608\nisahc::agent agent took 313.524µs to start up\ntide::server Server listening on http://0.0.0.0:8000\n```\n\nBy default, this doesn't care _what_ the balance is, it just adds it to the\nheader given by `--balance-header`. However, there are a few options to restrict\naccess based on the balance.\n\nThe `--balance-minimum` option can be used to require a minimum balance. This\ncan be used as a form of \"skin in the game\", by requiring a non-zero balance\n(which may be useful in to prevent bots or assist rate limiting), or to gate\naccess to only high rollers if you wanted to do that for some reason.\n\nThe `--balance-maximum` option can be used to reject accounts with a balance\nover a given amount. This can be used to limit risk, or gate access to only the\ncommon folk if you were so inclined.\n\nThe `--balance-unit` option can be used to conveniently scale the above limits.\nHow many zeroes are there in a Gwei? No need to remember, just set\n`--balance-unit=Gwei` and `niftygate` will do the scaling internally. The\nbalance header will still be given in Wei, though.\n\n## Notes\n\nThe examples above show demonstrate using the features independently, but they\nare all implemented as composable middleware. You can enable all of them in a\nsingle process. It seems a bit silly to use both signing and verifying in the\nsame process, but there's no reason you **can't** do it.\n\n## Try it out!\n\nAssuming you've enabled all the features, and the proxy is in front of the demo\napplication, if you were to query each with `curl`, you'd see something like the\nfollowing:\n\nQuerying the demo app directly:\n\n```shell\n$ curl -s http://127.0.0.1:8080 | sort\naccept: [\"*/*\"]\nhost: [\"127.0.0.1:8080\"]\nuser-agent: [\"curl/7.64.1\"]\n```\n\nQuerying through the proxy:\n\n```shell\n$ curl -s http://127.0.0.1:8000 | sort\naccept-encoding: [\"deflate, gzip\"]\naccept: [\"*/*\"]\ncontent-length: [\"0\"]\ncontent-type: [\"application/octet-stream\"]\nforwarded: [\"by=127.0.0.1:8000;for=\\\"127.0.0.1:52698\\\";host=127.0.0.1:8000;proto=http\"]\nhost: [\"127.0.0.1:8000\"]\nuser-agent: [\"curl/7.64.1\"]\nx-web3-address: [\"24f9f97c9e540fed57ef81f6c9aeabdb6fc73acd\"]\nx-web3-balance: [\"100000000000000000000\"]\nx-web3-signature: [\"krpQZO9WpgAEso2uk6eAKDy29QjeVtr+gdDZ7iG4bFkYiTfNvTvU5l4bb2iod5F4Ab8a8tJqzXHSXLkyz9U/gRs=\"]\n```\n\n## Smart Contracts\n\n### Embedded Presets\n\nTo help you get started, `niftygate` embeds a set presets from the OpenZeppelin\nproject. These address some of the more common use cases, and are (according to\nthe OpenZeppelin documentation) production-ready.\n\nCurrently, there are five presets included, along with utilities for deploying\nand interacting with each. These can be found under the `contract` subcommand.\n\nTo help you figure out which contract is appropriate, check the `guide`\nsubcommand. There you'll find an interactive program that will ask you a few\nsimple questions, and present you with a recommendation.\n\n## Roadmap\n\n- 0.1 - Initial Release with Web3 Account Verification\n- 0.2 - Support Token Standards\n  - Support for [ERC-20 (Token Standard)](https://eips.ethereum.org/EIPS/eip-20)\n  - Support for [ERC-777 (Token Standard)](https://eips.ethereum.org/EIPS/eip-777)\n  - Support for [ERC-721 (Non-Fungible Token Standard)](https://eips.ethereum.org/EIPS/eip-721)\n  - Support for [ERC-1155 (Multi Token Standard)](https://eips.ethereum.org/EIPS/eip-1155)\n- 0.3 - Observability for Smart Contracts\n- 0.5 - Support Upgradeable Smart Contracts\n- 0.6 - Renamed from sig-proxy to NiftyGate\n- 0.7 - TLS Support\n- 0.8 - Asset Management and (experimental) marketplace support\n\n## Wishlist (in no particular order)\n\nInfura Integration\n\nSupport for [RFC-7486 (HTTP Origin-Bound Authentication)](https://tools.ietf.org/html/rfc7486)\n\n- Replacing fixed messages with random challenges, adding nonces and expiration, etc.\n\nOptional endpoint to serve an embedded script for in-browser support.\n\n- Use [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) for key generation and signing.\n- Use [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API) for key storage.\n- Use [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) for header manipulation and auth flow.\n\nX509 Support\n\n- This would provide an alternative where a chain-of-trust model is preferred.\n\nPGP Support\n\n- This would provide an alternative where a web-of-trust model is preferred.\n\n## License\n\n`niftygate` is available under the MIT License. See `LICENSE.txt` for the full text.\n\n`niftygate` embeds contract ABI specs, and documentation excerpts from [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts).\nThese are also distributed under the terms of the MIT License [here](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/LICENSE).\n\n## How can NiftyGate help me?\n\n### I already have a Site, and a Smart Contract\n\nRun niftygate in server mode, give it the address of your site, and the address of your contract.\n\n### I have a site, but I don't want to use Smart Contracts\n\nRun niftygate in server mode, Give niftygate the address to your site, and it will let users log in with their Wallet.\n\n### I have a non-web application, and I want to interface with Smart Contracts\n\nCompile niftygate as a library, and embed it in your application.\n\n### I have a non-web application, and I don't want to modify my code.\n\nRun niftygate in client mode, and point your application at it.\n\n### I'm using a container platform, like Docker or Kubernetes.\n\nRun niftygate in either client or server mode, deployed as a sidecar container.\n\n### I'm using Kubernetes, and I want to integrate Smart Contracts into a Controller.\n\nUse the `contract events --stream` mode. This will output matching events as compact JSON on STDOUT.\n\n### I don't have a Smart Contract, but I want one.\n\nDeploy one of the built-in contracts that comes with niftygate, no code required!\n\n### I don't know what kind of Smart Contract I need.\n\nUse the interactive guide built into niftygate.\n\n### I don't have an Ethereum node to connect to.\n\nSign up for an account at infura.io, and point niftygate at it. Free accounts\nallow up to 100k daily requests, and if you need more than that, they have paid\nplans available.\n\n### I want to use a private blockchain.\n\nGo for it. Most of the development of niftygate is done on a private blockchain.\nAs long as it speaks JSON-RPC + Web3 over WebSockets, it should be fine.\n\nGanache and geth are good options for this, depending on your needs.\n\n### I want to use my own identity platform.\n\nRun niftygate in server mode, and tell it which headers it should pass along.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolstrom%2Fniftygate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcolstrom%2Fniftygate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolstrom%2Fniftygate/lists"}