Skip to content

Commit

Permalink
Merge pull request #140 from ahopkins/dev
Browse files Browse the repository at this point in the history
Version 1.2.0 - 2018-11-08
  • Loading branch information
ahopkins committed Nov 8, 2018
2 parents de3d6eb + 6aa63ab commit eb4b55d
Show file tree
Hide file tree
Showing 58 changed files with 1,325 additions and 371 deletions.
5 changes: 2 additions & 3 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ source =
tests

[run]
source =
sanic_jwt
tests
source = sanic_jwt
omit = tests
branch = True

[report]
Expand Down
63 changes: 43 additions & 20 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,48 @@
# Config file for automatic testing at travis-ci.org

language: python

python:
# - "3.7-dev"
- "3.6"
- "3.5"
# - "pypy"

# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
dist: xenial
sudo: true
env:
global:
- LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
- SEGFAULT_SIGNALS=all
- DEVELOPMENT=false
matrix:
fast_finish: true
include:
- python: "3.5"
env: TOXENV=py35
- python: "3.6"
env: TOXENV=py36
- python: "3.7"
env: TOXENV=py37
# - python: "3.6"
# env: TOXENV=check
cache:
directories:
- $HOME/.cache/pip
before_install:
- python --version
- uname -a
- lsb_release -a
- pip install codecov
install:
- pip install -r example/requirements.txt

# command to run tests, e.g. python setup.py test
- pip install tox
- virtualenv --version
- easy_install --version
- pip --version
- tox --version
script:
- python setup.py test

- tox -v
after_success:
- coverage xml
- python-codacy-coverage -r coverage.xml
- codecov

