Exemplo n.º 1
0
    def test_encode_decode_with_ecdsa_sha512(self):
        try:
            import ecdsa

            # PEM-formatted EC key
            with open('tests/testkey_ec', 'r') as ec_priv_file:
                priv_eckey = ecdsa.SigningKey.from_pem(ec_priv_file.read())
                jwt_message = jwt.encode(self.payload, priv_eckey,
                                         algorithm='ES512')

            with open('tests/testkey_ec.pub', 'r') as ec_pub_file:
                pub_eckey = ecdsa.VerifyingKey.from_pem(ec_pub_file.read())
                assert jwt.decode(jwt_message, pub_eckey)

                load_output = jwt.load(jwt_message)
                jwt.verify_signature(key=pub_eckey, *load_output)

            # string-formatted key
            with open('tests/testkey_ec', 'r') as ec_priv_file:
                priv_eckey = ec_priv_file.read()
                jwt_message = jwt.encode(self.payload, priv_eckey,
                                         algorithm='ES512')

            with open('tests/testkey_ec.pub', 'r') as ec_pub_file:
                pub_eckey = ec_pub_file.read()
                assert jwt.decode(jwt_message, pub_eckey)

                load_output = jwt.load(jwt_message)
                jwt.verify_signature(key=pub_eckey, *load_output)
        except ImportError:
            pass
Exemplo n.º 2
0
    def test_encode_decode_with_rsa_sha512(self):
        try:
            from Crypto.PublicKey import RSA

            # RSA-formatted key
            with open('tests/testkey', 'r') as rsa_priv_file:
                priv_rsakey = RSA.importKey(rsa_priv_file.read())
                jwt_message = jwt.encode(self.payload,
                                         priv_rsakey,
                                         algorithm='RS512')

            with open('tests/testkey.pub', 'r') as rsa_pub_file:
                pub_rsakey = RSA.importKey(rsa_pub_file.read())
                assert jwt.decode(jwt_message, pub_rsakey)

                load_output = jwt.load(jwt_message)
                jwt.verify_signature(key=pub_rsakey, *load_output)

            # string-formatted key
            with open('tests/testkey', 'r') as rsa_priv_file:
                priv_rsakey = rsa_priv_file.read()
                jwt_message = jwt.encode(self.payload,
                                         priv_rsakey,
                                         algorithm='RS512')

            with open('tests/testkey.pub', 'r') as rsa_pub_file:
                pub_rsakey = rsa_pub_file.read()
                assert jwt.decode(jwt_message, pub_rsakey)

                load_output = jwt.load(jwt_message)
                jwt.verify_signature(key=pub_rsakey, *load_output)
        except ImportError:
            pass
Exemplo n.º 3
0
    def test_encode_decode_with_rsa_sha256(self):
        # PEM-formatted RSA key
        with open('tests/testkey_rsa', 'r') as rsa_priv_file:
            priv_rsakey = load_pem_private_key(ensure_bytes(rsa_priv_file.read()),
                                               password=None, backend=default_backend())
            jwt_message = jwt.encode(self.payload, priv_rsakey,
                                     algorithm='RS256')

        with open('tests/testkey_rsa.pub', 'r') as rsa_pub_file:
            pub_rsakey = load_ssh_public_key(ensure_bytes(rsa_pub_file.read()),
                                             backend=default_backend())
            assert jwt.decode(jwt_message, pub_rsakey)

            load_output = jwt.load(jwt_message)
            jwt.verify_signature(key=pub_rsakey, *load_output)

        # string-formatted key
        with open('tests/testkey_rsa', 'r') as rsa_priv_file:
            priv_rsakey = rsa_priv_file.read()
            jwt_message = jwt.encode(self.payload, priv_rsakey,
                                     algorithm='RS256')

        with open('tests/testkey_rsa.pub', 'r') as rsa_pub_file:
            pub_rsakey = rsa_pub_file.read()
            assert jwt.decode(jwt_message, pub_rsakey)

            load_output = jwt.load(jwt_message)
            jwt.verify_signature(key=pub_rsakey, *load_output)
