Metadata-Version: 2.1
Name: handshake
Version: 0.2.1
Summary: A Python library to create and validate authentication tokens.
Home-page: https://github.com/meeb/handshake
Author: https://github.com/meeb
Author-email: meeb@meeb.org
License: BSD
Description: # handshake
        
        A Python library to create and validate authentication tokens.
        
        `handshake` is used to generate and validate arbitrary authentication tokens
        that contain arbitrary metadata and support expiration. It uses basic
        cryptographic primitives (hashing, HMACs) and is based around the concept of a
        shared private secret for security.
        
        Example usage would be to create namespaced authentication tokens for clients
        of an API which another service can check is valid and hasn't expired. The
        tokens are safe to be made public, put in headers etc. and can be used like
        session tokens.
        
        The tokens are strings in the format of:
        
        ```
        arbitrary:data:here:timestamp:random:signature
        ```
        
        All fields other than timestamp, random and signature are optional. Signatures
        are in the format of:
        
        ```
        HMAC(arbitrary:data:here:timestamp:random){shared_secret}
        ```
        
        The library is designed to allow whatever metadata is required into the token,
        such as the first parameter could be a namespace and the second parameter an
        object id. This allows tokens to be easily split between internal systems and
        uses while containing metadata or IDs for other objects.
        
        For example, you could use `handshake` to allow an API to generate tokens which
        a client stores for a variable amount of time and can verify their state with
        other services. The arbitrary data prefix can be used to store an application
        namespace and the UUID of the object being referenced (such as `user:uuid` or
        `service:recordtype:uuid`). This library is of most use if you have multiple
        diverse systems, microservices or other distributed endpoints that require
        ad-hoc authentication and something like JWT or OAuth is overkill.
        
        
        ## Installation
        
        `handshake` is pure Python and has no dependancies. You can install `handshake`
        via pip:
        
        ```bash
        $ pip install handshake
        ```
        
        Any modern version of Python3 will be compatible.
        
        
        ## Usage
        
        `handshake` has one class providing two basic public functions. Examples:
        
        ```python
        import os
        from handshake import AuthToken
        
        # The shared secret, keep this private, can be str or bytes but needs to be
        # from a cryptographically secure source
        secret = os.urandom(128)
        
        # Create the instance
        token = AuthToken(secret)
        
        # Basic token with no additional parameters
        plain_token = token.create()
        token.verify(plain_token)
        
        # The token must be no more than 300 seconds old
        plain_token = token.create()
        token.verify(plain_token, time_range=300)
        
        # Namespaced but no specific item, namespace is arbitrary
        namespaced_token = token.create('namespace')
        token.verify(namespaced_token)
        
        # Namespaced and with an arbitrary item ID
        from uuid import uuid4
        client_token = token.create('user', uuid4())
        token.verify(client_token)
        
        # Lots of metadata
        client_token = token.create('network', 'node', '12345', '67890')
        token.verify(client_token)
        
        # Use blake2s for hashes and signatures
        from hashlib import blake2s
        token = AuthToken(secret, hashfunc=blake2s)
        blake2s_token = token.create()
        token.verify(blake2s_token)
        ```
        
        If a token fails to validate it raise the relevent exception:
        
        ```python
        # Create a token with one secret
        token = AuthToken('a fixed secret string')
        plain_token = token.create()
        
        # Attempt to verify it with a different token, this is invalid
        token_with_different_secret = AuthToken('not the same secret string')
        token_with_different_secret.verify(plain_token)
        # ... a child of handshake.errors.InvalidTokenError exception is raised
        ```
        
        ## Limitations
        
        The secret must be at least 16 bytes or characters and no more than 1024 bytes
        or characters. The total generated token length cannot be longer than 2048
        characters.
        
        
        ## Full API synopsis
        
        ### `handshake.AuthToken(secret=str_or_bool, hashfunc=function)`
        
        Initiates an AuthToken object using the specified secret. The secret is
        required. It must be either a string or a bytes and must be between 32 and 1024
        characters or bytes in length. The secret should be sourced from a
        cryptographically safe random source, such as `os.urandom`.
        
        `hashfunc` defaults to `hashlib.sha256` but you can replace it with another
        hash function if you need to.
        
        ### `handshake.AuthToken.create(*arbitrary str)`
        
        Creates an authentication token.
        
        ### `handshake.AuthToken.verify(token=str, time_range=int)`
        
        Verifies an authentication token created with `handshake.AuthToken.create()`.
        
        `time_range` is an optional integer which if set specifies the valid time
        range the token must have been generated within. This is used to verify
        expiring tokens. It defaults to `0` which disables time range validation.
        
        If the token is valid a tuple containing any arbitrary data in the token. For
        example a token of
        
        ```
        arbitrary:data:here:timestamp:random:signature
        ```
        
        If valid would return a tuple of:
        
        ```python
        ('arbitrary', 'data', 'here')
        ```
        
        If the token is invalid for any reason a `handshake.errors.InvalidTokenError`
        exception is raised (or a child exception of
        `handshake.errors.InvalidTokenError`). You can handle different errors by
        catching them specifically and the exception names describe the event:
        
        ```python
        import os
        from handshake import AuthToken, errors
        
        secret = os.urandom(128)
        token = AuthToken(secret)
        test_token = token.create()
        
        try:
            token.verify(test_token)
        except errors.TokenExpiredError as e:
            print(e)
        except errors.TokenSignatureError as e:
            print(e)
        except errors.InvalidTokenError as e:
            print(e)
        ```
        
        
        # Tests
        
        There is a test suite that you can run by cloning this repository and
        executing:
        
        ```bash
        $ make test
        ```
        
        
        # Contributing
        
        All properly formatted and sensible pull requests, issues and comments are
        welcome.
        
Keywords: handshake,auth,tokens,authentication,tickets
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Description-Content-Type: text/markdown
