Ejemplo n.º 1
0
    def test_sreg(self):
        authreq = self.consumer.beginWithoutDiscovery(
            OpenIDServiceEndpoint.fromOPEndpointURL('http://example.com/endpoint/'))

        sreg_request = sreg.SRegRequest(required=['nickname'])
        authreq.addExtension(sreg_request)

        url = authreq.redirectURL(
            'http://localhost/',
            return_to='http://localhost/')

        self.client.post('/login/')

        response = self.client.open(make_builder(url))

        self.assertEqual(response.status_code, 302)
        parsed = urlparse(response.headers['LOCATION'])

        info = self.consumer.complete(
            dict(parse_qsl(parsed.query)),
            response.headers['LOCATION'])

        self.assertIsInstance(info, SuccessResponse)


        sreg_resp = sreg.SRegResponse.fromSuccessResponse(info)
        self.assertEqual(sreg_resp['nickname'], 'user')
Ejemplo n.º 2
0
def associate(services, url):
    '''Create an association (OpenID section 8) between RP and OP.
    Return response as a dictionary.'''
    req_data = {
        'openid.ns':"http://specs.openid.net/auth/2.0",
        'openid.mode':"associate",
        'openid.assoc_type':"HMAC-SHA1",
        'openid.session_type':"no-encryption",
        }
    if url.startswith('http:'):
        # Use DH exchange
        req_data['openid.session_type'] = "DH-SHA1"
        # Private key: random number between 1 and dh_prime-1
        priv = random.SystemRandom().randrange(1, dh_prime - 1)
        # Public key: 2^priv mod prime
        pubkey = pow(2L, priv, dh_prime)
        dh_public_base64 = base64.b64encode(btwoc(pubkey))
        # No need to send key and generator
        req_data['openid.dh_consumer_public'] = dh_public_base64
    if is_compat_1x(services):
        # 14.2.1: clear session_type in 1.1 compatibility mode
        if req_data['openid.session_type'] == "no-encryption":
            req_data['openid.session_type'] = ''
        del req_data['openid.ns']
    res = urllib.urlopen(url, b(urllib.urlencode(req_data)))
    try:
        if res.getcode() != 200:
            raise ValueError("OpenID provider refuses connection with status %s" % res.getcode())
        data = parse_response(res.read())
    except ValueError:
        endpoint = OpenIDServiceEndpoint.fromOPEndpointURL(url)
        store = MemoryStore()
        consumer = GenericConsumer(store)
        try:
            assoc = consumer._requestAssociation(endpoint, req_data['openid.assoc_type'], req_data['openid.session_type'])
            data = {
                'assoc_handle': assoc.handle,
                'expires_in': assoc.lifetime,
                'mac_key': oidutil.toBase64(assoc.secret),
            }
        except ServerError:
            data = {
                'error': 'Server %s refused its suggested association type: session_type=%s, assoc_type=%s' % (url, req_data['openid.assoc_type'], req_data['openid.session_type']),
            }
    if 'error' in data:
        raise ValueError, "associate failed: "+data['error']
    if url.startswith('http:'):
        enc_mac_key = b(data.get('enc_mac_key'))
        if not enc_mac_key:
            raise ValueError, "Provider protocol error: not using DH-SHA1"
        enc_mac_key = base64.b64decode(enc_mac_key)
        dh_server_public = unbtwoc(base64.b64decode(b(data['dh_server_public'])))
        # shared secret: sha1(2^(server_priv*priv) mod prime) xor enc_mac_key
        shared_secret = btwoc(pow(dh_server_public, priv, dh_prime))
        shared_secret = hashlib.sha1(shared_secret).digest()
        if len(shared_secret) != len(enc_mac_key):
            raise ValueError, "incorrect DH key size"
        # Fake mac_key result
        data['mac_key'] = b(base64.b64encode(string_xor(enc_mac_key, shared_secret)))
    return data
Ejemplo n.º 3
0
def _verifyDiscoveryResultsOpenID2(self, resp_msg, endpoint):
    to_match = OpenIDServiceEndpoint()
    to_match.type_uris = [OPENID_2_0_TYPE]
    to_match.claimed_id = resp_msg.getArg(OPENID2_NS, 'claimed_id')
    to_match.local_id = resp_msg.getArg(OPENID2_NS, 'identity')

    # Raises a KeyError when the op_endpoint is not present
    to_match.server_url = resp_msg.getArg(
        OPENID2_NS, 'op_endpoint', no_default)

    # claimed_id and identifier must both be present or both
    # be absent
    if (to_match.claimed_id is None and
        to_match.local_id is not None):
        raise consumer.ProtocolError(
            'openid.identity is present without openid.claimed_id')

    elif (to_match.claimed_id is not None and
          to_match.local_id is None):
        raise consumer.ProtocolError(
            'openid.claimed_id is present without openid.identity')

    # This is a response without identifiers, so there's really no
    # checking that we can do, so return an endpoint that's for
    # the specified `openid.op_endpoint'
    elif to_match.claimed_id is None:
        return OpenIDServiceEndpoint.fromOPEndpointURL(to_match.server_url)

    # The claimed ID doesn't match, so we have to do discovery
    # again. This covers not using sessions, OP identifier
    # endpoints and responses that didn't match the original
    # request.
    if to_match.server_url.startswith(u'https://www.google.com/a/'):
        import urllib
        claimed_id = u'https://www.google.com/accounts/o8/user-xrds?uri=%s' % urllib.quote_plus(to_match.claimed_id)
    else:
        claimed_id = to_match.claimed_id

    if not endpoint:
        oidutil.log('No pre-discovered information supplied.')
        endpoint = self._discoverAndVerify(claimed_id, [to_match])
    else:
        # The claimed ID matches, so we use the endpoint that we
        # discovered in initiation. This should be the most common
        # case.
        try:
            self._verifyDiscoverySingle(endpoint, to_match)
        except consumer.ProtocolError, e:
            oidutil.log(
                "Error attempting to use stored discovery information: " +
                str(e))
            oidutil.log("Attempting discovery to verify endpoint")
            endpoint = self._discoverAndVerify(
                claimed_id, [to_match])
