Skip to main content

authorization SDK used to build protected Web APIs

Project description

web-auth-sdk

The web-auth-sdk is an authorization SDK that is used to build protected Web APIs. It provides the ability to intercept incoming requests and inject custom logic for authentication and authorization before the request reaches the view function.

In addition, it supports Google OAuth2 for logging in and session logging in.

To access protected APIs, clients should authenticate by passing credentials or authorizations. For example, a JWT key can be used as follows:

  curl 'http://api.example.com/resources' -H 'Authorization: Bearer eyJ1c2VyX2lkIjoxLCJwZXJtaXNzaW9uX2JpdG'
  curl 'http://api.example.com/resources?access_token=eyJ1c2VyX2lkIjoxLCJwZXJtaXNzaW9uX2JpdG'
  curl 'http://api.example.com/resources' --cookie 'access_token=eyJ1c2VyX2lkIjoxLCJwZXJtaXNzaW9uX2JpdG'

Requirements

  • Python 3.8+
  • FastAPI 0.80+ (optional)
  • Django 4.0+ (optional)
  • Flask 2.0+ (optional)

Installation

pip install web-auth-sdk

Permission Representation

  1. Permission list, located at usr/etc/permissions.json file:

    permissions = [
        {'bitmask_idx': 0, 'codename': 'add_order', 'name': 'Can add order', 'service': 'order'},
        {'bitmask_idx': 1, 'codename': 'change_order', 'name': 'Can change order', 'service': 'order'},
        {'bitmask_idx': 2, 'codename': 'delete_order', 'name': 'Can delete order', 'service': 'order'},
        {'bitmask_idx': 3, 'codename': 'view_order', 'name': 'Can view order', 'service': 'order'},
        {'bitmask_idx': 4, 'codename': 'add_tickettype', 'name': 'Can add ticket type', 'service': 'order'},
        {'bitmask_idx': 5, 'codename': 'change_tickettype', 'name': 'Can change ticket type', 'service': 'order'},
        {'bitmask_idx': 6, 'codename': 'view_tickettype', 'name': 'Can view ticket type', 'service': 'order'},
        {'bitmask_idx': 7, 'codename': 'delete_tickettype', 'name': 'Can delete ticket type', 'service': 'order'},
    ]
    
  2. How to grant permissions?

    Permissions are encoded using a bitmask of length n that is a multiple of 24. Each permission is represented by a 1 on the corresponding bitmask_idx-th position in the bitmask, indicating that the permission is granted.

  3. Base64-encoded the bitmask

    Bitmask Base64-encoded
    111111111111111111111111111111110111111101111111 /////39/
  4. Decoded/Encoded JWT

    {
      "user_id": 1,
      "permission_bitmask": "/////39/",
      "iat": 1678798980,
      "exp": 1678800187
    }
    
    eyJ1c2VyX2lkIjoxLCJwZXJtaXNzaW9uX2JpdG1hc2siOiIvLy8vLzM5LyIsImlhdCI6MTY3ODc5ODk4MCwiZXhwIjoxNjc4ODAwMTg3fQ
    