Exemplo n.º 4
0
    def test_encode_decode_with_rsa_sha512(self):
        try:
            from Crypto.PublicKey import RSA

            # PEM-formatted RSA key
            with open('tests/testkey_rsa', 'r') as rsa_priv_file:
                priv_rsakey = RSA.importKey(rsa_priv_file.read())
                jwt_message = jwt.encode(self.payload, priv_rsakey,
                                         algorithm='RS512')

            with open('tests/testkey_rsa.pub', 'r') as rsa_pub_file:
                pub_rsakey = RSA.importKey(rsa_pub_file.read())
                assert jwt.decode(jwt_message, pub_rsakey)

                load_output = jwt.load(jwt_message)
                jwt.verify_signature(key=pub_rsakey, *load_output)

            # string-formatted key
            with open('tests/testkey_rsa', 'r') as rsa_priv_file:
                priv_rsakey = rsa_priv_file.read()
                jwt_message = jwt.encode(self.payload, priv_rsakey,
                                         algorithm='RS512')

            with open('tests/testkey_rsa.pub', 'r') as rsa_pub_file:
                pub_rsakey = rsa_pub_file.read()
                assert jwt.decode(jwt_message, pub_rsakey)

                load_output = jwt.load(jwt_message)
                jwt.verify_signature(key=pub_rsakey, *load_output)
        except ImportError:
            pass
Exemplo n.º 5
0
    def test_encode_decode_with_ecdsa_sha512(self):
        # PEM-formatted EC key
        with open('tests/testkey_ec', 'r') as ec_priv_file:
            priv_eckey = load_pem_private_key(ensure_bytes(ec_priv_file.read()),
                                              password=None, backend=default_backend())
            jwt_message = jwt.encode(self.payload, priv_eckey,
                                     algorithm='ES512')

        with open('tests/testkey_ec.pub', 'r') as ec_pub_file:
            pub_eckey = load_pem_public_key(ensure_bytes(ec_pub_file.read()), backend=default_backend())
            assert jwt.decode(jwt_message, pub_eckey)

            load_output = jwt.load(jwt_message)
            jwt.verify_signature(key=pub_eckey, *load_output)

        # string-formatted key
        with open('tests/testkey_ec', 'r') as ec_priv_file:
            priv_eckey = ec_priv_file.read()
            jwt_message = jwt.encode(self.payload, priv_eckey,
                                     algorithm='ES512')

        with open('tests/testkey_ec.pub', 'r') as ec_pub_file:
            pub_eckey = ec_pub_file.read()
            assert jwt.decode(jwt_message, pub_eckey)

            load_output = jwt.load(jwt_message)
            jwt.verify_signature(key=pub_eckey, *load_output)
Exemplo n.º 6
0
def parse_token(token):
    """Parses a JWT OAuth 2.0 Access Token into a joat.Token object.

  Raises an ExpiredSignature exception if the token is expired.
  Returns None in other cases of invalidity."""

    try:
        claims, enc, header, sig = jwt.load(token)
        salt = salt_generator(claims)
        verified_claims = jwt.decode(token, salt)
    except jwt.DecodeError as e:
        # improperly formatted token
        return None
    except jwt.ExpiredSignature as e:
        # token is expired, return none
        return None

    payload = {
        'provider': verified_claims['iss'],
        'client_id': verified_claims['aud'],
        'user_id': verified_claims['sub'],
        'authorized_scope': verified_claims['scp']
    }

    if 'jti' in verified_claims:
        payload['jti'] = verified_claims['jti']

    return payload
Exemplo n.º 7
0
def parse_token(token):
  """Parses a JWT OAuth 2.0 Access Token into a joat.Token object.

  Raises an ExpiredSignature exception if the token is expired.
  Returns None in other cases of invalidity."""

  try:
    claims, enc, header, sig = jwt.load(token)
    salt = salt_generator(claims)
    verified_claims = jwt.decode(token, salt)
  except jwt.DecodeError as e:
    # improperly formatted token
    return None
  except jwt.ExpiredSignature as e:
    # token is expired, return none
    return None

  payload = {
    'provider': verified_claims['iss'],
    'client_id': verified_claims['aud'],
    'user_id': verified_claims['sub'],
    'authorized_scope': verified_claims['scp']
  }

  if 'jti' in verified_claims:
    payload['jti'] = verified_claims['jti']

  return payload
Exemplo n.º 8
0
    def test_custom_headers(self):
        right_secret = 'foo'
        headers = {'foo': 'bar', 'kid': 'test'}
        jwt_message = jwt.encode(self.payload, right_secret, headers=headers)
        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        for key, value in headers.items():
            self.assertEqual(header[key], value)
