Skip to main content

hypermea-negotiable-auth

An advanced yet easy to use auth module for APIs built using hypermea or Eve.

The auth class that ships with Eve, BasicAuth, allows users of your API to authenticate with Basic Authentication. The NegotiableAuth class in this package extends this to allow the user to choose from any authentication scheme your API supports. This allows for easy configuration and handling of multiple auth schemes - including schemes like Digest which require negotiation.

NOTE: This package is near-production ready. Before calling it 1.0 it needs better docs and perhaps a bit more tweaking. It is already in use in a number of production systems - but use at your own risk!

Getting Started

The steps are:

  1. Create a handler functions for each scheme you support
  2. Register those functions with auth_parser
  3. Extend NegotiableAuth and override process_claims()

Step 1 - Create handler functions

To handle a scheme you must define at least one function, usually two, which the authparser library will call. You can name them however you like - authparser calls them user_record_fn and challenge_fn

  • user_record_fn(token, **kwargs)
  • challenge_fn(**kwargs) [optional - see authparser for details, mandatory for schemes like Digest]

This is best described with an example. Let's say you want to handle Bearer token authorization. When the time comes to validate the token, your user_record_fn will be called. So let's create it. I'll call it handle_bearer:

def handle_bearer(token, **kwargs):
    # do stuff to validate the token
    # ...
    # if it checks out, populate the user record:
    record = {
        'user': 'someone@example.com',
        'role': 'employee'
    }
    # if there is a problem (if NegotiableAuth sees '_issues' then it will deny access):
    record = {
        '_issues': {
            'token': 'The token has expired.'
        }
    }
    
    return record

Step 2 - Register the handler functions

The best place to do this is above the class definition you will create in step 3. I will start by creating a file named my_auth.py

from hypermea_negotiable_auth import NegotiableAuth, AUTH_PARSER
from --wherever you defined your handler-- import handle_bearer

AUTH_PARSER.add_handler('Bearer', handle_bearer)

Now when the time comes, NegotiableAuth will know if it receives a request whose Authorization header has a Bearer token, it will call your handle_bearer() function.

Step 3 - Extend NegotiableAuth and override process_claims()

The NegotiableAuth class is an abstract base class and cannot be used on its own. You must make your own class that inherits from it. There is only one function to override: process_claims().

Building on the my_auth.py we started in step 2:

from hypermea_negotiable_auth import NegotiableAuth, AUTH_PARSER
from --wherever you defined your handler-- import handle_bearer

class MyAuth(NegotiableAuth):
    def __init__(self):
        super(MyAuth, self).__init__()
        
    def process_claims(self, claims, allowed_roles, resource, method):
        authorized = 'user' in claims
        role = claims.get('role')

        if resouce = 'salary' and role != 'employer':
            authorized = False
        
        if resource == 'position' and method != 'GET' and role != 'employer':
            authorized = False
        
	    return authorized
     

This is a too-simple example for illustration only. The request will be authorized if user exists in claims, unless the request is for salary then only employers are allowed. If it is a GET request for position, it is allowed for everyone - only employers can POST, PUT, DELETE, etc.

There are many things you can do in your own process_claims(). Please read the Eve docs for more details.

The things you need to know:

  • claims is the record returned from your handler function.
    • If the handler returns falsey, or dict with _issues, it will reject the request before your class's process_claims() is called
    • your process_claims() need only return True or False, depending whether the claims is allowed in or not.
    • As you see, you are in full control of what's in claims and how to determine whether to grant access based on what is in the claims.
  • allowed_roles, resource, and method are passed in from Eve depending on the request and what is in your Eve settings.
  • If you are using Eve's User-Restricted Resource Access, process_claims() is where you will call self.set_request_auth_value()

Wire it into your project

Once you have defined your auth class, add it to your Eve app. When you instantiate the app, pass the class name as the auth param.

app = Eve('app-name', auth=MyAuth)

Beyond the Basics

When NegotiableAuth calls your handler function, it passes the following kwargs to get_user_record()

  • allowed_roles
  • resource
  • method
  • request - the flask request object

When you define that function, have it return an dict with each member a claim (e.g. username, email, role). If the function returns falsey, or a dict that has a member named _issues, then access will be denied. To communicate issues back to the requestor, have _issues be a dict of name/value pairs, for example (this example has just one name/value):

{
    '_issues': {
        'user': 'This user does not exist.'
    }
}

get_challenge_header() - passed through to the scheme's challenge_fn

  • request

...more docs coming soon...

Metadata

Release files for hypermea-negotiable-auth 0.9.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hypermea-negotiable-auth 0.9.9
File Size Uploaded Provenance
hypermea_negotiable_auth-0.9.9.tar.gz 5.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for hypermea-negotiable-auth 0.9.9
File Interpreter ABI Platform
hypermea_negotiable_auth-0.9.9-py3-none-any.whl Python 3 none any Details

Total release size: 11.7 kB

Release files / hypermea_negotiable_auth-0.9.9.tar.gz

Download URL hypermea_negotiable_auth-0.9.9.tar.gz
Size 5.6 kB
Tags Source
SHA-256 checksum
How to use checksums
aefe710103b5b47dd15d70549491ae41ce561b0c43fdcb8381fb32ca762c8b4c
BLAKE2b-256 checksum
How to use checksums
14cc3c60944f0aaeab54d2df5ca52a57f9103bcda967c994c663d50194bb1ded
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.3

Release files / hypermea_negotiable_auth-0.9.9-py3-none-any.whl

Download URL hypermea_negotiable_auth-0.9.9-py3-none-any.whl
Size 6.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e25dc3bdfb63282a8dae45a2ffa06dc68b72600bcab1813fee1c5c4fcee2bc4a
BLAKE2b-256 checksum
How to use checksums
6a942d0ca4a9e50afbcd8dc7b82a64eee0d6659b12f6df5bdc2352252ac6b2d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.3

Security for hypermea-negotiable-auth 0.9.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page