Skip to content

Commit bdc87ec

Browse files
committed
including a command line tool for encoding/decoding jwt
1 parent 74531b9 commit bdc87ec

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

bin/jwt

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

jwt/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ def base64url_decode(input):
2929
def base64url_encode(input):
3030
return base64.urlsafe_b64encode(input).replace('=', '')
3131

32+
def header(jwt):
33+
header_segment = jwt.split('.', 1)[0]
34+
try:
35+
return json.loads(base64url_decode(header_segment))
36+
except (ValueError, TypeError):
37+
raise DecodeError("Invalid header encoding")
38+
3239
def encode(payload, key, algorithm='HS256'):
3340
segments = []
3441
header = {"typ": "JWT", "alg": algorithm}

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ def read(fname):
66

77
setup(
88
name = "PyJWT",
9-
version = "0.1.3",
9+
version = "0.1.4",
1010
author = "Jeff Lindsay",
1111
author_email = "jeff.lindsay@twilio.com",
1212
description = ("JSON Web Token implemtnation in Python"),
1313
license = "MIT",
1414
keywords = "jwt json web token security signing",
1515
url = "http://github.com/progrium/pyjwt",
1616
packages=['jwt', 'tests'],
17+
scripts=['bin/jwt'],
1718
long_description=read('README.md'),
1819
classifiers=[
1920
"Development Status :: 3 - Alpha",

0 commit comments

Comments
 (0)