Exemplo n.º 9
0
    def test_verify_signature_no_secret(self):
        right_secret = 'foo'
        jwt_message = jwt.encode(self.payload, right_secret)
        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        self.assertRaises(
            jwt.DecodeError, lambda: jwt.verify_signature(
                decoded_payload, signing, header, signature))
Exemplo n.º 10
0
    def test_custom_headers(self):
        right_secret = 'foo'
        headers = {'foo': 'bar', 'kid': 'test'}
        jwt_message = jwt.encode(self.payload, right_secret, headers=headers)
        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        for key, value in headers.items():
            self.assertEqual(header[key], value)
Exemplo n.º 11
0
    def test_verify_signature_no_secret(self):
        right_secret = 'foo'
        jwt_message = jwt.encode(self.payload, right_secret)
        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        self.assertRaises(
            jwt.DecodeError,
            lambda: jwt.verify_signature(decoded_payload, signing,
                                         header, signature))
Exemplo n.º 12
0
    def test_decode_skip_expiration_verification(self):
        self.payload['exp'] = time.time() - 1
        secret = 'secret'
        jwt_message = jwt.encode(self.payload, secret)

        jwt.decode(jwt_message, secret, verify_expiration=False)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)
        jwt.verify_signature(decoded_payload, signing, header,
                             signature, secret, verify_expiration=False)
Exemplo n.º 13
0
    def test_decode_invalid_header_string(self):
        example_jwt = ("eyJhbGciOiAiSFMyNTbpIiwgInR5cCI6ICJKV1QifQ=="
                       ".eyJoZWxsbyI6ICJ3b3JsZCJ9"
                       ".tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8")
        example_secret = "secret"

        try:
            jwt.load(example_jwt)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid header string' in str(e))
        else:
            self.fail('DecodeError not raised')

        try:
            jwt.decode(example_jwt, example_secret)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid header string' in str(e))
        else:
            self.fail('DecodeError not raised')
Exemplo n.º 14
0
    def test_decode_invalid_crypto_padding(self):
        example_jwt = ("eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9"
                       ".eyJoZWxsbyI6ICJ3b3JsZCJ9"
                       ".aatvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8")
        example_secret = "secret"

        self.assertRaises(jwt.DecodeError, lambda: jwt.load(example_jwt))

        self.assertRaises(jwt.DecodeError,
                          lambda: jwt.decode(example_jwt, example_secret))
Exemplo n.º 15
0
    def test_decode_skip_notbefore_verification(self):
        self.payload['nbf'] = time.time() + 10
        secret = 'secret'
        jwt_message = jwt.encode(self.payload, secret)

        jwt.decode(jwt_message, secret, verify_expiration=False)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)
        jwt.verify_signature(decoded_payload, signing, header,
                             signature, secret, verify_expiration=False)
Exemplo n.º 16
0
    def test_decode_invalid_payload_string(self):
        example_jwt = ("eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9"
                       ".eyJoZWxsb-kiOiAid29ybGQifQ=="
                       ".tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8")
        example_secret = "secret"

        try:
            jwt.load(example_jwt)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid payload string' in str(e))
        else:
            self.fail('DecodeError not raised')

        try:
            jwt.decode(example_jwt, example_secret)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid payload string' in str(e))
        else:
            self.fail('DecodeError not raised')
Exemplo n.º 17
0
    def test_decode_unicode_value(self):
        example_payload = {"hello": "world"}
        example_secret = "secret"
        example_jwt = ("eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9"
                       ".eyJoZWxsbyI6ICJ3b3JsZCJ9"
                       ".tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8")
        decoded_payload = jwt.decode(example_jwt, example_secret)

        self.assertEqual(decoded_payload, example_payload)
        decoded_payload, signing, header, signature = jwt.load(example_jwt)
        self.assertEqual(decoded_payload, example_payload)
Exemplo n.º 18
0
    def test_decode_invalid_payload_string(self):
        example_jwt = (
            'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9'
            '.eyJoZWxsb-kiOiAid29ybGQifQ=='
            '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8')
        example_secret = 'secret'

        try:
            jwt.load(example_jwt)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid payload string' in str(e))
        else:
            self.fail('DecodeError not raised')

        try:
            jwt.decode(example_jwt, example_secret)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid payload string' in str(e))
        else:
            self.fail('DecodeError not raised')
