Commits

Martin von Löwis committed 56cfcf7

Add error numbers.

  • Participants
  • Parent commits 54808a0

Comments (0)

Files changed (1)

File openid2rp/__init__.py

         return char
     bytes_from_ints = bytes
 
+class NotAuthenticated(Exception):
+    CONNECTION_REFUSED = 1
+    DIRECT_VERIFICATION_FAILED = 2
+    CANCELLED = 3
+    UNSUPPORTED_VERSION = 4
+    UNEXPECTED_MODE = 5
+    CLAIMED_ID_MISSING = 6
+    DISCOVERY_FAILED = 7
+    INCONSISTENT_IDS = 8
+    REPLAY_ATTACK = 9
+    MISSING_NONCE = 10
+    msgs = {
+        CONNECTION_REFUSED : 'OP refuses connection with status %d',
+        DIRECT_VERIFICATION_FAILED : 'OP doesn\'t assert that the signature of the verification request is valid',
+        CANCELLED : 'OP did not authenticate user (cancelled)',
+        UNSUPPORTED_VERSION : 'Unsupported OpenID version',
+        UNEXPECTED_MODE : 'Unexpected mode %s',
+        CLAIMED_ID_MISSING : 'Cannot determine claimed ID',
+        DISCOVERY_FAILED : 'Claimed ID %s cannot be rediscovered',
+        INCONSISTENT_IDS : 'Discovered and asserted endpoints differ',
+        REPLAY_ATTACK : 'Replay attack detected',
+        MISSING_NONCE : 'Nonce missing in OpenID 2 response',
+        }
+
+    def __init__(self, errno, *args):
+        msg = self.msgs[errno]
+        if args:
+            msg %= args
+        self.errno = errno
+        Exception.__init__(self, msg, errno, *args)
+
+    def __str__(self):
+        return self.args[0]
+
 def normalize_uri(uri):
     """Normalize an uri according to OpenID section 7.2. Return a pair
     type,value, where type can be either 'xri' or 'uri'."""
     request.extend((k, v) for k, (v,) in response.items() if 'openid.mode' != k)
     res = urllib.urlopen(op_endpoint, urllib.urlencode(request))
     if 200 != res.getcode():
-        raise NotAuthenticated('OP refuses connection with status %d' % res.getcode())
+        raise NotAuthenticated(NotAuthenticated.CONNECTION_REFUSED, res.getcode())
     response = parse_response(res.read())
     if 'true' != response['is_valid']:
-        raise NotAuthenticated('OP doesn\'t assert that the signature of the verification request is valid')
-
-class NotAuthenticated(Exception):
-    pass
+        raise NotAuthenticated(NotAuthenticated.DIRECT_VERIFICATION_FAILED)
 
 def _prepare_response(response):
     if isinstance(response, str):
     if session['assoc_handle'] != response['openid.assoc_handle'][0]:
         raise ValueError('incorrect session')
     if response['openid.mode'][0] == 'cancel':
-        raise NotAuthenticated('provider did not authenticate user (cancelled)')
+        raise NotAuthenticated(NotAuthenticated.CANCELLED)
     if response['openid.mode'][0] != 'id_res':
         raise ValueError('invalid openid.mode')
     if  'openid.identity' not in response:
     if 'openid.ns' in response:
         ns = response['openid.ns'][0]
         if ns != 'http://specs.openid.net/auth/2.0':
-            raise NotAuthenticated('Unsupported OpenID version')
+            raise NotAuthenticated(NotAuthenticate.UNSUPPORTED_VERSION)
     else:
         ns = None
     mode = response['openid.mode'][0]
     if mode == 'cancel':
-        raise NotAuthenticated('Login cancelled')
+        raise NotAuthenticated(NotAuthenticated.CANCELLED)
     if mode != 'id_res':
-        raise NotAuthenticated('Unexpected mode ' + mode)
+        raise NotAuthenticated(NotAuthenticated.UNEXPECTED_MODE, mode)
     # Establish claimed ID
     if 'openid.claimed_id' in response:
         claimed_id = response['openid.claimed_id'][0]
     elif 'openid1' in response:
         claimed_id = response['openid1'][0]
     else:
-        raise NotAuthenticated('Cannot determine claimed ID')
+        raise NotAuthenticated(NotAuthenticated.CLAIMED_ID_MISSING)
     discovered = discovery_cache(claimed_id)
     if not discovered:
         discovered = discover(claimed_id)
         if not discovered:
-            raise NotAuthenticated('Claimed ID %s cannot be rediscovered' % claimed_id)
+            raise NotAuthenticated(NotAuthenticated.DISCOVERY_FAILED, claimed_id)
     services, op_endpoint, op_local = discovered
     # For a provider-allocated claimed_id, there will be no op_local ID,
     # and there is no point checking it.
     # For OpenID 1.1, op_endpoint may not be included in the response
     if ('openid.op_endpoint' in response and
         op_endpoint != response['openid.op_endpoint'][0]):
-        raise NotAuthenticated('Discovered and asserted endpoints differ')
+        raise NotAuthenticated(NotAuthenticated.INCONSISTENT_IDS)
     # XXX verify protocol version, verify claimed_id wrt. original request,
     # verify return_to URL
     
         timestamp = parse_nonce(nonce)
         if (datetime.datetime.utcnow() - timestamp).total_seconds() > 10:
             # allow for at most 10s transmission time and time shift
-            raise NotAuthenticated('Replay attack detected')
+            raise NotAuthenticated(NotAuthenticated.REPLAY_ATTACK)
         if nonce_seen(nonce):
-            raise NotAuthenticated('Replay attack deteced')
+            raise NotAuthenticated(NotAuthenticated.REPLAY_ATTACK)
     elif ns:
-        raise NotAuthenticated('Nonce missing in OpenID 2 response')
+        raise NotAuthenticated(NotAuthenticated.MISSING_NONCE)
     return signed, claimed_id
 
 def parse_nonce(nonce):