Development

  • FastAPI

    import web_auth
    
    
    web_auth.configure()
    
    @fastapi.get('/tickets')
    @web_auth.permissions('view_ticket') # Iterable[str] are acceptable
    async def list_tickets() -> list[object]: 
        pass
    
  • Django

    import web_auth
    from web_auth.django import DjangoBridge
    
    
    web_auth.configure(bridge_class=DjangoBridge)
    
    @web_auth.permissions('view_ticket')
    def list_tickets(request) -> list[object]: 
        pass
    
    urlpatterns = [django.urls.path('list-tickets', list_tickets)]
    
  • Flask

    import web_auth
    from web_auth.flask import FlaskBridge
    
    
    web_auth.configure(bridge_class=FlaskBridge)
    
    @flask.route('/tickets', methods=['GET'])
    @web_auth.permissions('view_ticket')
    def list_tickets() -> list[object]: 
        pass
    
  • Use instanced context

    import web_auth
    
    
    context = web_auth.build_context()  
    
    @fastapi.get('/tickets')
    @context.permissions('view_ticket')
    async def list_tickets() -> list[object]: 
        pass
    
  • Implement access control & retrieve the consumer info

    import fastapi
    import web_auth
    
    
    context = web_auth.build_context()
    
    @fastapi.get('/profile')
    @context.permissions()
    def get_profile(request: fastapi.Request, consumer: web_auth.Consumer) -> web_auth.Consumer:
        # raise `web_auth.AuthException` if the consumer does not have permission
        context.bridge.access_control(
            request=request, 
            permissions={'view_ticket'},
            aggregation_type=web_auth.PermissionAggregationTypeEnum.ALL,
        )
        return consumer
    
  • Customization

    1. Permission Storage
    from typing import Optional
    
    import fastapi
    import requests
    
    from web_auth import build_context, Storage, PermissionModel, Context
    
    
    class RESTStorage(Storage):
        def __init__(self, ttl: int, url: str, context: Optional[Context] = None):
            self.url = url
            super().__init__(ttl=ttl, context=context)
    
        def _load_permissions(self) -> list[PermissionModel]:
            return [PermissionModel(**r) for r in requests.get(self.url).json()]
    
    my_context = build_context(
        storage_class=RESTStorage,
        storage_params={'ttl': 60, 'url': 'http://api.example.com/permissions?format=json'},
    )
    
    @fastapi.get('/tickets')
    @my_context(['view_ticket', 'change_ticket'])
    def get_tickets() -> list[object]:
        pass
    
    1. Authentication
    import fastapi
    import pydantic
    
    from web_auth import build_context, Config
    from web_auth.fastapi import FastapiBridge
    
    
    class MyConsumer(pydantic.BaseModel):
        user_id: int
    
    class MyFastapiBridge(FastapiBridge):
        consumer_class = MyConsumer
    
        def authenticate(self, request: fastapi.Request) -> tuple[MyConsumer, str]:
            # your authenticate logic
            return MyConsumer(user_id=1), 'JWT'
    
    my_context = build_context(
        bridge_class=MyFastapiBridge,
        storage_class=Config.DEFAULT_STORAGE_CLASS,
        storage_params=Config.DEFAULT_STORAGE_PARAMS,
    )
    
    @fastapi.get('/profile')
    @my_context([])
    def get_profile(consumer: MyConsumer) -> MyConsumer:
        return consumer
    
    1. Authorization
    import fastapi
    
    from web_auth import build_context, Authorization, Consumer, PermissionAggregationTypeEnum
    from web_auth.fastapi import FastapiBridge 
    
    
    class MyAuthorization(Authorization):
        def authorize(
            self,
            consumer: Consumer,
            permissions: set[str],
            aggregation_type: PermissionAggregationTypeEnum,
        ):
            permission_models = self.context.storage.get_permissions()
            # Checks whether the `consumer` has the `permissions` in `permission_models`
    
    class MyFastapiBridge(FastapiBridge):
        authorization_class = MyAuthorization
    
    my_context = build_context(
        bridge_class=MyFastapiBridge,
    )
    
    @fastapi.get('/tickets')
    @my_context(['view_ticket', 'change_ticket'])
    def get_tickets() -> list[object]:
        pass
    
  • Oauth2 client

    1. Install apps to settings.py
    INSTALLED_APPS = [
        'web_auth.django'
    ]
    
    1. Register url to urls.py
    urlpatterns = [
        django.urls.path('', django.urls.include('web_auth.django.urls')),
    ]
    
    1. Login with Google
    1. Session Login

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

web_auth_sdk-0.2.0.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

web_auth_sdk-0.2.0-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file web_auth_sdk-0.2.0.tar.gz.

File metadata

  • Download URL: web_auth_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.4.0 CPython/3.9.16 Linux/5.15.0-1034-azure

File hashes

Hashes for web_auth_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9fc93c5be511e3015747a39c01836e224ae9f50b9eca3ea257249a20bf2e8bb6
MD5 ee9143951f154026689efe3e7d5ce5f4
BLAKE2b-256 9143fe3aab2b0fc4d0997c91f72fdb25b1a8557337c62132edf54880c4bd1ee3

See more details on using hashes here.

File details

Details for the file web_auth_sdk-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: web_auth_sdk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 17.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.4.0 CPython/3.9.16 Linux/5.15.0-1034-azure

File hashes

Hashes for web_auth_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9c12cbadcb56079185f1a7c07ba099f447776971ed99693ee85bcf5bc83097be
MD5 7ce0f9700466a12771ec65ecd6e45a2f
BLAKE2b-256 f355d1e73be75ad2b0229259df2ef3655239e7cb95c27473454d9c255224d56f

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page