Skip to main content

An Ariadne extension for authorization, allowing global permissions for all resolvers and fine-grained control over required permissions for specific resolvers in GraphQL APIs.

Project description

How to use:

pip install ariadne-auth

Set your Authorization Extension with global permissions

from graphql import GraphQLResolveInfo
from ariadne_auth.authz import AuthorizationExtension
from ariadne_auth.types import HasPermissions


# Define a function that returns the permission object
def get_permission_obj(info: GraphQLResolveInfo) -> HasPermissions:
    return info.context["my_permission_obj"]

# it can be also an async function
async def get_permission_obj_async(info: GraphQLResolveInfo) -> HasPermissions:
    return info.context["my_permission_obj"]


# Instantiate the AuthorizationExtension
authz = AuthorizationExtension(permissions_object_provider_fn=get_permission_obj)

# Set list of permissions required for all resolvers 
authz.set_required_global_permissions(["user:logged_in"])

Configure resolvers

query = QueryType()
ship = ObjectType("Ship")
faction = ObjectType("Faction")

# Set additional required permissions for specific resolvers
@query.field("rebels")
@authz.require_permissions(permissions=["read:rebels"])   # + "user:logged_in"
async def resolve_rebels(*_):
    return FACTIONS[0]


@query.field("empire")
@authz.require_permissions(permissions=["read:empire"], ignore_global_permissions=False)  # + "user:logged_in"
async def resolve_empire(*_):
    return FACTIONS[1]



# Disable global permissions for specific resolver
@query.field("ships")
@authz.require_permissions(permissions=[], ignore_global_permissions=True)
async def resolve_ships(obj, *_):
    return SHIPS

# Note the global permission is set on default_field_resolver method
# and it requires to disable permissions explicit for each field
@ship.field("name")
@authz.require_permissions(permissions=[], ignore_global_permissions=True)
async def resolve_ship_name(obj, *_):
    return obj["name"]

If needed you may also overwrite the function to get the permission object for specific resolver

def get_ship_permissions(info: GraphQLResolveInfo) -> HasPermissions:
    return info.context["my_ship_permission_obj"]

@ship.field("name")
@authz.require_permissions(
    permissions=[],
    ignore_global_permissions=True,
    permissions_object_provider_fn=get_ship_permissions
)
async def resolve_ship_name(obj, *_):
    return obj["name"]

Add your extension to Ariadne GraphQL instance

app = GraphQL(
    schema,
    http_handler=GraphQLHTTPHandler(extensions=[authz]),  # add the authz extension
)

You may also pass authz instance into info.context to use it directly

use _auth.assert_permissions or await _auth.assert_permissions_async to check permissions in your resovlers

# Depends on the faction, additional permissions are required
@faction.field("ships")
async def resolve_faction_ships(faction_obj, info: GraphQLResolveInfo, *_):
    _auth = info.context["auth"]
    if (
        faction_obj["name"] == "Alliance to Restore the Republic"
    ):  # Rebels faction requires additional perm to read ships
        _auth.assert_permissions(_auth.permissions_object_provider_fn(info), ["read:ships"])

    return [_ship for _ship in SHIPS if _ship["factionId"] == faction_obj["id"]]



def get_context_value(request, data):
    return {
        **authz.generate_authz_context(request),
    }


app = GraphQL(
    schema,
    context_value=get_context_value,
    http_handler=GraphQLHTTPHandler(extensions=[authz])
)

Run test app

The repository contains a test application that demonstrates how to use the library

To run test application use: hatch run ariadne_auth

Note that user_id is hardcoded in test_app/app.py:148

Example request

for user with permissions

    permissions=[
        "user:logged_in",
        "read:empire",
        "read:rebels",
    ],  # can't read rebels ships
query {
  empire{
    id
    name
    ships {
      id
      name
    }
  }
  rebels{
    id
    name
    ships {
      name
    }
  }
  ships {
    name
  }
}

Versioning policy

ariadne-auth follows a custom versioning scheme where the minor version increases for breaking changes, while the patch version increments for bug fixes, enhancements, and other non-breaking updates.

Since ariadne-auth has not yet reached a stable API, this approach is in place until version 1.0.0. Once the API stabilizes, the project will adopt Semantic Versioning.


Crafted with ❤️ by Mirumee Software hello@mirumee.com

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

ariadne_auth-0.1.0.tar.gz (10.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ariadne_auth-0.1.0-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

File details

Details for the file ariadne_auth-0.1.0.tar.gz.

File metadata

  • Download URL: ariadne_auth-0.1.0.tar.gz
  • Upload date:
  • Size: 10.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for ariadne_auth-0.1.0.tar.gz
Algorithm Hash digest
SHA256 01d83f30524f9e39c996c663c09a2636a78d0281977733c55ec925ec83fa89bb
MD5 e73f8d009deaa01a51c67d9f1abc4241
BLAKE2b-256 2f5f4d0acc29cb974ab7a3c24d7ef413de21d96442b8ddff2e869e28399891a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for ariadne_auth-0.1.0.tar.gz:

Publisher: publish.yml on mirumee/ariadne-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ariadne_auth-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ariadne_auth-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for ariadne_auth-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a2ca92449a2beec721b7fa7d4a0eb823ef682000269830be829bbad532c4f0a1
MD5 76a200b5d40659eba65bf54bb22141f8
BLAKE2b-256 626f23f05604eabdfc48c70c7590d5bd93c373041aebe2e29a39fe2729fbc589

See more details on using hashes here.

Provenance

The following attestation bundles were made for ariadne_auth-0.1.0-py3-none-any.whl:

Publisher: publish.yml on mirumee/ariadne-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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