env:
- DEVELOPMENT=false
- tox -e report
- coverage xml
- python-codacy-coverage -r coverage.xml
- codecov
after_failure:
- more .tox/log/* | cat
- more .tox/*/log/* | cat
notifications:
email:
on_success: never
on_failure: always
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

[![Build Status](https://travis-ci.org/ahopkins/sanic-jwt.svg?branch=master)](https://travis-ci.org/ahopkins/sanic-jwt)
[![Documentation](https://readthedocs.org/projects/sanic-jwt/badge/?version=latest)](http://sanic-jwt.readthedocs.io/en/latest/?badge=latest)
[![Waffle.io](https://badge.waffle.io/ahopkins/sanic-jwt.svg?columns=In%20Progress)](https://waffle.io/ahopkins/sanic-jwt)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/9727756ffccd45f7bc5ad6292596e03d)](https://www.codacy.com/app/ahopkins/sanic-jwt?utm_source=github.com&utm_medium=referral&utm_content=ahopkins/sanic-jwt&utm_campaign=Badge_Grade)
[![Test Coverage](https://codecov.io/gh/ahopkins/sanic-jwt/branch/dev/graph/badge.svg)](https://codecov.io/gh/ahopkins/sanic-jwt)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)


Sanic JWT adds authentication protection and endpoints to [Sanic].
Expand Down
2 changes: 2 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
sphinx==1.8.1
sphinx_rtd_theme==0.4.2
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
# built documents.
#
# The short X.Y version.
version = u"1.1"
version = u"1.2"
# The full version, including alpha/beta/rc tags.
release = u"1.1.4"
release = u"1.2.0"

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
14 changes: 11 additions & 3 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Sanic JWT
=========

|Latest PyPI version| |Version status| |Python versions| |Build Status|
|Codacy Badge| |Documentation| Waffle.io|
|Codacy Badge| |Documentation| |Black|


Sanic JWT adds authentication protection and endpoints to `Sanic <http://sanic.readthedocs.io>`_.
Expand Down Expand Up @@ -38,6 +38,14 @@ Pick your favorite user management system, run :doc:`a single class to initializ

------------

+++++++++++++++++++++++++++
What is new in Version 1.2?
+++++++++++++++++++++++++++

**Version 1.2** saw a a few `minor fixes and changes <https://github.com/ahopkins/sanic-jwt/issues?q=is%3Aopen+is%3Aissue+milestone%3Av1.2>`_. Some new features were added to allow custom claims and additional payload verifications. **Version 1.1.4** is still stable, so there is no need to upgrade to **1.2**.

In addition, there was a change that will (unfortunately) have some potential impact on users. Expired and invalid tokens will report as ``HTTP 401``.

+++++++++++++++++++++++++++
What is new in Version 1.1?
+++++++++++++++++++++++++++
Expand Down Expand Up @@ -105,5 +113,5 @@ Have fun, and happy coding.
:target: https://www.codacy.com/app/ahopkins/sanic-jwt?utm_source=github.com&utm_medium=referral&utm_content=ahopkins/sanic-jwt&utm_campaign=Badge_Grade
.. |Documentation| image:: https://readthedocs.org/projects/sanic-jwt/badge/?version=latest
:target: http://sanic-jwt.readthedocs.io/en/latest/?badge=latest
.. |Waffle.io| image:: https://badge.waffle.io/ahopkins/sanic-jwt.svg?columns=In%20Progress
:target: https://waffle.io/ahopkins/sanic-jwt
.. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black
14 changes: 14 additions & 0 deletions docs/source/pages/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ Changelog

The format is based on `Keep a Changelog <http://keepachangelog.com/en/1.0.0/>`_ and this project adheres to `Semantic Versioning <http://semver.org/spec/v2.0.0.html>`_.

++++++++++++++++++++++++++
Version 1.2.0 - 2018-08-06
++++++++++++++++++++++++++

| **Added**
| - Custom claims
| - Extra payload validation
| - Configuration option: ``SANIC_JWT_DO_PROTECTION``
|
| **Changed**
| - Invalid tokens now ``401`` instead of ``403``
|
++++++++++++++++++++++++++
Version 1.1.4 - 2018-08-06
++++++++++++++++++++++++++
Expand Down
8 changes: 8 additions & 0 deletions docs/source/pages/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,14 @@ Alias for ``cookie_access_token_name``
| **Default**: ``False``
|
-----------------
``do_protection``
-----------------

| **Purpose**: Whether or not protection should be inforced. This almost **always** should stay as ``True``, unless you know what you are doing since it will effectively render the ``@protected`` decorator useless and all traffic will be passed thru.
| **Default**: ``True``
|
--------------------
``expiration_delta``
--------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/source/pages/endpoints.rst
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ One of the benefits of a lightweight framework like Sanic is that it makes build
http://app2.mymicroserviceapp.com/auth
http://app3.mymicroserviceapp.com/auth
Instead, you probably only want to authenticate against a single service, and use the token generated there among all yout services. This can be easily accomplished with the ``auth_mode=True`` :doc:`configuration`. Set it to ``True`` on your authentication service, and ``False`` everywhere else. All the decorators will still work as expected.
Instead, you probably only want to authenticate against a single service, and use the token generated there among all your services. This can be easily accomplished with the ``auth_mode=True`` :doc:`configuration`. Set it to ``True`` on your authentication service, and ``False`` everywhere else. All the decorators will still work as expected.

.. code-block:: python
Expand Down
2 changes: 1 addition & 1 deletion docs/source/pages/gettingstarted.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ You should get back a bit of JSON like this::

Want to check to make sure it is valid? ::

curl -X GET -H "Authorization: Bearer <JWT>" http://localhost:8888/auth/verify
curl -X GET -H "Authorization: Bearer <JWT>" http://localhost:8000/auth/verify

Your response should be this: ::

Expand Down
5 changes: 5 additions & 0 deletions docs/source/pages/initialization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ One of the most powerful concepts of the JWT is that you are able to pass data (
authenticate=lambda: True,
extend_payload=my_extender)
------------

---------------------
Runtime Configuration
Expand All @@ -375,6 +376,8 @@ There are several ways to :doc:`configure the settings<configuration>` for Sanic
claim_iat=True,
cookie_domain='example.com',)
------------

----------------
Additional Views
----------------
Expand Down Expand Up @@ -433,6 +436,8 @@ As an example, perhaps you would like to create a "passwordless" login. You coul
async def options(self, request):
return response.text('', status=204)
------------

-------------------
Component Overrides
-------------------
Expand Down
53 changes: 53 additions & 0 deletions docs/source/pages/payload.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,59 @@ Not before - ``NBF``
------------

+++++++++++++
Custom Claims
+++++++++++++

Sometimes you may find a need to add claims to a JWT beyond what is built into Sanic JWT.

To do so, simply subclass ``Claim`` and register them at :doc:`initialization<initialization>` by providing the custom claim class in a list to ``custom_claims``.

.. code-block:: python
from sanic_jwt import Claim, Initialize
MyCustomClaim(Claim):
key = 'foo'
def setup(self, payload, user):
return 'bar'
def verify(self, value):
return value == 'bar'
Initialize(..., custom_claims=[MyCustomClaim])
There are three attributes that a ``Claim`` must have: ``key``, ``setup``, and ``verify``.

| ``key``: The name of the claim and the key that will be inserted into the payload.
| ``setup``: A method to be run at the time the payload is created. It should return the value of the claim.
| ``verify``: A method to be run when a token is being verified. It should return a ``boolean`` whether or not the claim has been met.
|
------------

+++++++++++++++++++
Extra Verifications
+++++++++++++++++++

Besides registering custom claims, sometimes you may find the need to do additional verifications on a payload. For example, perhaps you want to run checks that span more than one claim on the payload.

To accomplish this, you can register a list of methods (that each return a ``boolean``) at :doc:`initialization<initialization>` by providing the list to ``extra_verifications``.

.. code-block:: python
def check_number_of_claims(payload):
return len(payload.keys()) == 5
extra_verifications = [check_number_of_claims]
Initialize(
...,
extra_verifications=extra_verifications
)
------------

++++++++++++++++
Payload Handlers
++++++++++++++++
Expand Down
65 changes: 65 additions & 0 deletions example/custom_authentication_cls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from sanic import Sanic
from sanic.response import json

from sanic_jwt import Authentication, exceptions, Initialize


class MyAuthentication(Authentication):

async def authenticate(self, request, *args, **kwargs):
username = request.json.get("username", None)
password = request.json.get("password", None)

if not username or not password:
raise exceptions.AuthenticationFailed(
"Missing username or password."
)

return {"user_id": 1}

async def store_refresh_token(
self, user_id, refresh_token, *args, **kwargs
):
key = "refresh_token_{user_id}".format(user_id=user_id)
self.app.my_cache[key] = refresh_token

async def retrieve_refresh_token(self, user_id, *args, **kwargs):
key = "refresh_token_{user_id}".format(user_id=user_id)
token = self.app.my_cache.get(key, None)
return token

async def retrieve_user(self, request, payload, *args, **kwargs):
if payload:
user_id = payload.get("user_id", None)
return {"user_id": user_id}

else:
return None


# elsewhere in the universe ...
if __name__ == "__main__":
app = Sanic(__name__)
app.my_cache = {}

sanicjwt = Initialize(
app, authentication_class=MyAuthentication, refresh_token_enabled=True
)

@app.route("/")
async def helloworld(request):
return json({"hello": "world"})

@app.route("/protected")
@sanicjwt.protected()
async def protected_request(request):
return json({"protected": True})

# this route is for demonstration only

@app.route("/cache")
@sanicjwt.protected()
async def protected_cache(request):
return json(request.app.my_cache)

app.run()

0 comments on commit eb4b55d

Please sign in to comment.