Skip to content

Commit d634f52

Browse files
committed
Merged master branch in to remove Python 3.2 support and add the new
test vectors from jpadilla#160
2 parents 3c479e2 + 8f00324 commit d634f52

21 files changed

+497
-246
lines changed

.coveragerc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ omit =
44
.tox/*
55
setup.py
66
*.egg/*
7+
*/__main__.py

.travis.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
language: python
22
sudo: false
33
env:
4-
- TOXENV=pep8
5-
- TOXENV=py26
6-
- TOXENV=py27
7-
- TOXENV=py32
8-
- TOXENV=py33
9-
- TOXENV=py34
4+
- TOXENV=flake8
5+
- TOXENV=py26-crypto
6+
- TOXENV=py27-crypto
7+
- TOXENV=py33-crypto
8+
- TOXENV=py34-crypto
109
- TOXENV=py34-nocrypto
1110
- TOXENV=py27-nocrypto
12-
- TOXENV=py34-contrib-crypto
13-
- TOXENV=py27-contrib-crypto
11+
- TOXENV=py34-contrib_crypto
12+
- TOXENV=py27-contrib_crypto
1413
install:
15-
- pip install tox coveralls
14+
- pip install -U pip
15+
- pip install -U tox coveralls
1616
script:
1717
- tox
1818
after_success:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
66

77
[Unreleased][unreleased]
88
-------------------------------------------------------------------------
9+
### Added
10+
- Added a new `jwt.get_unverified_header()` to parse and return the header portion of a token prior to signature verification.
11+
12+
### Removed
13+
- Python 3.2 is no longer a supported platform. This version of Python is
14+
rarely used. Users affected by this should upgrade to 3.3+.
915

1016
[v1.2.0][1.2.0]
1117
-------------------------------------------------------------------------

appveyor.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
environment:
2+
matrix:
3+
- PYTHON: "C:\\Python27-x64"
4+
TOX_ENV: "py27-crypto"
5+
6+
- PYTHON: "C:\\Python34-x64"
7+
TOX_ENV: "py34-crypto"
8+
9+
init:
10+
- SET PATH=%PYTHON%;%PATH%
11+
- python -c "import sys;sys.stdout.write(sys.version)"
12+
- ECHO .
13+
- python -m pip list
14+
15+
# pip & virtualenv are pre-installed
16+
install:
17+
- python -m pip install -U setuptools
18+
- python -m pip install -U pip
19+
- python -m pip install -U wheel
20+
- python -m pip install -U tox
21+
22+
build: false # Not a C# project, build stuff at the test step instead.
23+
24+
test_script:
25+
- python -m tox -e %TOX_ENV%
26+
27+
after_test:
28+
- python setup.py bdist_wheel
29+
- ps: "ls dist"
30+
31+
artifacts:
32+
- path: dist\*
33+
34+
#on_success:
35+
# - TODO: upload the content of dist/*.whl to a public wheelhouse

jwt/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818

