Code Monkey home page Code Monkey logo

apistar-jwt's Introduction

apistar-jwt

pypi travis codecov

DEPRECATION NOTICE

API Star gutted a lot of functionality to go a different path. As a result, this library will be obsolete. I don't intend to continue to maintain it.

If you liked the spirit of API Star, I would recommend checking out Molten and Molten JWT.


JSON Web Token Component for use with *API Star 0.4 <= x < 0.6.

Installation

$ pip install apistar-jwt

Alternatively, install through pipenv.

$ pipenv install apistar-jwt

Usage

Register the JWT Component with your APIStar app.

from apistar import App
from apistar_jwt.token import JWT

routes = [
  # ...
]

components = [
    JWT({
        'JWT_SECRET': 'BZz4bHXYQD?g9YN2UksRn7*r3P(eo]P,Rt8NCWKs6VP34qmTL#8f&ruD^TtG',
    }),
]

app = App(routes=routes, components=components)

Inject the JWT component in your login function and use it to encode the JWT.

from apistar import exceptions, types, validators
from apistar_jwt.token import JWT

class UserData(types.Type):
    email = validators.String()
    password = validators.String()


def login(data: UserData, jwt: JWT) -> dict:
    # do some check with your database here to see if the user is authenticated
    user = db_login(data)
    if not user:
        raise exceptions.Forbidden('Incorrect username or password.')
    payload = {
        'id': user.id,
        'username': user.email,
        'random_data': '102310',
    }
    token = jwt.encode(payload)
    if token is None:
        # encoding failed, handle error
        raise exceptions.BadRequest()
    return {'token': token}

Inject the JWTUser component in any resource where you want authentication with the provided JWT.

from apistar_jwt.token import JWTUser

def welcome(user: JWTUser) -> dict:
    message = f'Welcome {user.username}#{user.id}, here is your random data: {user.token["random_data"]}'
    return {'message': message}

Note

Requests made with JWT The token must be passed as an Authorization header using the Bearer scheme in requests made to a resource.

$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoxfQ.fCqeAJGHYwZ9y-hJ3CKUWPiENOM0xtGsMeUWmIq4o8Q" http://localhost:8080/some-resource-requiring-jwt-auth

Decorators

We provide two decorators for convenience to enforce authentication required or allow anonymous users for a route:

from apistar_jwt.token import JWTUser
from apistar_jwt.decorators import anonymous_allowed, authentication_required


@authentication_required
def auth_required(request: http.Request, user: JWTUser):
    return user.__dict__


@anonymous_allowed
def anon_allowed(request: http.Request, user: JWTUser):
    if user:
        return user.__dict__
    return None

The @authentication_required decorator will enforce the user to be logged in for that route. Meanwhile the @anonymous_allowed will set user: JWTUser=None and allow anonymous users to hit the route. The default behavior is @authentication_required so you do not need to annotate with this decorator, it is just to help your code be explicit.

Settings

There are two settings this package uses to identify the username and user_id keys in the JWT payload, they are by default:

{
  'JWT_USER_ID': 'id',
  'JWT_USER_NAME': 'username',
}

If your JWT uses some other kind of key, override these keys when you instantiate your component:

from apistar_jwt.token import JWT

components = [
  JWT({
    'JWT_USER_ID': 'pk',
    'JWT_USER_NAME': 'email',
  })
]

JWT_WHITE_LIST allows you to specify a list of route functions that will not require JWT authentication. This is useful if you have setup a default authentication policy but want to open up certain routes, especially ones that might be in third party packages or in apistar itself like the schema docs.

from apistar_jwt.token import JWT

components = [
  JWT({
    'JWT_WHITE_LIST': ['serve_schema', 'home'],
  })
]

In this instance, the serve_schema and home Routes will not require JWT authentication.

JWT_ALGORITHMS is related to the algorithms used for decoding JWTs. By default we only use 'HS256' but JWT supports passing an array of supported algorithms which it will sequentially try when attempting to decode.

from apistar_jwt.token import JWT

components = [
  JWT({
    'JWT_ALGORITHMS': ['HS256', 'RSA512'],
  })
]

JWT_AUTHORIZATION_PREFIX is the string that comes before the token in the Authorization header. Defaults to 'bearer' (the header is not case sensitive)

from apistar_jwt.token import JWT

components = [
  JWT({
    'JWT_AUTHORIZATION_PREFIX': 'jwt'
  })
]

JWT_SECRET is a long, randomized, secret key that should never be checked into version control.