Exemplo n.º 19
0
    def test_decode_invalid_header_string(self):
        example_jwt = (
            'eyJhbGciOiAiSFMyNTbpIiwgInR5cCI6ICJKV1QifQ=='
            '.eyJoZWxsbyI6ICJ3b3JsZCJ9'
            '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8')
        example_secret = 'secret'

        try:
            jwt.load(example_jwt)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid header string' in str(e))
        else:
            self.fail('DecodeError not raised')

        try:
            jwt.decode(example_jwt, example_secret)
        except jwt.DecodeError as e:
            self.assertTrue('Invalid header string' in str(e))
        else:
            self.fail('DecodeError not raised')
Exemplo n.º 20
0
    def test_decode_unicode_value(self):
        example_payload = {'hello': 'world'}
        example_secret = 'secret'
        example_jwt = (
            'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9'
            '.eyJoZWxsbyI6ICJ3b3JsZCJ9'
            '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8')
        decoded_payload = jwt.decode(example_jwt, example_secret)

        self.assertEqual(decoded_payload, example_payload)
        decoded_payload, signing, header, signature = jwt.load(example_jwt)
        self.assertEqual(decoded_payload, example_payload)
Exemplo n.º 21
0
    def test_decode_with_expiration(self):
        self.payload['exp'] = utc_timestamp() - 1
        secret = 'secret'
        jwt_message = jwt.encode(self.payload, secret)

        self.assertRaises(jwt.ExpiredSignature,
                          lambda: jwt.decode(jwt_message, secret))

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        self.assertRaises(
            jwt.ExpiredSignature, lambda: jwt.verify_signature(
                decoded_payload, signing, header, signature, secret))
Exemplo n.º 22
0
    def test_load_verify_valid_jwt(self):
        example_payload = {'hello': 'world'}
        example_secret = 'secret'
        example_jwt = (
            b'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9'
            b'.eyJoZWxsbyI6ICJ3b3JsZCJ9'
            b'.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8')

        decoded_payload, signing, header, signature = jwt.load(example_jwt)

        jwt.verify_signature(decoded_payload, signing, header,
                             signature, example_secret)

        self.assertEqual(decoded_payload, example_payload)
Exemplo n.º 23
0
    def test_unicode_secret(self):
        secret = '\xc2'
        jwt_message = jwt.encode(self.payload, secret)

        decoded_payload = jwt.decode(jwt_message, secret)

        self.assertEqual(decoded_payload, self.payload)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        jwt.verify_signature(decoded_payload, signing, header,
                             signature, secret)

        self.assertEqual(decoded_payload, self.payload)
Exemplo n.º 24
0
    def test_bytes_secret(self):
        secret = b'\xc2'  # char value that ascii codec cannot decode
        jwt_message = jwt.encode(self.payload, secret)

        decoded_payload = jwt.decode(jwt_message, secret)

        self.assertEqual(decoded_payload, self.payload)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        jwt.verify_signature(decoded_payload, signing,
                             header, signature, secret)

        self.assertEqual(decoded_payload, self.payload)
Exemplo n.º 25
0
    def test_load_verify_valid_jwt(self):
        example_payload = {"hello": "world"}
        example_secret = "secret"
        example_jwt = (
            b"eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9"
            b".eyJoZWxsbyI6ICJ3b3JsZCJ9"
            b".tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8")

        decoded_payload, signing, header, signature = jwt.load(example_jwt)

        jwt.verify_signature(decoded_payload, signing, header,
                             signature, example_secret)

        self.assertEqual(decoded_payload, example_payload)
Exemplo n.º 26
0
    def test_decode_invalid_header_padding(self):
        example_jwt = (
            "aeyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9"
            ".eyJoZWxsbyI6ICJ3b3JsZCJ9"
            ".tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8")
        example_secret = "secret"

        self.assertRaises(
            jwt.DecodeError,
            lambda: jwt.load(example_jwt))

        self.assertRaises(
            jwt.DecodeError,
            lambda: jwt.decode(example_jwt, example_secret))
Exemplo n.º 27
0
    def test_decode_invalid_header_padding(self):
        example_jwt = (
            'aeyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9'
            '.eyJoZWxsbyI6ICJ3b3JsZCJ9'
            '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8')
        example_secret = 'secret'

        self.assertRaises(
            jwt.DecodeError,
            lambda: jwt.load(example_jwt))

        self.assertRaises(
            jwt.DecodeError,
            lambda: jwt.decode(example_jwt, example_secret))