1919
from .api_jwt import (
20-
encode, decode, register_algorithm, unregister_algorithm, PyJWT
20+
encode, decode, register_algorithm, unregister_algorithm,
21+
get_unverified_header, PyJWT
2122
)
2223
from .api_jws import PyJWS
2324
from .exceptions import (
Lines changed: 135 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,135 @@
1-
#!/usr/bin/env python
2-
3-
from __future__ import print_function
4-
5-
import optparse
6-
import sys
7-
import json
8-
import time
9-
import jwt
10-
11-
__prog__ = 'jwt'
12-
__version__ = '1.0.0'
13-
14-
15-
def fix_optionparser_whitespace(input):
16-
"""
17-
Hacks around whitespace hypersensitivity in OptionParser
18-
"""
19-
newline = ' ' * 80
20-
doublespace = '\033[8m.\033[0m' * 2
21-
return input.replace(' ', doublespace).replace('\n', newline)
22-
23-
24-
def main():
25-
"""Encodes or decodes JSON Web Tokens based on input
26-
27-
Decoding examples:
28-
29-
%prog --key=secret json.web.token
30-
%prog --no-verify json.web.token
31-
32-
Encoding requires the key option and takes space separated key/value pairs
33-
separated by equals (=) as input. Examples:
34-
35-
%prog --key=secret iss=me exp=1302049071
36-
%prog --key=secret foo=bar exp=+10
37-
38-
The exp key is special and can take an offset to current Unix time.
39-
"""
40-
p = optparse.OptionParser(
41-
description=fix_optionparser_whitespace(main.__doc__),
42-
prog=__prog__,
43-
version='%s %s' % (__prog__, __version__),
44-
usage='%prog [options] input'
45-
)
46-
47-
p.add_option(
48-
'-n', '--no-verify',
49-
action='store_false',
50-
dest='verify',
51-
default=True,
52-
help='ignore signature verification on decode'
53-
)
54-
55-
p.add_option(
56-
'--key',
57-
dest='key',
58-
metavar='KEY',
59-
default=None,
60-
help='set the secret key to sign with'
61-
)
62-
63-
p.add_option(
64-
'--alg',
65-
dest='algorithm',
66-
metavar='ALG',
67-
default='HS256',
68-
help='set crypto algorithm to sign with. default=HS256'
69-
)
70-
71-
options, arguments = p.parse_args()
72-
73-
if len(arguments) > 0 or not sys.stdin.isatty():
74-
if len(arguments) == 1 and ( options.verify is False or options.key is not None ):
75-
# Try to decode
76-
try:
77-
if not sys.stdin.isatty():
78-
token = sys.stdin.read()
79-
else:
80-
token = arguments[0]
81-
82-
token = token.encode('utf-8')
83-
data = jwt.decode(token, key=options.key, verify=options.verify)
84-
85-
print(json.dumps(data))
86-
sys.exit(0)
87-
except jwt.DecodeError as e:
88-
print(e)
89-
sys.exit(1)
90-
91-
# Try to encode
92-
if options.key is None:
93-
print('Key is required when encoding. See --help for usage.')
94-
sys.exit(1)
95-
96-
# Build payload object to encode
97-
payload = {}
98-
99-
for arg in arguments:
100-
try:
101-
k, v = arg.split('=', 1)
102-
103-
# exp +offset special case?
104-
if k == 'exp' and v[0] == '+' and len(v) > 1:
105-
v = str(int(time.time()+int(v[1:])))
106-
107-
# Cast to integer?
108-
if v.isdigit():
109-
v = int(v)
110-
else:
111-
# Cast to float?
112-
try:
113-
v = float(v)
114-
except ValueError:
115-
pass
116-
117-
# Cast to true, false, or null?
118-
constants = {'true': True, 'false': False, 'null': None}
119-
120-
if v in constants:
121-
v = constants[v]
122-
123-
payload[k] = v
124-
except ValueError:
125-
print('Invalid encoding input at {}'.format(arg))
126-
sys.exit(1)
127-
128-
try:
129-
token = jwt.encode(
130-
payload,
131-
key=options.key,
132-
algorithm=options.algorithm
133-
)
134-
135-
print(token)
136-
sys.exit(0)
137-
except Exception as e:
138-
print(e)
139-
sys.exit(1)
140-
else:
141-
p.print_help()
142-
143-
if __name__ == '__main__':
144-
main()
1+
#!/usr/bin/env python
2+
3+
from __future__ import absolute_import, print_function
4+
5+
import json
6+
import optparse
7+
import sys
8+
import time
9+
10+
from . import DecodeError, __package__, __version__, decode, encode
11+
12+
13+
def main():
14+
15+
usage = '''Encodes or decodes JSON Web Tokens based on input.
16+
17+
%prog [options] input
18+
19+
Decoding examples:
20+
21+
%prog --key=secret json.web.token
22+
%prog --no-verify json.web.token
23+
24+
Encoding requires the key option and takes space separated key/value pairs
25+
separated by equals (=) as input. Examples:
26+
27+
%prog --key=secret iss=me exp=1302049071
28+
%prog --key=secret foo=bar exp=+10
29+
30+
The exp key is special and can take an offset to current Unix time.\
31+
'''
32+
p = optparse.OptionParser(
33+
usage=usage,
34+
prog=__package__,
35+
version='%s %s' % (__package__, __version__),
36+
)
37+
38+
p.add_option(
39+
'-n', '--no-verify',
40+
action='store_false',
41+
dest='verify',
42+
default=True,
43+
help='ignore signature verification on decode'
44+
)
45+
46+
p.add_option(
47+
'--key',
48+
dest='key',
49+
metavar='KEY',
50+
default=None,
51+
help='set the secret key to sign with'
52+
)
53+
54+
p.add_option(
55+
'--alg',
56+
dest='algorithm',
57+
metavar='ALG',
58+
default='HS256',
59+
help='set crypto algorithm to sign with. default=HS256'
60+
)
61+
62+
options, arguments = p.parse_args()
63+
64+
if len(arguments) > 0 or not sys.stdin.isatty():
65+
if len(arguments) == 1 and (not options.verify or options.key):
66+
# Try to decode
67+
try:
68+
if not sys.stdin.isatty():
69+
token = sys.stdin.read()
70+
else:
71+
token = arguments[0]
72+
73+
token = token.encode('utf-8')
74+
data = decode(token, key=options.key, verify=options.verify)
75+
76+
print(json.dumps(data))
77+
sys.exit(0)
78+
except DecodeError as e:
79+
print(e)
80+
sys.exit(1)
81+
82+
# Try to encode
83+
if options.key is None:
84+
print('Key is required when encoding. See --help for usage.')
85+
sys.exit(1)
86+
87+
# Build payload object to encode
88+
payload = {}
89+
90+
for arg in arguments:
91+
try:
92+
k, v = arg.split('=', 1)
93+
94+
# exp +offset special case?
95+
if k == 'exp' and v[0] == '+' and len(v) > 1:
96+
v = str(int(time.time()+int(v[1:])))
97+
98+
# Cast to integer?
99+
if v.isdigit():
100+
v = int(v)
101+
else:
102+
# Cast to float?
103+
try:
104+
v = float(v)
105+
except ValueError:
106+
pass
107+
108+
# Cast to true, false, or null?
109+
constants = {'true': True, 'false': False, 'null': None}
110+
111+
if v in constants:
112+
v = constants[v]
113+
114+
payload[k] = v
115+
except ValueError:
116+
print('Invalid encoding input at {}'.format(arg))
117+
sys.exit(1)
118+
119+
try:
120+
token = encode(
121+
payload,
122+
key=options.key,
123+
algorithm=options.algorithm
124+
)
125+
126+
print(token)
127+
sys.exit(0)
128+
except Exception as e:
129+
print(e)
130+
sys.exit(1)
131+
else:
132+
p.print_help()
133+
134+
if __name__ == '__main__':
135+
main()

jwt/api_jws.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ def decode(self, jws, key='', verify=True, algorithms=None, options=None,
119119

120120
return payload
121121

122+
def get_unverified_header(self, jwt):
123+
"""Returns back the JWT header parameters as a dict()
124+
125+
Note: The signature is not verified so the header parameters
126+
should not be fully trusted until signature verification is complete
127+
"""
128+
return self._load(jwt)[2]
129+
122130
def _load(self, jwt):
123131
if isinstance(jwt, text_type):
124132
jwt = jwt.encode('utf-8')
@@ -178,3 +186,4 @@ def _verify_signature(self, payload, signing_input, header, signature,
178186
decode = _jws_global_obj.decode
179187
register_algorithm = _jws_global_obj.register_algorithm
180188
unregister_algorithm = _jws_global_obj.unregister_algorithm
189+
get_unverified_header = _jws_global_obj.get_unverified_header

jwt/api_jwt.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,4 @@ def _validate_iss(self, payload, issuer):
169169
decode = _jwt_global_obj.decode
170170
register_algorithm = _jwt_global_obj.register_algorithm
171171
unregister_algorithm = _jwt_global_obj.unregister_algorithm
172+
get_unverified_header = _jwt_global_obj.get_unverified_header

0 commit comments

Comments
 (0)