Ejemplo n.º 4
0
    def test_setup_redirect(self):
        authreq = self.consumer.beginWithoutDiscovery(
            OpenIDServiceEndpoint.fromOPEndpointURL('http://example.com/endpoint/'))

        url = authreq.redirectURL(
            'http://localhost/',
            return_to='http://localhost/')

        response = self.client.open(make_builder(url))

        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            parse_qs(urlparse(response.headers['LOCATION']).query)['next'][0],
            url)
Ejemplo n.º 5
0
    def test_immediate_failure(self):
        authreq = self.consumer.beginWithoutDiscovery(
            OpenIDServiceEndpoint.fromOPEndpointURL('http://example.com/endpoint/'))

        url = authreq.redirectURL(
            'http://localhost/',
            return_to='http://localhost/',
            immediate=True)

        response = self.client.open(make_builder(url))
        self.assertEqual(response.status_code, 302)
        parsed = urlparse(response.headers['LOCATION'])

        info = self.consumer.complete(
            dict(parse_qsl(parsed.query)),
            response.headers['LOCATION'])

        self.assertIsInstance(info, SetupNeededResponse)
Ejemplo n.º 6
0
def associate(services, url):
    '''Create an association (OpenID section 8) between RP and OP.
    Return response as a dictionary.'''
    req_data = {
        'openid.ns': "http://specs.openid.net/auth/2.0",
        'openid.mode': "associate",
        'openid.assoc_type': "HMAC-SHA1",
        'openid.session_type': "no-encryption",
    }
    if url.startswith('http:'):
        # Use DH exchange
        req_data['openid.session_type'] = "DH-SHA1"
        # Private key: random number between 1 and dh_prime-1
        priv = random.SystemRandom().randrange(1, dh_prime - 1)
        # Public key: 2^priv mod prime
        pubkey = pow(2L, priv, dh_prime)
        dh_public_base64 = base64.b64encode(btwoc(pubkey))
        # No need to send key and generator
        req_data['openid.dh_consumer_public'] = dh_public_base64
    if is_compat_1x(services):
        # 14.2.1: clear session_type in 1.1 compatibility mode
        if req_data['openid.session_type'] == "no-encryption":
            req_data['openid.session_type'] = ''
        del req_data['openid.ns']
    res = urllib.urlopen(url, b(urllib.urlencode(req_data)))
    try:
        if res.getcode() != 200:
            raise ValueError(
                "OpenID provider refuses connection with status %s" %
                res.getcode())
        data = parse_response(res.read())
    except ValueError:
        endpoint = OpenIDServiceEndpoint.fromOPEndpointURL(url)
        store = MemoryStore()
        consumer = GenericConsumer(store)
        try:
            assoc = consumer._requestAssociation(
                endpoint, req_data['openid.assoc_type'],
                req_data['openid.session_type'])
            data = {
                'assoc_handle': assoc.handle,
                'expires_in': assoc.lifetime,
                'mac_key': oidutil.toBase64(assoc.secret),
            }
        except ServerError:
            data = {
                'error':
                'Server %s refused its suggested association type: session_type=%s, assoc_type=%s'
                % (url, req_data['openid.assoc_type'],
                   req_data['openid.session_type']),
            }
    if 'error' in data:
        raise ValueError, "associate failed: " + data['error']
    if url.startswith('http:'):
        enc_mac_key = b(data.get('enc_mac_key'))
        if not enc_mac_key:
            raise ValueError, "Provider protocol error: not using DH-SHA1"
        enc_mac_key = base64.b64decode(enc_mac_key)
        dh_server_public = unbtwoc(
            base64.b64decode(b(data['dh_server_public'])))
        # shared secret: sha1(2^(server_priv*priv) mod prime) xor enc_mac_key
        shared_secret = btwoc(pow(dh_server_public, priv, dh_prime))
        shared_secret = hashlib.sha1(shared_secret).digest()
        if len(shared_secret) != len(enc_mac_key):
            raise ValueError, "incorrect DH key size"
        # Fake mac_key result
        data['mac_key'] = b(
            base64.b64encode(string_xor(enc_mac_key, shared_secret)))
    return data