ariadne-auth


Nameariadne-auth JSON
Version 0.0.1.dev5 PyPI version JSON
download
home_pageNone
SummaryAn Ariadne extension for authorization, allowing global permissions for all resolvers and fine-grained control over required permissions for specific resolvers in GraphQL APIs.
upload_time2025-02-25 16:32:23
maintainerNone
docs_urlNone
authorNone
requires_python>=3.9
licenseNone
keywords ariadne ariadne-extension authorization permissions
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # How to use:
```shell
pip install ariadne-auth
```

### Set your Authorization Extension with global permissions

```python
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
```python
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)  # + "user:logged_in"
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
```python
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
```python
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
```python
# 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
```
```graphql
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](https://mirumee.com)**
hello@mirumee.com
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "ariadne-auth",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "ariadne, ariadne-extension, authorization, permissions",
    "author": null,
    "author_email": "Mirumee Labs <hello@mirumee.com>",
    "download_url": "https://files.pythonhosted.org/packages/f0/93/890010ca9458fb58e6bd14559b20eb0e3204c8236e53315e35ff2ddbf86b/ariadne_auth-0.0.1.dev5.tar.gz",
    "platform": null,
    "description": "# How to use:\n```shell\npip install ariadne-auth\n```\n\n### Set your Authorization Extension with global permissions\n\n```python\nfrom graphql import GraphQLResolveInfo\nfrom ariadne_auth.authz import AuthorizationExtension\nfrom ariadne_auth.types import HasPermissions\n\n\n# Define a function that returns the permission object\ndef get_permission_obj(info: GraphQLResolveInfo) -> HasPermissions:\n    return info.context[\"my_permission_obj\"]\n\n# it can be also an async function\nasync def get_permission_obj_async(info: GraphQLResolveInfo) -> HasPermissions:\n    return info.context[\"my_permission_obj\"]\n\n\n# Instantiate the AuthorizationExtension\nauthz = AuthorizationExtension(permissions_object_provider_fn=get_permission_obj)\n\n# Set list of permissions required for all resolvers \nauthz.set_required_global_permissions([\"user:logged_in\"])\n```\n\n\n### Configure resolvers\n```python\nquery = QueryType()\nship = ObjectType(\"Ship\")\nfaction = ObjectType(\"Faction\")\n\n# Set additional required permissions for specific resolvers\n@query.field(\"rebels\")\n@authz.require_permissions(permissions=[\"read:rebels\"])   # + \"user:logged_in\"\nasync def resolve_rebels(*_):\n    return FACTIONS[0]\n\n\n@query.field(\"empire\")\n@authz.require_permissions(permissions=[\"read:empire\"], ignore_global_permissions=False)  # + \"user:logged_in\"\nasync def resolve_empire(*_):\n    return FACTIONS[1]\n\n\n\n# Disable global permissions for specific resolver\n@query.field(\"ships\")\n@authz.require_permissions(permissions=[], ignore_global_permissions=True)  # + \"user:logged_in\"\nasync def resolve_ships(obj, *_):\n    return SHIPS\n\n# Note the global permission is set on default_field_resolver method\n# and it requires to disable permissions explicit for each field\n@ship.field(\"name\")\n@authz.require_permissions(permissions=[], ignore_global_permissions=True)\nasync def resolve_ship_name(obj, *_):\n    return obj[\"name\"]\n```\n\nIf needed you may also overwrite the function to get the permission object for specific resolver\n```python\ndef get_ship_permissions(info: GraphQLResolveInfo) -> HasPermissions:\n    return info.context[\"my_ship_permission_obj\"]\n\n@ship.field(\"name\")\n@authz.require_permissions(\n    permissions=[],\n    ignore_global_permissions=True,\n    permissions_object_provider_fn=get_ship_permissions\n)\nasync def resolve_ship_name(obj, *_):\n    return obj[\"name\"]\n\n```\n\n\n### Add your extension to Ariadne GraphQL instance\n```python\napp = GraphQL(\n    schema,\n    http_handler=GraphQLHTTPHandler(extensions=[authz]),  # add the authz extension\n)\n```\n \nYou may also pass `authz` instance into info.context to use it directly \n\nuse `_auth.assert_permissions` or `await _auth.assert_permissions_async` to check permissions in your resovlers\n```python\n# Depends on the faction, additional permissions are required\n@faction.field(\"ships\")\nasync def resolve_faction_ships(faction_obj, info: GraphQLResolveInfo, *_):\n    _auth = info.context[\"auth\"]\n    if (\n        faction_obj[\"name\"] == \"Alliance to Restore the Republic\"\n    ):  # Rebels faction requires additional perm to read ships\n        _auth.assert_permissions(_auth.permissions_object_provider_fn(info), [\"read:ships\"])\n\n    return [_ship for _ship in SHIPS if _ship[\"factionId\"] == faction_obj[\"id\"]]\n\n\n\ndef get_context_value(request, data):\n    return {\n        **authz.generate_authz_context(request),\n    }\n\n\napp = GraphQL(\n    schema,\n    context_value=get_context_value,\n    http_handler=GraphQLHTTPHandler(extensions=[authz])\n)\n```\n\n\n## Run test app \nThe repository contains a test application that demonstrates how to use the library\n\n#### To run test application use: `hatch run ariadne_auth`\nNote that `user_id` is hardcoded in `test_app/app.py:148`\n\n\n### Example request\nfor user with permissions\n```\n    permissions=[\n        \"user:logged_in\",\n        \"read:empire\",\n        \"read:rebels\",\n    ],  # can't read rebels ships\n```\n```graphql\nquery {\n  empire{\n    id\n    name\n    ships {\n      id\n      name\n    }\n  }\n  rebels{\n    id\n    name\n    ships {\n      name\n    }\n  }\n  ships {\n    name\n  }\n}\n```\n\n## Versioning policy ##\nariadne-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.\n\nSince 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.\n\n----------------\n\n**Crafted with \u2764\ufe0f by [Mirumee Software](https://mirumee.com)**\nhello@mirumee.com",
    "bugtrack_url": null,
    "license": null,
    "summary": "An Ariadne extension for authorization, allowing global permissions for all resolvers and fine-grained control over required permissions for specific resolvers in GraphQL APIs.",
    "version": "0.0.1.dev5",
    "project_urls": {
        "Homepage": "https://github.com/mirumee/ariadne-auth",
        "Issues": "https://github.com/mirumee/ariadne-auth/issues"
    },
    "split_keywords": [
        "ariadne",
        " ariadne-extension",
        " authorization",
        " permissions"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "684653d66d5ed791894d66fad039482f9ae7b774df0be6ea1dda932a4eda9830",
                "md5": "d230273e164f3688e3b16cd30de2552e",
                "sha256": "ac7eca2672ef6d8febb65cb7471cfb11de809a8135b397b13cbee304aa1a527d"
            },
            "downloads": -1,
            "filename": "ariadne_auth-0.0.1.dev5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d230273e164f3688e3b16cd30de2552e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 6468,
            "upload_time": "2025-02-25T16:32:22",
            "upload_time_iso_8601": "2025-02-25T16:32:22.304748Z",
            "url": "https://files.pythonhosted.org/packages/68/46/53d66d5ed791894d66fad039482f9ae7b774df0be6ea1dda932a4eda9830/ariadne_auth-0.0.1.dev5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f093890010ca9458fb58e6bd14559b20eb0e3204c8236e53315e35ff2ddbf86b",
                "md5": "54a7760385864f70ef974b8061765f2a",
                "sha256": "d9ff0df5fea862e2f0061d6920cd4c62782adb04436d2654ef87b64079b9c832"
            },
            "downloads": -1,
            "filename": "ariadne_auth-0.0.1.dev5.tar.gz",
            "has_sig": false,
            "md5_digest": "54a7760385864f70ef974b8061765f2a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 10820,
            "upload_time": "2025-02-25T16:32:23",
            "upload_time_iso_8601": "2025-02-25T16:32:23.707280Z",
            "url": "https://files.pythonhosted.org/packages/f0/93/890010ca9458fb58e6bd14559b20eb0e3204c8236e53315e35ff2ddbf86b/ariadne_auth-0.0.1.dev5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-25 16:32:23",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mirumee",
    "github_project": "ariadne-auth",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "ariadne-auth"
}
        
Elapsed time: 0.95493s