bootleg-jwt


Namebootleg-jwt JSON
Version 0.3.0 PyPI version JSON
download
home_pagehttps://github.com/freyjagp/bootleg-jwt
SummarySign tokens with blake2b, then verify them.
upload_time2023-06-17 01:44:11
maintainer
docs_urlNone
authorFreyja Odinthrir
requires_python>=3.10, <4
license
keywords cryptography tokens hashing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # bootleg-jwt <!-- omit in toc -->

`bootleg-jwt` aims to mimic JSON Web Tokens in a simple, `pydantic` way.

___

## New for v0.3.0 <!-- omit in toc -->

Version 0.3.0 extends v0.2.x with backwards compatible addition of the `_salt` and `_person` arguments. When these arguments are passed alongside a token, the token's hash is generated using them. Note: the `_salt` and `_person` arguments may not be longer than 16 bytes. This is a limitation of the blake2b hashing algorithm. If a string is supplied, it will be encoded to utf-8 and truncated automatically. Otherwise, any bytestring longer than 16 bytes will fail validation. This is by design.

`_salt` and `_person` allow the token to be namespaced and salted. This provides an extra layer of validation, allowing implementations of `BootlegJWT` to perform more checks on tokens, other than what is baked in. This would allow, for example, invalidating all tokens with a particular salt or namespace.

___

## Table of Contents <!-- omit in toc -->