Exemplo n.º 28
0
    def test_decode_invalid_crypto_padding(self):
        example_jwt = (
            'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9'
            '.eyJoZWxsbyI6ICJ3b3JsZCJ9'
            '.aatvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8')
        example_secret = 'secret'

        self.assertRaises(
            jwt.DecodeError,
            lambda: jwt.load(example_jwt))

        self.assertRaises(
            jwt.DecodeError,
            lambda: jwt.decode(example_jwt, example_secret))
Exemplo n.º 29
0
    def test_unicode_secret(self):
        secret = '\xc2'
        jwt_message = jwt.encode(self.payload, secret)

        decoded_payload = jwt.decode(jwt_message, secret)

        self.assertEqual(decoded_payload, self.payload)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        jwt.verify_signature(decoded_payload, signing, header, signature,
                             secret)

        self.assertEqual(decoded_payload, self.payload)
Exemplo n.º 30
0
    def test_bytes_secret(self):
        secret = b'\xc2'  # char value that ascii codec cannot decode
        jwt_message = jwt.encode(self.payload, secret)

        decoded_payload = jwt.decode(jwt_message, secret)

        self.assertEqual(decoded_payload, self.payload)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        jwt.verify_signature(decoded_payload, signing, header, signature,
                             secret)

        self.assertEqual(decoded_payload, self.payload)
Exemplo n.º 31
0
    def test_decode_with_notbefore(self):
        self.payload['nbf'] = utc_timestamp() + 10
        secret = 'secret'
        jwt_message = jwt.encode(self.payload, secret)

        self.assertRaises(
            jwt.ExpiredSignature,
            lambda: jwt.decode(jwt_message, secret))

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        self.assertRaises(
            jwt.ExpiredSignature,
            lambda: jwt.verify_signature(
                decoded_payload, signing, header, signature, secret))
Exemplo n.º 32
0
def remote_user_jwt(request):
    # type: (HttpRequest) -> HttpResponse
    try:
        json_web_token = request.POST["json_web_token"]
        payload, signing_input, header, signature = jwt.load(json_web_token)
    except KeyError:
        raise JsonableError(_("No JSON web token passed in request"))
    except jwt.DecodeError:
        raise JsonableError(_("Bad JSON web token"))

    remote_user = payload.get("user", None)
    if remote_user is None:
        raise JsonableError(_("No user specified in JSON web token claims"))
    domain = payload.get('realm', None)
    if domain is None:
        raise JsonableError(_("No domain specified in JSON web token claims"))

    email = "%s@%s" % (remote_user, domain)

    try:
        jwt.verify_signature(payload, signing_input, header, signature,
                             settings.JWT_AUTH_KEYS[domain])
        # We do all the authentication we need here (otherwise we'd have to
        # duplicate work), but we need to call authenticate with some backend so
        # that the request.backend attribute gets set.
        return_data = {}  # type: Dict[str, bool]
        user_profile = authenticate(username=email,
                                    realm_subdomain=get_subdomain(request),
                                    return_data=return_data,
                                    use_dummy_backend=True)
        if return_data.get('invalid_subdomain'):
            logging.warning(
                "User attempted to JWT login to wrong subdomain %s: %s" % (
                    get_subdomain(request),
                    email,
                ))
            raise JsonableError(_("Wrong subdomain"))
    except (jwt.DecodeError, jwt.ExpiredSignature):
        raise JsonableError(_("Bad JSON web token signature"))
    except KeyError:
        raise JsonableError(_("Realm not authorized for JWT login"))
    except UserProfile.DoesNotExist:
        user_profile = None

    return login_or_register_remote_user(request, email, user_profile,
                                         remote_user)
Exemplo n.º 33
0
    def test_encode_decode_with_rsa_sha384(self):
        try:
            from Crypto.PublicKey import RSA

            with open('tests/testkey', 'r') as rsa_priv_file:
                priv_rsakey = RSA.importKey(rsa_priv_file.read())
                jwt_message = jwt.encode(self.payload, priv_rsakey,
                                         algorithm='RS384')

            with open('tests/testkey.pub', 'r') as rsa_pub_file:
                pub_rsakey = RSA.importKey(rsa_pub_file.read())
                assert jwt.decode(jwt_message, pub_rsakey)

                load_output = jwt.load(jwt_message)
                jwt.verify_signature(key=pub_rsakey, *load_output)
        except ImportError:
            pass
