Partial fix #1048 - Don't require as long nonce
[mediagoblin.git] / mediagoblin / oauth / oauth.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 import datetime
17
18 from oauthlib.common import Request
19 from oauthlib.oauth1 import RequestValidator
20
21 from mediagoblin.db.models import NonceTimestamp, Client, RequestToken, AccessToken
22
23 class GMGRequestValidator(RequestValidator):
24
25 enforce_ssl = False
26
27 def __init__(self, data=None, *args, **kwargs):
28 self.POST = data
29 super(GMGRequestValidator, self).__init__(*args, **kwargs)
30
31 @property
32 def nonce_length(self):
33 return 5, 30
34
35 def save_request_token(self, token, request):
36 """ Saves request token in db """
37 client_id = self.POST[u"oauth_consumer_key"]
38
39 request_token = RequestToken(
40 token=token["oauth_token"],
41 secret=token["oauth_token_secret"],
42 )
43 request_token.client = client_id
44 if u"oauth_callback" in self.POST:
45 request_token.callback = self.POST[u"oauth_callback"]
46 request_token.save()
47
48 def save_verifier(self, token, verifier, request):
49 """ Saves the oauth request verifier """
50 request_token = RequestToken.query.filter_by(token=token).first()
51 request_token.verifier = verifier["oauth_verifier"]
52 request_token.save()
53
54 def save_access_token(self, token, request):
55 """ Saves access token in db """
56 access_token = AccessToken(
57 token=token["oauth_token"],
58 secret=token["oauth_token_secret"],
59 )
60 access_token.request_token = request.oauth_token
61 request_token = RequestToken.query.filter_by(token=request.oauth_token).first()
62 access_token.user = request_token.user
63 access_token.save()
64
65 def get_realms(*args, **kwargs):
66 """ Currently a stub - called when making AccessTokens """
67 return list()
68
69 def validate_timestamp_and_nonce(self, client_key, timestamp,
70 nonce, request, request_token=None,
71 access_token=None):
72 # RFC5849 (OAuth 1.0) section 3.3 says the timestamp is going
73 # to be seconds after the epoch, we need to convert for postgres
74 try:
75 timestamp = datetime.datetime.fromtimestamp(float(timestamp))
76 except ValueError:
77 # Well, the client must have passed up something ridiculous
78 return False
79
80 nc = NonceTimestamp.query.filter_by(timestamp=timestamp, nonce=nonce)
81 nc = nc.first()
82 if nc is None:
83 return True
84
85 return False
86
87 def validate_client_key(self, client_key, request):
88 """ Verifies client exists with id of client_key """
89 client = Client.query.filter_by(id=client_key).first()
90 if client is None:
91 return False
92
93 return True
94
95 def validate_access_token(self, client_key, token, request):
96 """ Verifies token exists for client with id of client_key """
97 client = Client.query.filter_by(id=client_key).first()
98 token = AccessToken.query.filter_by(token=token)
99 token = token.first()
100
101 if token is None:
102 return False
103
104 request_token = RequestToken.query.filter_by(token=token.request_token)
105 request_token = request_token.first()
106
107 if client.id != request_token.client:
108 return False
109
110 return True
111
112 def validate_realms(self, *args, **kwargs):
113 """ Would validate reals however not using these yet. """
114 return True # implement when realms are implemented
115
116
117 def get_client_secret(self, client_key, request):
118 """ Retrives a client secret with from a client with an id of client_key """
119 client = Client.query.filter_by(id=client_key).first()
120 return client.secret
121
122 def get_access_token_secret(self, client_key, token, request):
123 access_token = AccessToken.query.filter_by(token=token).first()
124 return access_token.secret
125
126 class GMGRequest(Request):
127 """
128 Fills in data to produce a oauth.common.Request object from a
129 werkzeug Request object
130 """
131
132 def __init__(self, request, *args, **kwargs):
133 """
134 :param request: werkzeug request object
135
136 any extra params are passed to oauthlib.common.Request object
137 """
138 kwargs["uri"] = kwargs.get("uri", request.url)
139 kwargs["http_method"] = kwargs.get("http_method", request.method)
140 kwargs["body"] = kwargs.get("body", request.data)
141 kwargs["headers"] = kwargs.get("headers", dict(request.headers))
142
143 super(GMGRequest, self).__init__(*args, **kwargs)