- [Generate a token](#generate-a-token)
- [Validate a token](#validate-a-token)
- [Renew a token](#renew-a-token)

## Generate a token

```python
from bootleg_jwt import BootlegJWT, Payload, header, body
from pydantic import BaseModel
from os import environ              # An environment variable is required.


SECRET = "some-secret-key"


DURATION = 60 * 60                  # Token expires after this many seconds


TYPE = "Testing Token"              # An arbitrary name


environ['SECRET'] = SECRET          # This module depends upon an environment
                                    # variable `SECRET`. You may also set this
                                    # secret in a `.env` file in your project's root,
                                    # or by using `export SECRET="secret"`



## These two pydantic models are simple examples. They may have arbitrary names and data. They must only map to Token.body.user and Token.body.data
class UserData(BaseModel):
    id: int
    username: str


class BodyData(BaseModel):
    info: str
    value: bool


payload_user = UserData(id=69,username="nice")
payload_body = BodyData(info="Some Information", value=True)


payload = Payload(
    header=header(duration=DURATION,type=TYPE),
    body=body(user=payload_user,data=payload_body)
)


generate = BootlegJWT(payload=payload)
token = generate.TOKEN
encoded = generate.ENCODED
json = generate.JSON
validate = generate.VALID
divider = "\n------------------------------\n"



print(token,divider,encoded,divider,json,divider,validate)
```

<details>
<summary>Output (click to expand):</summary>
<br>

```json
header=Header(type='Testing Token', duration=Duration(unit=Unit(type='time', name='seconds', shorthand='s'), value=3600), created=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677382369), expires=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677385969)) body=Body(user=UserData(id=69, username='nice'), data=BodyData(info='Some Information', value=True)) signature=Hash(value=b'e0b99c4eca2811bd9d164185219a283a4fddc2129ec0d2b3e5ba7b22596e4c7b8ac6d7b7c81812b50ace0a5b6d0be3ce5f977f753069d951bf15d13f179014df', algorithm='blake2b', keyed=True, salt=b'', person=b'')
------------------------------
 b'eyJoZWFkZXIiOiB7InR5cGUiOiAiVGVzdGluZyBUb2tlbiIsICJkdXJhdGlvbiI6IHsidW5pdCI6IHsidHlwZSI6ICJ0aW1lIiwgIm5hbWUiOiAic2Vjb25kcyIsICJzaG9ydGhhbmQiOiAicyJ9LCAidmFsdWUiOiAzNjAwfSwgImNyZWF0ZWQiOiB7InVuaXQiOiB7InR5cGUiOiAidGltZSIsICJuYW1lIjogInNlY29uZHMgc2luY2UgZXBvY2giLCAic2hvcnRoYW5kIjogInMrZXBvY2gifSwgInZhbHVlIjogMTY3NzM4MjM2OX0sICJleHBpcmVzIjogeyJ1bml0IjogeyJ0eXBlIjogInRpbWUiLCAibmFtZSI6ICJzZWNvbmRzIHNpbmNlIGVwb2NoIiwgInNob3J0aGFuZCI6ICJzK2Vwb2NoIn0sICJ2YWx1ZSI6IDE2NzczODU5Njl9fSwgImJvZHkiOiB7InVzZXIiOiB7ImlkIjogNjksICJ1c2VybmFtZSI6ICJuaWNlIn0sICJkYXRhIjogeyJpbmZvIjogIlNvbWUgSW5mb3JtYXRpb24iLCAidmFsdWUiOiB0cnVlfX0sICJzaWduYXR1cmUiOiB7InZhbHVlIjogImUwYjk5YzRlY2EyODExYmQ5ZDE2NDE4NTIxOWEyODNhNGZkZGMyMTI5ZWMwZDJiM2U1YmE3YjIyNTk2ZTRjN2I4YWM2ZDdiN2M4MTgxMmI1MGFjZTBhNWI2ZDBiZTNjZTVmOTc3Zjc1MzA2OWQ5NTFiZjE1ZDEzZjE3OTAxNGRmIiwgImFsZ29yaXRobSI6ICJibGFrZTJiIiwgImtleWVkIjogdHJ1ZSwgInNhbHQiOiAiIiwgInBlcnNvbiI6ICIifX0='
------------------------------
 {
    "header": {
        "type": "Testing Token",
        "duration": {
            "unit": {
                "type": "time",
                "name": "seconds",
                "shorthand": "s"
            },
            "value": 3600
        },
        "created": {
            "unit": {
                "type": "time",
                "name": "seconds since epoch",
                "shorthand": "s+epoch"
            },
            "value": 1677382369
        },
        "expires": {
            "unit": {
                "type": "time",
                "name": "seconds since epoch",
                "shorthand": "s+epoch"
            },
            "value": 1677385969
        }
    },
    "body": {
        "user": {
            "id": 69,
            "username": "nice"
        },
        "data": {
            "info": "Some Information",
            "value": true
        }
    },
    "signature": {
        "value": "e0b99c4eca2811bd9d164185219a283a4fddc2129ec0d2b3e5ba7b22596e4c7b8ac6d7b7c81812b50ace0a5b6d0be3ce5f977f753069d951bf15d13f179014df",
        "algorithm": "blake2b",
        "keyed": true,
        "salt": "",
        "person": ""
    }
}
------------------------------
 True
```

</details>
<br>

## Validate a token

```python
from bootleg_jwt import BootlegJWT, Payload, header, body
from pydantic import BaseModel
from os import environ              # An environment variable is required.


SECRET = "some-secret-key"


DURATION = 60 * 60                  # Token expires after this many seconds


TYPE = "Testing Token"              # An arbitrary name


environ['SECRET'] = SECRET          # This module depends upon an environment
                                    # variable `SECRET`. You may also set this
                                    # secret in a `.env` file in your project's root,
                                    # or by using `export SECRET="secret"`



## These two pydantic models are simple examples. They may have arbitrary names and data. They must only map to Token.body.user and Token.body.data
class UserData(BaseModel):
    id: int
    username: str


class BodyData(BaseModel):
    info: str
    value: bool


payload_user = UserData(id=69,username="nice")
payload_body = BodyData(info="Some Information", value=True)


payload = Payload(
    header=header(duration=DURATION,type=TYPE),
    body=body(user=payload_user,data=payload_body)
)


divider = "\n------------------------------\n"


def generate(payload):
    generate = BootlegJWT(payload=payload)
    decoded = generate.DECODED
    encoded = generate.ENCODED
    json = generate.JSON
    validate = generate.VALID
    print(decoded,divider,encoded,divider,json,divider,validate)
    return encoded


def validate_token(token):
    validate_token = BootlegJWT(token=token)
    v_decoded = validate_token.DECODED
    v_json = validate_token.JSON
    v_valid = validate_token.VALID
    print(v_decoded,divider,v_json,divider,v_valid)


validate_token(generate(payload))
```

<details>
<summary>Output (click to expand):</summary>
<br>

```json
header=Header(type='Testing Token', duration=Duration(unit=Unit(type='time', name='seconds', shorthand='s'), value=3600), created=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677383225), expires=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677386825)) body=Body(user=UserData(id=69, username='nice'), data=BodyData(info='Some Information', value=True)) signature=Hash(value=b'9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d', algorithm='blake2b', keyed=True, salt=b'', person=b'')
------------------------------
 b'eyJoZWFkZXIiOiB7InR5cGUiOiAiVGVzdGluZyBUb2tlbiIsICJkdXJhdGlvbiI6IHsidW5pdCI6IHsidHlwZSI6ICJ0aW1lIiwgIm5hbWUiOiAic2Vjb25kcyIsICJzaG9ydGhhbmQiOiAicyJ9LCAidmFsdWUiOiAzNjAwfSwgImNyZWF0ZWQiOiB7InVuaXQiOiB7InR5cGUiOiAidGltZSIsICJuYW1lIjogInNlY29uZHMgc2luY2UgZXBvY2giLCAic2hvcnRoYW5kIjogInMrZXBvY2gifSwgInZhbHVlIjogMTY3NzM4MzIyNX0sICJleHBpcmVzIjogeyJ1bml0IjogeyJ0eXBlIjogInRpbWUiLCAibmFtZSI6ICJzZWNvbmRzIHNpbmNlIGVwb2NoIiwgInNob3J0aGFuZCI6ICJzK2Vwb2NoIn0sICJ2YWx1ZSI6IDE2NzczODY4MjV9fSwgImJvZHkiOiB7InVzZXIiOiB7ImlkIjogNjksICJ1c2VybmFtZSI6ICJuaWNlIn0sICJkYXRhIjogeyJpbmZvIjogIlNvbWUgSW5mb3JtYXRpb24iLCAidmFsdWUiOiB0cnVlfX0sICJzaWduYXR1cmUiOiB7InZhbHVlIjogIjlhNmEzZmM1Yzg2NjQ0MmVlODg2YzFkMjBmNDRmZTQ5ZGEyOWJlNGU1NmZkNmY0MGExYzNlMjNmNjcyZDgwMWMwZDc4N2Y5ZjIzOTI2NTQ3N2RhMTMzOWZmZmM0MTc1NGYxNmEwODk5ZjU5NTVhYTBlZDc2MDI2OTM5MTkwNzFkIiwgImFsZ29yaXRobSI6ICJibGFrZTJiIiwgImtleWVkIjogdHJ1ZSwgInNhbHQiOiAiIiwgInBlcnNvbiI6ICIifX0='
------------------------------
 {
    "header": {
        "type": "Testing Token",
        "duration": {
            "unit": {
                "type": "time",
                "name": "seconds",
                "shorthand": "s"
            },
            "value": 3600
        },
        "created": {
            "unit": {
                "type": "time",
                "name": "seconds since epoch",
                "shorthand": "s+epoch"
            },
            "value": 1677383225
        },
        "expires": {
            "unit": {
                "type": "time",
                "name": "seconds since epoch",
                "shorthand": "s+epoch"
            },
            "value": 1677386825
        }
    },
    "body": {
        "user": {
            "id": 69,
            "username": "nice"
        },
        "data": {
            "info": "Some Information",
            "value": true
        }
    },
    "signature": {
        "value": "9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d",
        "algorithm": "blake2b",
        "keyed": true,
        "salt": "",
        "person": ""
    }
}
------------------------------
 True
header=Header(type='Testing Token', duration=Duration(unit=Unit(type='time', name='seconds', shorthand='s'), value=3600), created=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677383225), expires=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677386825)) body=Body(user={'id': 69, 'username': 'nice'}, data={'info': 'Some Information', 'value': True}) signature=Hash(value=b'9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d', algorithm='blake2b', keyed=True, salt=b'', person=b'')
------------------------------
 {
    "header": {
        "type": "Testing Token",
        "duration": {
            "unit": {
                "type": "time",
                "name": "seconds",
                "shorthand": "s"
            },
            "value": 3600
        },
        "created": {
            "unit": {
                "type": "time",
                "name": "seconds since epoch",
                "shorthand": "s+epoch"
            },
            "value": 1677383225
        },
        "expires": {
            "unit": {
                "type": "time",
                "name": "seconds since epoch",
                "shorthand": "s+epoch"
            },
            "value": 1677386825
        }
    },
    "body": {
        "user": {
            "id": 69,
            "username": "nice"
        },
        "data": {
            "info": "Some Information",
            "value": true
        }
    },
    "signature": {
        "value": "9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d",
        "algorithm": "blake2b",
        "keyed": true,
        "salt": "",
        "person": ""
    }
}
------------------------------
 True


```

## Renew a token

Using `BootlegJWT.renew(token)`, you may pass a token to BootlegJWT in bytestring form. This function will return an instance of `BootlegJWT` with a new token and expiration date, retaining all of the input token's properties.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/freyjagp/bootleg-jwt",
    "name": "bootleg-jwt",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.10, <4",
    "maintainer_email": "",
    "keywords": "cryptography,tokens,hashing",
    "author": "Freyja Odinthrir",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/40/26/2dee8210e74dc8d85c797afe95811c5d9aa396b6bbdc39d726c75c1df367/bootleg-jwt-0.3.0.tar.gz",
    "platform": null,
    "description": "# bootleg-jwt <!-- omit in toc -->\n\n`bootleg-jwt` aims to mimic JSON Web Tokens in a simple, `pydantic` way.\n\n___\n\n## New for v0.3.0 <!-- omit in toc -->\n\nVersion 0.3.0 extends v0.2.x with backwards compatible addition of the `_salt` and `_person` arguments. When these arguments are passed alongside a token, the token's hash is generated using them. Note: the `_salt` and `_person` arguments may not be longer than 16 bytes. This is a limitation of the blake2b hashing algorithm. If a string is supplied, it will be encoded to utf-8 and truncated automatically. Otherwise, any bytestring longer than 16 bytes will fail validation. This is by design.\n\n`_salt` and `_person` allow the token to be namespaced and salted. This provides an extra layer of validation, allowing implementations of `BootlegJWT` to perform more checks on tokens, other than what is baked in. This would allow, for example, invalidating all tokens with a particular salt or namespace.\n\n___\n\n## Table of Contents <!-- omit in toc -->\n\n- [Generate a token](#generate-a-token)\n- [Validate a token](#validate-a-token)\n- [Renew a token](#renew-a-token)\n\n## Generate a token\n\n```python\nfrom bootleg_jwt import BootlegJWT, Payload, header, body\nfrom pydantic import BaseModel\nfrom os import environ              # An environment variable is required.\n\n\nSECRET = \"some-secret-key\"\n\n\nDURATION = 60 * 60                  # Token expires after this many seconds\n\n\nTYPE = \"Testing Token\"              # An arbitrary name\n\n\nenviron['SECRET'] = SECRET          # This module depends upon an environment\n                                    # variable `SECRET`. You may also set this\n                                    # secret in a `.env` file in your project's root,\n                                    # or by using `export SECRET=\"secret\"`\n\n\n\n## These two pydantic models are simple examples. They may have arbitrary names and data. They must only map to Token.body.user and Token.body.data\nclass UserData(BaseModel):\n    id: int\n    username: str\n\n\nclass BodyData(BaseModel):\n    info: str\n    value: bool\n\n\npayload_user = UserData(id=69,username=\"nice\")\npayload_body = BodyData(info=\"Some Information\", value=True)\n\n\npayload = Payload(\n    header=header(duration=DURATION,type=TYPE),\n    body=body(user=payload_user,data=payload_body)\n)\n\n\ngenerate = BootlegJWT(payload=payload)\ntoken = generate.TOKEN\nencoded = generate.ENCODED\njson = generate.JSON\nvalidate = generate.VALID\ndivider = \"\\n------------------------------\\n\"\n\n\n\nprint(token,divider,encoded,divider,json,divider,validate)\n```\n\n<details>\n<summary>Output (click to expand):</summary>\n<br>\n\n```json\nheader=Header(type='Testing Token', duration=Duration(unit=Unit(type='time', name='seconds', shorthand='s'), value=3600), created=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677382369), expires=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677385969)) body=Body(user=UserData(id=69, username='nice'), data=BodyData(info='Some Information', value=True)) signature=Hash(value=b'e0b99c4eca2811bd9d164185219a283a4fddc2129ec0d2b3e5ba7b22596e4c7b8ac6d7b7c81812b50ace0a5b6d0be3ce5f977f753069d951bf15d13f179014df', algorithm='blake2b', keyed=True, salt=b'', person=b'')\n------------------------------\n b'eyJoZWFkZXIiOiB7InR5cGUiOiAiVGVzdGluZyBUb2tlbiIsICJkdXJhdGlvbiI6IHsidW5pdCI6IHsidHlwZSI6ICJ0aW1lIiwgIm5hbWUiOiAic2Vjb25kcyIsICJzaG9ydGhhbmQiOiAicyJ9LCAidmFsdWUiOiAzNjAwfSwgImNyZWF0ZWQiOiB7InVuaXQiOiB7InR5cGUiOiAidGltZSIsICJuYW1lIjogInNlY29uZHMgc2luY2UgZXBvY2giLCAic2hvcnRoYW5kIjogInMrZXBvY2gifSwgInZhbHVlIjogMTY3NzM4MjM2OX0sICJleHBpcmVzIjogeyJ1bml0IjogeyJ0eXBlIjogInRpbWUiLCAibmFtZSI6ICJzZWNvbmRzIHNpbmNlIGVwb2NoIiwgInNob3J0aGFuZCI6ICJzK2Vwb2NoIn0sICJ2YWx1ZSI6IDE2NzczODU5Njl9fSwgImJvZHkiOiB7InVzZXIiOiB7ImlkIjogNjksICJ1c2VybmFtZSI6ICJuaWNlIn0sICJkYXRhIjogeyJpbmZvIjogIlNvbWUgSW5mb3JtYXRpb24iLCAidmFsdWUiOiB0cnVlfX0sICJzaWduYXR1cmUiOiB7InZhbHVlIjogImUwYjk5YzRlY2EyODExYmQ5ZDE2NDE4NTIxOWEyODNhNGZkZGMyMTI5ZWMwZDJiM2U1YmE3YjIyNTk2ZTRjN2I4YWM2ZDdiN2M4MTgxMmI1MGFjZTBhNWI2ZDBiZTNjZTVmOTc3Zjc1MzA2OWQ5NTFiZjE1ZDEzZjE3OTAxNGRmIiwgImFsZ29yaXRobSI6ICJibGFrZTJiIiwgImtleWVkIjogdHJ1ZSwgInNhbHQiOiAiIiwgInBlcnNvbiI6ICIifX0='\n------------------------------\n {\n    \"header\": {\n        \"type\": \"Testing Token\",\n        \"duration\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds\",\n                \"shorthand\": \"s\"\n            },\n            \"value\": 3600\n        },\n        \"created\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds since epoch\",\n                \"shorthand\": \"s+epoch\"\n            },\n            \"value\": 1677382369\n        },\n        \"expires\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds since epoch\",\n                \"shorthand\": \"s+epoch\"\n            },\n            \"value\": 1677385969\n        }\n    },\n    \"body\": {\n        \"user\": {\n            \"id\": 69,\n            \"username\": \"nice\"\n        },\n        \"data\": {\n            \"info\": \"Some Information\",\n            \"value\": true\n        }\n    },\n    \"signature\": {\n        \"value\": \"e0b99c4eca2811bd9d164185219a283a4fddc2129ec0d2b3e5ba7b22596e4c7b8ac6d7b7c81812b50ace0a5b6d0be3ce5f977f753069d951bf15d13f179014df\",\n        \"algorithm\": \"blake2b\",\n        \"keyed\": true,\n        \"salt\": \"\",\n        \"person\": \"\"\n    }\n}\n------------------------------\n True\n```\n\n</details>\n<br>\n\n## Validate a token\n\n```python\nfrom bootleg_jwt import BootlegJWT, Payload, header, body\nfrom pydantic import BaseModel\nfrom os import environ              # An environment variable is required.\n\n\nSECRET = \"some-secret-key\"\n\n\nDURATION = 60 * 60                  # Token expires after this many seconds\n\n\nTYPE = \"Testing Token\"              # An arbitrary name\n\n\nenviron['SECRET'] = SECRET          # This module depends upon an environment\n                                    # variable `SECRET`. You may also set this\n                                    # secret in a `.env` file in your project's root,\n                                    # or by using `export SECRET=\"secret\"`\n\n\n\n## These two pydantic models are simple examples. They may have arbitrary names and data. They must only map to Token.body.user and Token.body.data\nclass UserData(BaseModel):\n    id: int\n    username: str\n\n\nclass BodyData(BaseModel):\n    info: str\n    value: bool\n\n\npayload_user = UserData(id=69,username=\"nice\")\npayload_body = BodyData(info=\"Some Information\", value=True)\n\n\npayload = Payload(\n    header=header(duration=DURATION,type=TYPE),\n    body=body(user=payload_user,data=payload_body)\n)\n\n\ndivider = \"\\n------------------------------\\n\"\n\n\ndef generate(payload):\n    generate = BootlegJWT(payload=payload)\n    decoded = generate.DECODED\n    encoded = generate.ENCODED\n    json = generate.JSON\n    validate = generate.VALID\n    print(decoded,divider,encoded,divider,json,divider,validate)\n    return encoded\n\n\ndef validate_token(token):\n    validate_token = BootlegJWT(token=token)\n    v_decoded = validate_token.DECODED\n    v_json = validate_token.JSON\n    v_valid = validate_token.VALID\n    print(v_decoded,divider,v_json,divider,v_valid)\n\n\nvalidate_token(generate(payload))\n```\n\n<details>\n<summary>Output (click to expand):</summary>\n<br>\n\n```json\nheader=Header(type='Testing Token', duration=Duration(unit=Unit(type='time', name='seconds', shorthand='s'), value=3600), created=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677383225), expires=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677386825)) body=Body(user=UserData(id=69, username='nice'), data=BodyData(info='Some Information', value=True)) signature=Hash(value=b'9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d', algorithm='blake2b', keyed=True, salt=b'', person=b'')\n------------------------------\n b'eyJoZWFkZXIiOiB7InR5cGUiOiAiVGVzdGluZyBUb2tlbiIsICJkdXJhdGlvbiI6IHsidW5pdCI6IHsidHlwZSI6ICJ0aW1lIiwgIm5hbWUiOiAic2Vjb25kcyIsICJzaG9ydGhhbmQiOiAicyJ9LCAidmFsdWUiOiAzNjAwfSwgImNyZWF0ZWQiOiB7InVuaXQiOiB7InR5cGUiOiAidGltZSIsICJuYW1lIjogInNlY29uZHMgc2luY2UgZXBvY2giLCAic2hvcnRoYW5kIjogInMrZXBvY2gifSwgInZhbHVlIjogMTY3NzM4MzIyNX0sICJleHBpcmVzIjogeyJ1bml0IjogeyJ0eXBlIjogInRpbWUiLCAibmFtZSI6ICJzZWNvbmRzIHNpbmNlIGVwb2NoIiwgInNob3J0aGFuZCI6ICJzK2Vwb2NoIn0sICJ2YWx1ZSI6IDE2NzczODY4MjV9fSwgImJvZHkiOiB7InVzZXIiOiB7ImlkIjogNjksICJ1c2VybmFtZSI6ICJuaWNlIn0sICJkYXRhIjogeyJpbmZvIjogIlNvbWUgSW5mb3JtYXRpb24iLCAidmFsdWUiOiB0cnVlfX0sICJzaWduYXR1cmUiOiB7InZhbHVlIjogIjlhNmEzZmM1Yzg2NjQ0MmVlODg2YzFkMjBmNDRmZTQ5ZGEyOWJlNGU1NmZkNmY0MGExYzNlMjNmNjcyZDgwMWMwZDc4N2Y5ZjIzOTI2NTQ3N2RhMTMzOWZmZmM0MTc1NGYxNmEwODk5ZjU5NTVhYTBlZDc2MDI2OTM5MTkwNzFkIiwgImFsZ29yaXRobSI6ICJibGFrZTJiIiwgImtleWVkIjogdHJ1ZSwgInNhbHQiOiAiIiwgInBlcnNvbiI6ICIifX0='\n------------------------------\n {\n    \"header\": {\n        \"type\": \"Testing Token\",\n        \"duration\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds\",\n                \"shorthand\": \"s\"\n            },\n            \"value\": 3600\n        },\n        \"created\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds since epoch\",\n                \"shorthand\": \"s+epoch\"\n            },\n            \"value\": 1677383225\n        },\n        \"expires\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds since epoch\",\n                \"shorthand\": \"s+epoch\"\n            },\n            \"value\": 1677386825\n        }\n    },\n    \"body\": {\n        \"user\": {\n            \"id\": 69,\n            \"username\": \"nice\"\n        },\n        \"data\": {\n            \"info\": \"Some Information\",\n            \"value\": true\n        }\n    },\n    \"signature\": {\n        \"value\": \"9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d\",\n        \"algorithm\": \"blake2b\",\n        \"keyed\": true,\n        \"salt\": \"\",\n        \"person\": \"\"\n    }\n}\n------------------------------\n True\nheader=Header(type='Testing Token', duration=Duration(unit=Unit(type='time', name='seconds', shorthand='s'), value=3600), created=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677383225), expires=Timestamp(unit=Unit(type='time', name='seconds since epoch', shorthand='s+epoch'), value=1677386825)) body=Body(user={'id': 69, 'username': 'nice'}, data={'info': 'Some Information', 'value': True}) signature=Hash(value=b'9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d', algorithm='blake2b', keyed=True, salt=b'', person=b'')\n------------------------------\n {\n    \"header\": {\n        \"type\": \"Testing Token\",\n        \"duration\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds\",\n                \"shorthand\": \"s\"\n            },\n            \"value\": 3600\n        },\n        \"created\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds since epoch\",\n                \"shorthand\": \"s+epoch\"\n            },\n            \"value\": 1677383225\n        },\n        \"expires\": {\n            \"unit\": {\n                \"type\": \"time\",\n                \"name\": \"seconds since epoch\",\n                \"shorthand\": \"s+epoch\"\n            },\n            \"value\": 1677386825\n        }\n    },\n    \"body\": {\n        \"user\": {\n            \"id\": 69,\n            \"username\": \"nice\"\n        },\n        \"data\": {\n            \"info\": \"Some Information\",\n            \"value\": true\n        }\n    },\n    \"signature\": {\n        \"value\": \"9a6a3fc5c866442ee886c1d20f44fe49da29be4e56fd6f40a1c3e23f672d801c0d787f9f239265477da1339fffc41754f16a0899f5955aa0ed7602693919071d\",\n        \"algorithm\": \"blake2b\",\n        \"keyed\": true,\n        \"salt\": \"\",\n        \"person\": \"\"\n    }\n}\n------------------------------\n True\n\n\n```\n\n## Renew a token\n\nUsing `BootlegJWT.renew(token)`, you may pass a token to BootlegJWT in bytestring form. This function will return an instance of `BootlegJWT` with a new token and expiration date, retaining all of the input token's properties.\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Sign tokens with blake2b, then verify them.",
    "version": "0.3.0",
    "project_urls": {
        "Bug Reports": "https://github.com/freyjagp/bootleg-jwt/issues",
        "Homepage": "https://github.com/freyjagp/bootleg-jwt",
        "Source": "https://github.com/freyjagp/bootleg-jwt/"
    },
    "split_keywords": [
        "cryptography",
        "tokens",
        "hashing"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6b434221428eddd2e61cff7401ef6dc44cd14307bd2ba607438e195ac051d685",
                "md5": "f8a714ec784fb35f5a77d9e05b663fa3",
                "sha256": "7ec08f258b64caccc7f410ea7edc69ab9af1e3ea048c2e4a53cf03e23ed8534e"
            },
            "downloads": -1,
            "filename": "bootleg_jwt-0.3.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f8a714ec784fb35f5a77d9e05b663fa3",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10, <4",
            "size": 9855,
            "upload_time": "2023-06-17T01:44:08",
            "upload_time_iso_8601": "2023-06-17T01:44:08.632461Z",
            "url": "https://files.pythonhosted.org/packages/6b/43/4221428eddd2e61cff7401ef6dc44cd14307bd2ba607438e195ac051d685/bootleg_jwt-0.3.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "40262dee8210e74dc8d85c797afe95811c5d9aa396b6bbdc39d726c75c1df367",
                "md5": "a122e8afa463137aa494f81ddba175ce",
                "sha256": "89f086d23d89f681a32b01ce868e78dd6b9eb7081a87128b155c9a4f5f5fbf70"
            },
            "downloads": -1,
            "filename": "bootleg-jwt-0.3.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a122e8afa463137aa494f81ddba175ce",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10, <4",
            "size": 9306,
            "upload_time": "2023-06-17T01:44:11",
            "upload_time_iso_8601": "2023-06-17T01:44:11.673540Z",
            "url": "https://files.pythonhosted.org/packages/40/26/2dee8210e74dc8d85c797afe95811c5d9aa396b6bbdc39d726c75c1df367/bootleg-jwt-0.3.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-17 01:44:11",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "freyjagp",
    "github_project": "bootleg-jwt",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "bootleg-jwt"
}
        
Elapsed time: 0.08201s