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