Skip to content

Commit 42769df

Browse files
hzlmnasvetlov
authored andcommitted
JWTIdentityPolicy polishing (#161)
* Polishing JWT policy * Simplify tests * Minor cleaning
1 parent ff2171d commit 42769df

File tree

2 files changed

+64
-27
lines changed

2 files changed

+64
-27
lines changed

aiohttp_security/jwt_identity.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,40 @@
33
"""
44

55
from .abc import AbstractIdentityPolicy
6+
67
try:
78
import jwt
89
except ImportError: # pragma: no cover
910
jwt = None
1011

1112

1213
AUTH_HEADER_NAME = 'Authorization'
14+
AUTH_SCHEME = 'Bearer '
1315

1416

1517
class JWTIdentityPolicy(AbstractIdentityPolicy):
16-
def __init__(self, secret, algorithm=None):
18+
def __init__(self, secret, algorithm='HS256'):
1719
if jwt is None:
18-
raise RuntimeError("Please install pyjwt")
20+
raise RuntimeError('Please install `PyJWT`')
1921
self.secret = secret
20-
self.algorithm = 'HS256' if algorithm is None else algorithm
22+
self.algorithm = algorithm
2123

2224
async def identify(self, request):
2325
header_identity = request.headers.get(AUTH_HEADER_NAME)
24-
identity = jwt.decode(header_identity,
26+
27+
if header_identity is None:
28+
return
29+
30+
if not header_identity.startswith(AUTH_SCHEME):
31+
raise ValueError('Invalid authorization scheme. ' +
32+
'Should be `Bearer <token>`')
33+
34+
token = header_identity.split(' ')[1].strip()
35+
36+
identity = jwt.decode(token,
2537
self.secret,
2638
algorithm=self.algorithm)
27-
28-
return identity['identity']
39+
return identity
2940

3041
async def remember(self, *args, **kwargs): # pragma: no cover
3142
pass

tests/test_jwt_identity.py

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
1+
import jwt
12
import pytest
23
from aiohttp import web
3-
from aiohttp_security import AbstractAuthorizationPolicy
4+
45
from aiohttp_security import setup as _setup
5-
from aiohttp_security.jwt_identity import JWTIdentityPolicy
6+
from aiohttp_security import AbstractAuthorizationPolicy
67
from aiohttp_security.api import IDENTITY_KEY
7-
import jwt
8+
from aiohttp_security.jwt_identity import JWTIdentityPolicy
9+
10+
11+
@pytest.fixture
12+
def make_token():
13+
def factory(payload, secret):
14+
return jwt.encode(
15+
payload,
16+
secret,
17+
algorithm='HS256',
18+
)
19+
20+
return factory
821

922

1023
class Autz(AbstractAuthorizationPolicy):
@@ -22,35 +35,48 @@ async def test_no_pyjwt_installed(mocker):
2235
JWTIdentityPolicy('secret')
2336

2437

25-
async def test_identify(loop, test_client):
38+
async def test_identify(loop, make_token, test_client):
2639
kwt_secret_key = 'Key'
2740

28-
async def create(request):
29-
response = web.Response()
30-
data = await request.post()
41+
token = make_token({'login': 'Andrew'}, kwt_secret_key)
3142

32-
encoded_identity = jwt.encode({'identity': data['login']},
33-
kwt_secret_key,
34-
algorithm='HS256')
43+
async def check(request):
44+
policy = request.app[IDENTITY_KEY]
45+
identity = await policy.identify(request)
46+
assert 'Andrew' == identity['login']
47+
return web.Response()
3548

36-
response.text = encoded_identity.decode('utf-8')
37-
return response
49+
app = web.Application(loop=loop)
50+
_setup(app, JWTIdentityPolicy(kwt_secret_key), Autz())
51+
app.router.add_route('GET', '/', check)
52+
53+
client = await test_client(app)
54+
headers = {'Authorization': 'Bearer {}'.format(token.decode('utf-8'))}
55+
resp = await client.get('/', headers=headers)
56+
assert 200 == resp.status
57+
58+
59+
async def test_identify_broken_scheme(loop, make_token, test_client):
60+
kwt_secret_key = 'Key'
61+
62+
token = make_token({'login': 'Andrew'}, kwt_secret_key)
3863

3964
async def check(request):
4065
policy = request.app[IDENTITY_KEY]
41-
user_id = await policy.identify(request)
42-
assert 'Andrew' == user_id
66+
67+
try:
68+
await policy.identify(request)
69+
except ValueError as exc:
70+
raise web.HTTPBadRequest(reason=exc)
71+
4372
return web.Response()
4473

4574
app = web.Application(loop=loop)
4675
_setup(app, JWTIdentityPolicy(kwt_secret_key), Autz())
4776
app.router.add_route('GET', '/', check)
48-
app.router.add_route('POST', '/', create)
77+
4978
client = await test_client(app)
50-
resp = await client.post('/', data={'login': 'Andrew'})
51-
jwt_token = await resp.content.read()
52-
assert 200 == resp.status
53-
await resp.release()
54-
headers = {'Authorization': str(jwt_token.decode('utf-8'))}
79+
headers = {'Authorization': 'Token {}'.format(token.decode('utf-8'))}
5580
resp = await client.get('/', headers=headers)
56-
assert 200 == resp.status
81+
assert 400 == resp.status
82+
assert 'Invalid authorization scheme' in resp.reason

0 commit comments

Comments
 (0)