Exemplo n.º 34
0
Arquivo: auth.py Projeto: umkay/zulip
def remote_user_jwt(request):
    # type: (HttpRequest) -> HttpResponse
    try:
        json_web_token = request.POST["json_web_token"]
        payload, signing_input, header, signature = jwt.load(json_web_token)
    except KeyError:
        raise JsonableError(_("No JSON web token passed in request"))
    except jwt.DecodeError:
        raise JsonableError(_("Bad JSON web token"))

    remote_user = payload.get("user", None)
    if remote_user is None:
        raise JsonableError(_("No user specified in JSON web token claims"))
    domain = payload.get('realm', None)
    if domain is None:
        raise JsonableError(_("No domain specified in JSON web token claims"))

    email = "%s@%s" % (remote_user, domain)

    try:
        jwt.verify_signature(payload, signing_input, header, signature,
                             settings.JWT_AUTH_KEYS[domain])
        # We do all the authentication we need here (otherwise we'd have to
        # duplicate work), but we need to call authenticate with some backend so
        # that the request.backend attribute gets set.
        return_data = {} # type: Dict[str, bool]
        user_profile = authenticate(username=email,
                                    realm_subdomain=get_subdomain(request),
                                    return_data=return_data,
                                    use_dummy_backend=True)
        if return_data.get('invalid_subdomain'):
            logging.warning("User attempted to JWT login to wrong subdomain %s: %s" % (get_subdomain(request), email,))
            raise JsonableError(_("Wrong subdomain"))
    except (jwt.DecodeError, jwt.ExpiredSignature):
        raise JsonableError(_("Bad JSON web token signature"))
    except KeyError:
        raise JsonableError(_("Realm not authorized for JWT login"))
    except UserProfile.DoesNotExist:
        user_profile = None

    return login_or_register_remote_user(request, email, user_profile, remote_user)
Exemplo n.º 35
0
    def test_decode_with_notbefore_with_leeway(self):
        self.payload['nbf'] = utc_timestamp() + 10
        secret = 'secret'
        jwt_message = jwt.encode(self.payload, secret)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        # With 13 seconds leeway, should be ok
        jwt.decode(jwt_message, secret, leeway=13)

        jwt.verify_signature(decoded_payload, signing, header,
                             signature, secret, leeway=13)

        # With 1 seconds, should fail
        self.assertRaises(
            jwt.ExpiredSignature,
            lambda: jwt.decode(jwt_message, secret, leeway=1))

        self.assertRaises(
            jwt.ExpiredSignature,
            lambda: jwt.verify_signature(decoded_payload, signing,
                                         header, signature, secret, leeway=1))
Exemplo n.º 36
0
    def test_decode_with_expiration_with_leeway(self):
        self.payload['exp'] = utc_timestamp() - 2
        secret = 'secret'
        jwt_message = jwt.encode(self.payload, secret)

        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        # With 3 seconds leeway, should be ok
        jwt.decode(jwt_message, secret, leeway=3)

        jwt.verify_signature(decoded_payload, signing, header,
                             signature, secret, leeway=3)

        # With 1 seconds, should fail
        self.assertRaises(
            jwt.ExpiredSignature,
            lambda: jwt.decode(jwt_message, secret, leeway=1))

        self.assertRaises(
            jwt.ExpiredSignature,
            lambda: jwt.verify_signature(decoded_payload, signing,
                                         header, signature, secret, leeway=1))
Exemplo n.º 37
0
    def test_load_no_verification(self):
        right_secret = 'foo'
        jwt_message = jwt.encode(self.payload, right_secret)
        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        self.assertEqual(decoded_payload, self.payload)
