Protect your API from unverified users
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Hugo Thunnissen c369440a28 Add note about test request 2 months ago
nginx-config Add example nginx config 2 months ago
pictures Add installation instructions to README 2 months ago
.gitignore Initial commit: Prototype. 2 months ago
README.md Add note about test request 2 months ago
authenticate_handler.go Make API key cache expiration time configurable 2 months ago
authenticate_handler_test.go Make http handlers test-able and add tests for them 2 months ago
cached_key.go Add forgotten loops, resolve locking issues make key caching work in general :) 2 months ago
config-example.yml Make API key cache expiration time configurable 2 months ago
config.go Make API key cache expiration time configurable 2 months ago
database.go Make http handlers test-able and add tests for them 2 months ago
go.mod Tidy up module dependencies 2 months ago
go.sum Tidy up module dependencies 2 months ago
http_common.go Move authorized response action to helper function 2 months ago
key_cache.go Add forgotten loops, resolve locking issues make key caching work in general :) 2 months ago
key_cache_test.go Make key cache test check if keys are hit correctly 2 months ago
main.go Make API key cache expiration time configurable 2 months ago
verify_user_handler.go Make http handlers test-able and add tests for them 2 months ago
verify_user_handler_test.go Make http handlers test-able and add tests for them 2 months ago

README.md

Gitea API Protector

This is a tiny daemon that should help gitea communities to prevent malicious users from abusing the gitea API. To do this it introduces the concept of verified users: A verified user will be able to make API requests, but other users will not.

How does it work

To let the API protector do its thing, you first need to put an instance of nginx in front of your gitea instance as a reverse proxy. With nginx in place, you can make use of it's auth_request module to authenticate users through a subrequest to the API protector.

Basic idea of what happens:

    |===========|          Subrequest          |=====================|
    |           | ---------------------------> |                     |
    |           |                              | Gitea API Protector |
    |           |          200 = OK            |                     |
    |           | <--------------------------- |=====================|
    |   Nginx   |
    |           |
    |           |   subrequest returned 200,   |=======|
    |           |       proxy to gitea         |       |
    |           | ---------------------------> | Gitea |
    |===========|                              |       |
                                               |=======|


    |===========|          Subrequest          |=====================|
    |           | ---------------------------> |                     |
    |           |                              | Gitea API Protector |
    |           |     401 = Unauthorized       |                     |
    |           | <--------------------------- |=====================|
    |   Nginx   |
    |           |
    |           |   Subrequest returned 401,   |=======|
    |           |      NO proxy to gitea       |       |
    |           |              X               | Gitea |
    |===========|                              |       |
                                               |=======|

In order to determine whether the user doing the API request is a verified user, the API protector requests the user's ID from gitea, using the user's own token! After requesting the ID, and confirming that the user is indeed verified, the API request is executed as it normally would.

The API protector keeps the keys of verified users in an in-memory cache for a while, so that subsequent requests using the same token can be verified without doing an extra API call to gitea.

What makes a user verified?

You can tell the API Protector which users are verified in a very familiar way: through a pull-request! Instance admins can setup a normal git repository and add a special webhook to it. Through the webhook, gitea will tell the API Protector when a pull-request has been merged. Each time a pull request is merged, the user who created the pull request will become a verified user and is allowed to make use of the API.

The pull request itself can be any change at all, as long as it is merged you are good to go. It is up to the maintainers of the repo to decide what kind of change a pull request should contain to become a verified user. Maybe this is a chance to introduce yourself to your gitea community :)

Installation

There are currently two ways to install Gitea API Protector: using the binary release and compiling from source. The instructions below assume that you are installing the software on a linux system. In the case of the binary release, an amd64 linux system is assumed in particular.

Binary release

  • Download the latest release from the releases-page.
  • Extract the archive to a directory of choice: tar -xf gitea-api-protector-$VERSION.tar.gz
  • Enter the directory: cd gitea-api-extractor-$VERSION

Compiling from source

  • Make sure you have golang version 1.13 or higher installed on your system
  • Clone the repo: git clone git@codeberg.org:hugot/gitea-api-protector.git
  • Enter the directory: cd gitea-api-protector
  • Checkout the release you want to use: git checkout $VERSION
  • Run go build .

Configure the application

  • Edit the confifg, make sure to read the comments explaining what each option means:
    cp ./config-example.yml ./config.yml && $EDITOR ./config.yml
  • Now that that's out of the way, you can start the application
    ./gitea-api-protector-$VERSION ./config.yml
  • The application should start successfully. You can now go ahead and start configuring nginx.

Configure nginx
There are two things that need to be configured for nginx: One is the normal reverse proxy stuff for the Gitea API Protector, the other is changing/configuring your gitea reverse proxy to use the auth_request module.

You can find a reverse proxy config for the Gitea API protector at ./nginx-config/gitea-api-protector.conf. Copy it to wherever nginx config is stored on your system and edit it. There are # CHANGE ME! comments above each line that you should probably change.

There is also a reverse proxy config for gitea at ./nginx-config/gitea-example.conf. You can edit this near all the # CHANGE ME! comments and copy it over, or incorporate what you need into your existing gitea config if you have one. There are a lot of comments in the config file to explain which parts are important for both gitea and the API protector to function properly.

Configure the user verification repository
Now it's time to create the repository that will verify users through pull requests.

  • Create a new repo in Gitea as you normally would
  • Go to the settings page for the repo
  • Click on the webhooks tab
  • Add a new “Gitea” webhook:
    Add webhook image
  • Set https://your-api-protector-domain.tld/verify as target URL and set “Secret” to the secret you defined in your config.yml
  • Make sure the “POST Content Type” is set to application/json
    configure endpoint image
  • Select “Trigger On” > “Custom Events...” > “Pull Request”
    Trigger settings
  • Make sure that “Active” is checked for the webhook
    Active checkmark image
  • Click save, you are now ready to start verifying users for API use.

To put your configuration to the test, you can do a test request with curl as a verified/unverified user: curl -X GET 'https://gitea.example.com/api/v1/user' -H 'accept: application/json' -H 'Authorization: bearer YOUR_TOKEN_HERE. Unverified users should get a 401 response and verified users should get a 200 response containing their user data in json format.