Using nonce now, preventing OAuth replay attacks
authorxray7224 <xray7224@googlemail.com>
Sun, 14 Jul 2013 15:24:04 +0000 (16:24 +0100)
committerxray7224 <xray7224@googlemail.com>
Sun, 14 Jul 2013 15:24:04 +0000 (16:24 +0100)
mediagoblin/db/models.py
mediagoblin/federation/oauth.py
mediagoblin/federation/views.py

index b6ae533eba8babdc5c5c193c8f22a34ba86fead8..74dea44e600d85d9a817cd0d7e9a67761a521c80 100644 (file)
@@ -161,6 +161,16 @@ class AccessToken(Base):
     updated = Column(DateTime, nullable=False, default=datetime.datetime.now)
  
 
+class NonceTimestamp(Base):
+    """
+        A place the timestamp and nonce can be stored - this is for OAuth1
+    """
+    __tablename__ = "core__nonce_timestamps"
+
+    nonce = Column(Unicode, nullable=False, primary_key=True)
+    timestamp = Column(DateTime, nullable=False, primary_key=True)
+
+
 class MediaEntry(Base, MediaEntryMixin):
     """
     TODO: Consider fetching the media_files using join
@@ -636,8 +646,8 @@ with_polymorphic(
     [ProcessingNotification, CommentNotification])
 
 MODELS = [
-    User, Client, RequestToken, AccessToken, MediaEntry, Tag, MediaTag, 
-    MediaComment, Collection, CollectionItem, MediaFile, FileKeynames, 
+    User, Client, RequestToken, AccessToken, NonceTimestamp, MediaEntry, Tag, 
+    MediaTag, MediaComment, Collection, CollectionItem, MediaFile, FileKeynames, 
     MediaAttachmentFile, ProcessingMetaData, Notification, CommentNotification,
     ProcessingNotification, CommentSubscription]
 
index 846b079468e160a3a77c5f935489d28d89f26d56..ea0fea2cb84695ed7725aa5b1752a06702bce86d 100644 (file)
@@ -18,7 +18,7 @@ from oauthlib.common import Request
 from oauthlib.oauth1 import (AuthorizationEndpoint, RequestValidator, 
                              RequestTokenEndpoint, AccessTokenEndpoint)
 
-from mediagoblin.db.models import Client, RequestToken, AccessToken
+from mediagoblin.db.models import NonceTimestamp, Client, RequestToken, AccessToken
 
 
 
@@ -65,7 +65,12 @@ class GMGRequestValidator(RequestValidator):
     def validate_timestamp_and_nonce(self, client_key, timestamp, 
                                      nonce, request, request_token=None, 
                                      access_token=None):
-        return True # TODO!!! - SECURITY RISK IF NOT DONE
+        nc = NonceTimestamp.query.filter_by(timestamp=timestamp, nonce=nonce)
+        nc = nc.first()
+        if nc is None:
+            return True
+        
+        return False
 
     def validate_client_key(self, client_key, request):
         """ Verifies client exists with id of client_key """
index c538f4cb721c50d87e6ed34a9ece6421a7169ad3..aae9d55a62f1e2deca1e0d7a2f5d33aa291dbe4b 100644 (file)
@@ -32,7 +32,7 @@ from mediagoblin.federation.forms import AuthorizeForm
 from mediagoblin.federation.exceptions import ValidationException
 from mediagoblin.federation.oauth import GMGRequestValidator, GMGRequest
 from mediagoblin.federation.tools.request import decode_authorization_header
-from mediagoblin.db.models import Client, RequestToken, AccessToken
+from mediagoblin.db.models import NonceTimestamp, Client, RequestToken, AccessToken
 
 # possible client types
 client_types = ["web", "native"] # currently what pump supports
@@ -215,6 +215,14 @@ def request_token(request):
     rv = RequestTokenEndpoint(request_validator)
     tokens = rv.create_request_token(request, authorization)
 
+    # store the nonce & timestamp before we return back
+    nonce = authorization[u"oauth_nonce"]
+    timestamp = authorization[u"oauth_timestamp"]
+    timestamp = datetime.datetime.fromtimestamp(int(timestamp))
+
+    nc = NonceTimestamp(nonce=nonce, timestamp=timestamp)
+    nc.save()
+
     return form_response(tokens)
 
 class WTFormData(dict):