-
Notifications
You must be signed in to change notification settings - Fork 0
/
dauth.py
157 lines (116 loc) · 3.5 KB
/
dauth.py
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import StringIO
import uuid, json
import time
from flask import Flask, request, json_available
from flask.ext.restful import Resource, Api
import base64
from flask.wrappers import Response
import rsa
app = Flask(__name__)
USER_DB = {
"weigl": 'abc'
}
import os.path
def read_keys():
def readcontents(filename):
with open(filename) as fp:
c = fp.read()
return c
priv = rsa.PrivateKey.load_pkcs1(readcontents("key.private"))
pub = rsa.PublicKey.load_pkcs1(readcontents("key.public"))
return pub, priv
pub, priv = read_keys()
def rewrite_scopes(scopes):
return scopes
def check_user(username, password, scope):
try:
return USER_DB[username] == password
except KeyError:
return False
def _map_as_unique_str(map):
io = StringIO.StringIO()
io.write("^")
for k,v in map.iteritems():
io.write(k)
io.write("#")
io.write(v)
io.write("##")
io.write("$")
return io.getvalue()
def sign_dictionary(map):
host = request.host
content = _map_as_unique_str(map)
signature = rsa.sign(content, priv, 'SHA-512')
msg = {
'grant':map,
'from': host,
'signature': base64.b64encode(signature)
}
print msg
return msg
def check_authorization(data):
map = data['grant']
signatureref = base64.b64decode(data['signature'])
content = _map_as_unique_str(map)
return rsa.verify(content, signatureref, pub)
class Grant(Resource):
def get(self):
print request.method, request.path, "HTTP/1.1"
print request.headers
username = request.values['username']
password = request.values['password']
duration = int(request.values.get('duration',600))
scope = request.values.get('scope', [])
ipaddr = request.values.get('ipaddr', request.remote_addr)
scope = rewrite_scopes(scope)
if check_user(username, password, scope):
gid = str(uuid.uuid4())
endtime = int(time.time()) + duration
return sign_dictionary(
{
'username': username,
'ipaddr' : ipaddr,
'scope' : scope,
'grantid' : gid,
'validuntil': endtime
}
)
else:
return Response("Authorization not granted", 506)
class Auth(Resource):
def get(self):
print request.headers
try:
auth_txt = request.headers['Authorization']
except:
auth_txt = request.cookies['Authorization']
try:
auth_data = json.loads(auth_txt)
except:
return {'message':"error, no json"}
if check_authorization(auth_data):
return Response("ok", status=200)
else:
return Response("error", status=500)
class ScopeSystem(object):
def __init__(self):
self.scopes = {}
def clean(self):
curtime = time.time()
self.scopes = dict(filter(lambda a: a[1] > curtime, self.scopes.iteritems()))
SCOPES = ScopeSystem()
class Scopes(Resource):
def put(self):
SCOPES.clean()
data = request.json
curtime = time.time()
for s in data:
SCOPES.scopes[s] = curtime + 60 * 60 * 24 # 1 d TTL
return SCOPES.scopes
def get(self):
return SCOPES.scopes
api = Api(app)
api.add_resource(Grant, "/grant")
api.add_resource(Auth, "/auth")
if __name__ == '__main__':
app.run(debug=True)