Exemplo n.º 38
0
    def authorized_handler(self):
        if ('state' in request.args or 'oauth_random' in session) and \
           request.args['state'] != hashlib.sha256(
               current_app.secret_key +
               session.pop('oauth_random', '')).hexdigest():
            session['openid_error'] = 'Access denied: bad state'

            return redirect(self.get_current_url())

        resp = self.app.authorized_response()
        if resp is None:
            # XXX Hack to minimze changes
            session['openid_error'] = ('Access denied: %s %s' %
                                       (request.args['error_reason'],
                                        request.args['error_description']))
            return redirect(self.get_current_url())
        if 'oauth_token' in resp:
            session['%s_oauth_token' %
                    self.provider] = (resp['oauth_token'],
                                      resp['oauth_token_secret'])
        else:
            session['%s_oauth_token' % self.provider] = (resp['access_token'],
                                                         '')

        if 'screen_name' in resp:
            return self.after_login_func(
                AuthResponse(self.provider,
                             resp['user_id'],
                             nickname=resp.get('screen_name')))

        sub = None
        if self.jwks_uri:
            try:
                _, _, header, _ = jwt.load(resp['id_token'])
            except AttributeError:
                header = jwt.get_unverified_header(resp['id_token'])
            kid = header.get('kid')
            if kid not in self.jwks:
                h = httplib2.Http()
                hdr, content = h.request(self.jwks_uri)
                self.jwks = {}
                for key in json.loads(content.decode('utf-8'))['keys']:
                    self.jwks[key.get('kid')] = key

            if kid:
                keys = [self.jwks[kid]]
            else:
                keys = self.jwks.values()

            data = None
            for key in keys:
                try:
                    _key = self._json_to_key(key)
                    try:
                        data = jwt.decode(resp['id_token'], _key)
                    except TypeError:
                        data = jwt.decode(resp['id_token'],
                                          _key.exportKey(format='PEM'),
                                          audience=self.app.consumer_key)
                except jwt.DecodeError:
                    pass
                else:
                    break

            if not data:
                session['openid_error'] = 'Access denied'
                return redirect(self.get_current_url())

            sub = data['sub']

        # Facebook and Windows Live needs another call to fetch user id
        data = None
        me = self.app.get(self.userinfo_endpoint, data=data)

        email = None
        if 'email' in me.data:
            email = me.data['email']
        elif 'emails' in me.data:
            email = me.data['emails'].get('preferred')
        if 'sub' in me.data:
            if sub and sub != me.data['sub']:
                raise RuntimeError('Authentication error!')
            sub = me.data['sub']
        else:
            sub = me.data['id']
        return self.after_login_func(
            AuthResponse(self.provider,
                         sub,
                         fullname=me.data.get('name'),
                         email=email))
Exemplo n.º 39
0
def identify(mw_uri, consumer_token, access_token, leeway=10.0):
    """
    Gather's identifying information about a user via an authorized token.

    :Parameters:
        mw_uri : `str`
            The base URI of the MediaWiki installation.  Note that the URI
            should end in ``"index.php"``.
        consumer_token : :class:`~mwoauth.ConsumerToken`
            A token representing you, the consumer.
        access_token : :class:`~mwoauth.AccessToken`
            A token representing an authorized user.  Obtained from `complete()`
        leeway : `int` | `float`
            The number of seconds of leeway to account for when examining a
            tokens "issued at" timestamp.

    :Returns:
        A dictionary containing identity information.
    """

    # Construct an OAuth auth
    auth = OAuth1(consumer_token.key,
                  client_secret=consumer_token.secret,
                  resource_owner_key=access_token.key,
                  resource_owner_secret=access_token.secret)

    # Request the identity using auth
    r = requests.post(url=mw_uri,
                      params={'title': "Special:OAuth/identify"},
                      auth=auth)

    # Decode json & stuff
    try:
        identity, signing_input, header, signature = jwt.load(r.content)
    except jwt.DecodeError as e:
        raise Exception("An error occurred while trying to read json " +
                        "content: {0}".format(e))

    # Ensure no downgrade in authentication
    if not header['alg'] == "HS256":
        raise Exception("Unexpected algorithm used for authentication " +
                        "{0}, expected {1}".format("HS256", header['alg']))

    # Check signature
    try:
        jwt.verify_signature(identity, signing_input, header, signature,
                             consumer_token.secret, False)
    except jwt.DecodeError as e:
        raise Exception("Could not verify the jwt signature: {0}".format(e))

    # Verify the issuer is who we expect (server sends $wgCanonicalServer)
    issuer = urlparse(identity['iss']).netloc
    expected_domain = urlparse(mw_uri).netloc
    if not issuer == expected_domain:
        raise Exception("Unexpected issuer " +
                        "{0}, expected {1}".format(issuer, expected_domain))

    # Verify we are the intended audience of this response
    audience = identity['aud']
    if not audience == consumer_token.key:
        raise Exception("Unexpected audience " +
                        "{0}, expected {1}".format(audience, expected_domain))

    now = time.time()

    # Check that the identity was issued in the past.
    issued_at = float(identity['iat'])
    if not now >= (issued_at - leeway):
        raise Exception("Identity issued {0} ".format(issued_at - now) +
                        "seconds in the future!")

    # Check that the identity has not yet expired
    expiration = float(identity['exp'])
    if not now <= expiration:
        raise Exception("Identity expired {0} ".format(expiration - now) +
                        "seconds ago!")

    # Verify that the nonce matches our request one,
    # to avoid a replay attack
    authorization_header = force_unicode(r.request.headers['Authorization'])
    request_nonce = re.search(r'oauth_nonce="(.*?)"',
                              authorization_header).group(1)
    if identity['nonce'] != request_nonce:
        raise Exception('Replay attack detected: {0} != {1}'.format(
            identity['nonce'], request_nonce))

    return identity