from apistar_jwt.token import JWT

components = [
  JWT({
    'JWT_SECRET': 'QXp4Z83.%2F@JBiaPZ8T9YDwoasn[dn)cZ=fE}KqHMJPNka3QyPNq^KnMqL$oCsU9BC?.f9,oF2.2t4oN?[g%iq89(+'
  })
]

For all other settings, use JWT_OPTIONS key which will pass them along to the underlying PyJWT library when decoding.

from apistar_jwt.token import JWT

components = [
  JWT({
    'JWT_OPTIONS': {
      'issuer': 'urn:foo',
      'audience': 'urn:bar',
      'leeway': 10,
    },
  })
]

Quick rundown of the options:

audience is the urn for this applications audience, it must match a value in the aud key of the payload. Read more about audience claim.

issuer is the urn of the application that issues the token, it must match a value in the iss key of the payload. Read more about the issuer claim

leeway is the number of seconds of margin an expiration time claim in the past will still be valid for.

A fully customized JWT component would like like the following:

from apistar_jwt.token import JWT

components = [
  JWT({
    'JWT_ALGORITHMS': ['HS256', 'RSA512'],
    'JWT_USER_ID': 'pk',
    'JWT_USER_NAME': 'email',
    'JWT_SECRET': 'QXp4Z83.%2F@JBiaPZ8T9YDwoasn[dn)cZ=fE}KqHMJPNka3QyPNq^KnMqL$oCsU9BC?.f9,oF2.2t4oN?[g%iq89(+',
    'JWT_OPTIONS': {
      'issuer': 'urn:foo',
      'audience': 'urn:bar',
      'leeway': 10,
    },
    'JWT_WHITE_LIST': ['serve_schema'],
  })
]

Developing

This project uses pipenv to manage its development environment, and pytest as its tests runner. To install development dependencies:

pipenv install --dev

To run tests:

pipenv shell
pytest

This project uses Codecov to enforce code coverage on all pull requests. To run tests locally and output a code coverage report, run:

pipenv shell
pytest --cov=apistar_test/

apistar-jwt's People

Contributors

amitripshtos avatar audiolion avatar jgirardet avatar mblayman avatar mshenfield avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

apistar-jwt's Issues

Missing PyJWT in setup.py?

Hi, @audiolion. I noticed your project on the Discuss site so I thought I'd check it out. I see that the code calls import jwt, but I don't see PyJWT as a dependency in setup.py. Am I missing something?

Thanks for you efforts so far. I look forward to a time where API Star has a robust 3rd party ecosystem.

datetime in doc

it's datetime.datetime.utcnow() and not datetime.utcnow()

Return None instead of raising AuthenticationFailed

Based on the API Star Authorization documentation

An authentication class must implement the authenticate method, and should return a subclass of Auth, or None if the request was not authenticated.

This allows having multiple authentication mechanisms, and to globally set JWTAuthentication in the authentication setting w/out it requiring authorization for every endpoint. Right now, setting

settings = {
    'AUTHENTICATION': [JWTAuthentication()],
}

will 401 if a JWT hasn't been set, which doesn't work well for public endpoints.

Version Info:

Python: 3.6
API Star JWT: 0.2.1
API Star: 0.3.9

Thanks for creating this btw - it's been extremely handy for a side project.

Life after APIStar 0.5

Given the refined direction that apistar has taken with 0.6, will this repo be likely to stick around?

I've a few apistar containers running 0.5.42 that are not likely to receive any major updates other than introduction of JWT for authentication. This package seems to fit the bill nicely, and rather than write something same-same-but-different or clone the repo, it would be good to know the future of this repo.

I noticed travis doesn't have an end point, so thought I'd ask the question as to if that was the direction of this package.

Working Example?

Should be nice to have a working Example, something that people can just download and run.

The framework is new, I am using it for some time and yet I dont understand how to use Apistar-JWT,
should I use as Component?, or not?, or both at the same time can be used?, Pros Vs Cons of using it as Component?,
JWT supports passing Token on URL or POST args, does apistar-jwt supports that?,
I read the tests, but actually implementing it on the code just from reading the tests and readme seems complicated.

At least 1 minimal working example should be very useful and bring more users to the project.
Just a /example/app.py
Ive created the same for my Apistar components

Keep it up!, is a great project!. ๐Ÿ˜ธ

Token Storage

Where are the tokens stored? What if I have two or three instances of my app running, seems there is no way to share the tokens among the multiple instances.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.