User Guide

The objective of security is protection of information from theft or corruption, while allowing the information to remain accessible to its intended users.

Ticket

Ticket is a short packet of bytes generated by a network server for a client, which can be delivered to itself as a means of authentication or proof of authorization, and cannot easily be forged.

Ticket has the following characteristics:

  • It is valid for certain period of time, in particular it has an explicitly set expiration time.
  • Its value is signed to prove its authenticity.
  • It is encrypted to protect sensitive information.
  • It has noise to harden forgery.

Ticket can be instantiated by passing the following arguments:

  • max_age - period of time (in seconds) this Ticket is considered valid.
  • salt - a random sequence that hardens against ticket forgery. It is prepended to the validation key and the encryption key.
  • digestmod - hash algorithm used with HMAC (Hash-based Message Authentication Code) to sign ticket. Defaults to SHA1.
  • cypher - cryptography algorithm. Defaults to AES128.
  • options - a dictionary that holds the following configuration values: CRYPTO_VALIDATION_KEY (used by signature) and CRYPTO_ENCRYPTION_KEY (used by encryption).

Validation and Encryption Keys

Keys used for validation and encryption are ensured to be at least of 320 bits length. The ensure_strong_key() function appends HMAC signature to the key.

If the cryptography library is not available you will see a warning message:

Ticket: cypher not available

Although Ticket continues to function even cryptography library is not installed it strongly recommended to use cryptography in a production environment.

Thread Safety

Ticket does not alter it state once initialized. It is guaranteed to be thread safe.

Typical Use Case

Here is typical use case when all possible configuration attributes are used:

from wheezy.security.crypto.comp import aes192
from wheezy.security.crypto.comp import sha1
from wheezy.security.crypto import Ticket

options = {
    'CRYPTO_VALIDATION_KEY': 'LkLlYR5WbTk54kaIgJOp',
    'CRYPTO_ENCRYPTION_KEY': 'rH64daeXBZdgrR7WNawf'
}

ticket = Ticket(
        max_age=1200,
        salt='CzQnV0KazDKElBYiIC2w',
        digestmod=sha1,
        cypher=aes192,
        options=options)

The ticket instance can be shared application wide. The encode / decode methods are used in the following way:

protected_value = ticket.encode('hello')

assert 'hello' == ticket.decode(protected_value)

In case the validity of a ticket cannot be confirmed, the decode method returns None.

Extensibility

Ticket cypher can be any callable that satisfies the following contract:

  • Initialization is called with encryption key. Returned object must be a factory for the actual algorithm instance.
  • Algorithm factory must return new algorithm via simple callable with no arguments.
  • Algorithm implementation must support two methods: encrypt(value) and decrypt(value).

Principal

Principal is a container of user specific security information. It includes the following attributes:

  • id - user identity, e.g. number 755345, UUID f102a87b-ee36-4a2e-97de-8f803f470867 or whatever else is valid to look up a user quickly in your application.
  • roles - a list of authorized user roles, e.g. user, manager, etc.
  • alias - a user friendly name, display name, etc. This can be something like John Smith, etc.
  • extra - any string you would like to hold in security context.

Here is a sample how to instantiate new Principal:

principal = Principal(
        id='125134788',
        roles=['user'],
        alias='John Smith')

Principal supports the following methods:

  • dump - converts instance to a string.
  • load - reverse operation to dump.

You can use Ticket to securely pass Principal across network boundaries. Combining them both you can introduce an authentication/authorization cookie to your application.

Authorization

Authorization specifies access rights to resources and provides access control in particular to your application.

You are able to request authorization by decorating your method with authorized(). Here is a typical use case:

from wheezy.security import authorized

class MyBusinessLogic(object):

     principal = None

     @authorized
     def cancel_transfer(self, id):
         return True

     @authorized(roles=('operator',))
     def approve_transfer(self):
         return True

Note that the authorized() decorator requires the object to supply a principal attribute of type Principal.

If a caller is not authorized to perform a requested operation, a SecurityError exception is raised. See authorized() for more details.

Table Of Contents

Previous topic

Examples

Next topic

Modules

This Page