Exemplo n.º 40
0
def identify(mw_uri, consumer_token, access_token, leeway=10.0):
    """
    Gather's identifying information about a user via an authorized token.

    :Parameters:
        mw_uri : `str`
            The base URI of the MediaWiki installation.  Note that the URI
            should end in ``"index.php"``.
        consumer_token : :class:`~mwoauth.ConsumerToken`
            A token representing you, the consumer.
        access_token : :class:`~mwoauth.AccessToken`
            A token representing an authorized user.  Obtained from `complete()`
        leeway : `int` | `float`
            The number of seconds of leeway to account for when examining a
            tokens "issued at" timestamp.

    :Returns:
        A dictionary containing identity information.
    """

    # Construct an OAuth auth
    auth = OAuth1(consumer_token.key,
                  client_secret=consumer_token.secret,
                  resource_owner_key=access_token.key,
                  resource_owner_secret=access_token.secret)

    # Request the identity using auth
    r = requests.post(url=mw_uri,
                      params={'title': "Special:OAuth/identify"},
                      auth=auth)

    # Decode json & stuff
    try:
        identity, signing_input, header, signature = jwt.load(r.content)
    except jwt.DecodeError as e:
        raise Exception("An error occurred while trying to read json " +
                        "content: {0}".format(e))

    # Ensure no downgrade in authentication
    if not header['alg'] == "HS256":
        raise Exception("Unexpected algorithm used for authentication " +
                        "{0}, expected {1}".format("HS256", header['alg']))

    # Check signature
    try:
        jwt.verify_signature(identity, signing_input, header, signature,
                             consumer_token.secret, False)
    except jwt.DecodeError as e:
        raise Exception("Could not verify the jwt signature: {0}".format(e))

    # Verify the issuer is who we expect (server sends $wgCanonicalServer)
    issuer = urlparse(identity['iss']).netloc
    expected_domain = urlparse(mw_uri).netloc
    if not issuer == expected_domain:
        raise Exception("Unexpected issuer " +
                        "{0}, expected {1}".format(issuer, expected_domain))

    # Verify we are the intended audience of this response
    audience = identity['aud']
    if not audience == consumer_token.key:
        raise Exception("Unexpected audience " +
                        "{0}, expected {1}".format(audience, expected_domain))

    now = time.time()

    # Check that the identity was issued in the past.
    issued_at = float(identity['iat'])
    if not now >= (issued_at - leeway):
        raise Exception("Identity issued {0} ".format(issued_at - now) +
                        "seconds in the future!")

    # Check that the identity has not yet expired
    expiration = float(identity['exp'])
    if not now <= expiration:
        raise Exception("Identity expired {0} ".format(expiration - now) +
                        "seconds ago!")

    # Verify that the nonce matches our request one,
    # to avoid a replay attack
    authorization_header = force_unicode(r.request.headers['Authorization'])
    request_nonce = re.search(r'oauth_nonce="(.*?)"',
                              authorization_header).group(1)
    if identity['nonce'] != request_nonce:
        raise Exception('Replay attack detected: {0} != {1}'.format(
            identity['nonce'], request_nonce))

    return identity
Exemplo n.º 41
0
    def test_load_no_verification(self):
        right_secret = 'foo'
        jwt_message = jwt.encode(self.payload, right_secret)
        decoded_payload, signing, header, signature = jwt.load(jwt_message)

        self.assertEqual(decoded_payload, self.payload)