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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01d83f30524f9e39c996c663c09a2636a78d0281977733c55ec925ec83fa89bb
|
|
| MD5 |
e73f8d009deaa01a51c67d9f1abc4241
|
|
| BLAKE2b-256 |
2f5f4d0acc29cb974ab7a3c24d7ef413de21d96442b8ddff2e869e28399891a0
|
Provenance
The following attestation bundles were made for ariadne_auth-0.1.0.tar.gz:
Publisher:
publish.yml on mirumee/ariadne-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ariadne_auth-0.1.0.tar.gz -
Subject digest:
01d83f30524f9e39c996c663c09a2636a78d0281977733c55ec925ec83fa89bb - Sigstore transparency entry: 175406418
- Sigstore integration time:
-
Permalink:
mirumee/ariadne-auth@12f124fdc4ec528a77247bf494f646fc654512d4 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/mirumee
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@12f124fdc4ec528a77247bf494f646fc654512d4 -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2ca92449a2beec721b7fa7d4a0eb823ef682000269830be829bbad532c4f0a1
|
|
| MD5 |
76a200b5d40659eba65bf54bb22141f8
|
|
| BLAKE2b-256 |
626f23f05604eabdfc48c70c7590d5bd93c373041aebe2e29a39fe2729fbc589
|
Provenance
The following attestation bundles were made for ariadne_auth-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on mirumee/ariadne-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ariadne_auth-0.1.0-py3-none-any.whl -
Subject digest:
a2ca92449a2beec721b7fa7d4a0eb823ef682000269830be829bbad532c4f0a1 - Sigstore transparency entry: 175406419
- Sigstore integration time:
-
Permalink:
mirumee/ariadne-auth@12f124fdc4ec528a77247bf494f646fc654512d4 -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/mirumee
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@12f124fdc4ec528a77247bf494f646fc654512d4 -
Trigger Event:
release
-
Statement type: