示例#1
0
    def test_authtoken_rs256_verification(self):
        # Verify that the auth token (signed by Bouncer's private key)
        # can be validated using Bouncer's public key. Obtain/construct
        # Bouncer's public key from it's JSON Web Key Set (jwks) entpoint

        # Obtain authentication token.
        token, _ = self.test_authtoken_rs256_anatomy()

        # Obtain the JSON Web Key Set.
        r = requests.get(Url('/auth/jwks'))
        keys = r.json()['keys'][0]

        # Extract the public modulus and exponent from the data.
        exponent_bytes = base64url_decode(keys['e'].encode('ascii'))
        exponent_int = bytes_to_number(exponent_bytes)

        modulus_bytes = base64url_decode(keys['n'].encode('ascii'))
        modulus_int = bytes_to_number(modulus_bytes)

        # Generate a public key instance from these numbers.
        public_numbers = rsa.RSAPublicNumbers(n=modulus_int, e=exponent_int)
        public_key = public_numbers.public_key(backend=cryptography_backend)

        # Verify token signature using that public key.
        payload = jwt.decode(token, public_key, algorithms='RS256')
        assert payload['uid'] == self.user1_uid
示例#2
0
 def get_key(self, kid):
     keys = self.get_keys().get('keys')
     key = list(filter(lambda x: x.get('kid') == kid, keys))[0]
     _e = key['e']
     _n = key['n']
     e = int.from_bytes(base64url_decode(_e), 'big')
     n = int.from_bytes(base64url_decode(_n), 'big')
     return RSAPublicNumbers(e, n).public_key(default_backend())
示例#3
0
文件: schema1.py 项目: syed/quay
    def _payload(self):
        if self._signatures is None:
            return self._bytes.as_encoded_str()

        byte_data = self._bytes.as_encoded_str()
        protected = str(self._signatures[0][DOCKER_SCHEMA1_PROTECTED_KEY])
        parsed_protected = json.loads(base64url_decode(protected))
        signed_content_head = byte_data[:parsed_protected[
            DOCKER_SCHEMA1_FORMAT_LENGTH_KEY]]
        signed_content_tail = base64url_decode(
            str(parsed_protected[DOCKER_SCHEMA1_FORMAT_TAIL_KEY]))
        return signed_content_head + signed_content_tail
示例#4
0
    def test_ec_verify_should_return_true_for_test_vector(self):
        """
        This test verifies that ECDSA verification works with a known good
        signature and key.

        Reference: https://tools.ietf.org/html/rfc7520#section-4.3
        """
        signing_input = ensure_bytes(
            'eyJhbGciOiJFUzUxMiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhb'
            'XBsZSJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb'
            '3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdS'
            'Bkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmU'
            'geW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4')

        signature = base64url_decode(
            ensure_bytes(
                'AE_R_YZCChjn4791jSQCrdPZCNYqHXCTZH0-JZGYNlaAjP2kqaluUIIUnC9qvbu9P'
                'lon7KRTzoNEuT4Va2cmL1eJAQy3mtPBu_u_sDDyYjnAMDxXPn7XrT0lw-kvAD890j'
                'l8e2puQens_IEKBpHABlsbEPX6sFY8OcGDqoRuBomu9xQ2'))

        algo = ECAlgorithm(ECAlgorithm.SHA512)
        key = algo.prepare_key(load_ec_pub_key())

        result = algo.verify(signing_input, key, signature)
        assert result
示例#5
0
    def user_data(self, access_token, *args, **kwargs):
        response = kwargs.get('response')

        id_token = response.get('id_token')
        if six.PY2:
            # str() to fix a bug in Python's base64
            # https://stackoverflow.com/a/2230623/161278
            id_token = str(id_token)

        jwt_header_json = base64url_decode(id_token.split('.')[0])
        jwt_header = json.loads(jwt_header_json.decode('ascii'))

        # `kid` is short for key id
        key = self.get_public_key(jwt_header['kid'])

        try:
            return jwt_decode(
                id_token,
                key=key,
                algorithms=jwt_header['alg'],
                audience=self.setting('KEY'),
                leeway=self.setting('JWT_LEEWAY', default=0),
            )
        except (DecodeError, ExpiredSignature) as error:
            raise AuthTokenError(self, error)
示例#6
0
    def test_rsapss_verify_should_return_true_for_test_vector(self):
        """
        This test verifies that RSA-PSS verification works with a known good
        signature and key.

        Reference: https://tools.ietf.org/html/rfc7520#section-4.2
        """
        signing_input = ensure_bytes(
            'eyJhbGciOiJQUzM4NCIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhb'
            'XBsZSJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb'
            '3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdS'
            'Bkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmU'
            'geW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4')

        signature = base64url_decode(
            ensure_bytes(
                'cu22eBqkYDKgIlTpzDXGvaFfz6WGoz7fUDcfT0kkOy42miAh2qyBzk1xEsnk2IpN6'
                '-tPid6VrklHkqsGqDqHCdP6O8TTB5dDDItllVo6_1OLPpcbUrhiUSMxbbXUvdvWXz'
                'g-UD8biiReQFlfz28zGWVsdiNAUf8ZnyPEgVFn442ZdNqiVJRmBqrYRXe8P_ijQ7p'
                '8Vdz0TTrxUeT3lm8d9shnr2lfJT8ImUjvAA2Xez2Mlp8cBE5awDzT0qI0n6uiP1aC'
                'N_2_jLAeQTlqRHtfa64QQSUmFAAjVKPbByi7xho0uTOcbH510a6GYmJUAfmWjwZ6o'
                'D4ifKo8DYM-X72Eaw'))

        algo = RSAPSSAlgorithm(RSAPSSAlgorithm.SHA384)
        key = algo.prepare_key(load_rsa_pub_key())

        result = algo.verify(signing_input, key, signature)
        assert result
示例#7
0
    def user_data(self, access_token, *args, **kwargs):
        response = kwargs.get('response')

        id_token = response.get('id_token')
        if six.PY2:
            # str() to fix a bug in Python's base64
            # https://stackoverflow.com/a/2230623/161278
            id_token = str(id_token)

        jwt_header_json = base64url_decode(id_token.split('.')[0])
        jwt_header = json.loads(jwt_header_json.decode('ascii'))

        # `kid` is short for key id
        key = self.get_public_key(jwt_header['kid'])

        try:
            return jwt_decode(
                id_token,
                key=key,
                algorithms=jwt_header['alg'],
                audience=self.setting('KEY'),
                leeway=self.setting('JWT_LEEWAY', default=0),
            )
        except (DecodeError, ExpiredSignature) as error:
            raise AuthTokenError(self, error)
示例#8
0
    def test_request_authtoken_without_expiration(self):
        # Include the `exp` key in the `data` dictionary, with the value 0.
        # Note(JP): this is a private DC/OS interface introduced as a workaround
        # for the problem of reliable authentication token refresh. It must
        # never be publicly documented, and should be removed in a future
        # version.
        login_token = jwt.encode(
            {
                'exp': int(time.time() + 5 * 60),
                'uid': self.service1_uid
            },
            self.service1_private_key,
            algorithm='RS256').decode('ascii')

        r = requests.post(url=Url('/auth/login'),
                          json={
                              'exp': 0,
                              'uid': self.service1_uid,
                              'token': login_token
                          })
        assert r.status_code == 200
        token = r.json()['token']
        _, payload_bytes, _ = [
            base64url_decode(_.encode('ascii')) for _ in token.split(".")
        ]
        payload_dict = json.loads(payload_bytes.decode('ascii'))
        assert 'exp' not in payload_dict
示例#9
0
    def test_rsa_verify_should_return_true_for_test_vector(self):
        """
        This test verifies that RSA PKCS v1.5 verification works with a known
        good signature and key.

        Reference: https://tools.ietf.org/html/rfc7520#section-4.1
        """
        signing_input = ensure_bytes(
            'eyJhbGciOiJSUzI1NiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhb'
            'XBsZSJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb'
            '3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdS'
            'Bkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmU'
            'geW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4')

        signature = base64url_decode(
            ensure_bytes(
                'MRjdkly7_-oTPTS3AXP41iQIGKa80A0ZmTuV5MEaHoxnW2e5CZ5NlKtainoFmKZop'
                'dHM1O2U4mwzJdQx996ivp83xuglII7PNDi84wnB-BDkoBwA78185hX-Es4JIwmDLJ'
                'K3lfWRa-XtL0RnltuYv746iYTh_qHRD68BNt1uSNCrUCTJDt5aAE6x8wW1Kt9eRo4'
                'QPocSadnHXFxnt8Is9UzpERV0ePPQdLuW3IS_de3xyIrDaLGdjluPxUAhb6L2aXic'
                '1U12podGU0KLUQSE_oI-ZnmKJ3F4uOZDnd6QZWJushZ41Axf_fcIe8u9ipH84ogor'
                'ee7vjbU5y18kDquDg'))

        algo = RSAAlgorithm(RSAAlgorithm.SHA256)
        key = algo.prepare_key(load_rsa_pub_key())

        result = algo.verify(signing_input, key, signature)
        assert result
示例#10
0
    def test_rsa_verify_should_return_true_for_test_vector(self):
        """
        This test verifies that RSA PKCS v1.5 verification works with a known
        good signature and key.

        Reference: https://tools.ietf.org/html/rfc7520#section-4.1
        """
        signing_input = ensure_bytes(
            'eyJhbGciOiJSUzI1NiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhb'
            'XBsZSJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb'
            '3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdS'
            'Bkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmU'
            'geW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4'
        )

        signature = base64url_decode(ensure_bytes(
            'MRjdkly7_-oTPTS3AXP41iQIGKa80A0ZmTuV5MEaHoxnW2e5CZ5NlKtainoFmKZop'
            'dHM1O2U4mwzJdQx996ivp83xuglII7PNDi84wnB-BDkoBwA78185hX-Es4JIwmDLJ'
            'K3lfWRa-XtL0RnltuYv746iYTh_qHRD68BNt1uSNCrUCTJDt5aAE6x8wW1Kt9eRo4'
            'QPocSadnHXFxnt8Is9UzpERV0ePPQdLuW3IS_de3xyIrDaLGdjluPxUAhb6L2aXic'
            '1U12podGU0KLUQSE_oI-ZnmKJ3F4uOZDnd6QZWJushZ41Axf_fcIe8u9ipH84ogor'
            'ee7vjbU5y18kDquDg'
        ))

        algo = RSAAlgorithm(RSAAlgorithm.SHA256)
        key = algo.prepare_key(load_rsa_pub_key())

        result = algo.verify(signing_input, key, signature)
        assert result
示例#11
0
 def test_request_authtoken_with_custom_expiration(self):
     # Include the `exp` key in the `data` dictionary, with a non-zero
     # integer value. Note(JP): this is a private DC/OS interface introduced
     # as a workaround for the problem of reliable authentication token
     # refresh. It must never be publicly documented, and should be removed
     # in a future version, together with this test.
     url = Url('/auth/login')
     data = {
         'uid':
         self.service1_uid,
         'exp':
         84600,
         'token':
         jwt.encode(
             {
                 'exp': int(time.time() + 5 * 60),
                 'uid': self.service1_uid
             },
             self.service1_private_key,
             algorithm='RS256').decode('ascii')
     }
     r = requests.post(url, json=data)
     assert r.status_code == 200
     token = r.json()['token']
     _, payload_bytes, _ = [
         base64url_decode(_.encode('ascii')) for _ in token.split(".")
     ]
     payload_dict = json.loads(payload_bytes.decode('ascii'))
     assert payload_dict['exp'] == 84600
示例#12
0
    def test_ec_verify_should_return_true_for_test_vector(self):
        """
        This test verifies that ECDSA verification works with a known good
        signature and key.

        Reference: https://tools.ietf.org/html/rfc7520#section-4.3
        """
        signing_input = ensure_bytes(
            'eyJhbGciOiJFUzUxMiIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhb'
            'XBsZSJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb'
            '3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdS'
            'Bkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmU'
            'geW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4'
        )

        signature = base64url_decode(ensure_bytes(
            'AE_R_YZCChjn4791jSQCrdPZCNYqHXCTZH0-JZGYNlaAjP2kqaluUIIUnC9qvbu9P'
            'lon7KRTzoNEuT4Va2cmL1eJAQy3mtPBu_u_sDDyYjnAMDxXPn7XrT0lw-kvAD890j'
            'l8e2puQens_IEKBpHABlsbEPX6sFY8OcGDqoRuBomu9xQ2'
        ))

        algo = ECAlgorithm(ECAlgorithm.SHA512)
        key = algo.prepare_key(load_ec_pub_key())

        result = algo.verify(signing_input, key, signature)
        assert result
示例#13
0
    def test_rsapss_verify_should_return_true_for_test_vector(self):
        """
        This test verifies that RSA-PSS verification works with a known good
        signature and key.

        Reference: https://tools.ietf.org/html/rfc7520#section-4.2
        """
        signing_input = ensure_bytes(
            'eyJhbGciOiJQUzM4NCIsImtpZCI6ImJpbGJvLmJhZ2dpbnNAaG9iYml0b24uZXhhb'
            'XBsZSJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb'
            '3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdS'
            'Bkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmU'
            'geW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4'
        )

        signature = base64url_decode(ensure_bytes(
            'cu22eBqkYDKgIlTpzDXGvaFfz6WGoz7fUDcfT0kkOy42miAh2qyBzk1xEsnk2IpN6'
            '-tPid6VrklHkqsGqDqHCdP6O8TTB5dDDItllVo6_1OLPpcbUrhiUSMxbbXUvdvWXz'
            'g-UD8biiReQFlfz28zGWVsdiNAUf8ZnyPEgVFn442ZdNqiVJRmBqrYRXe8P_ijQ7p'
            '8Vdz0TTrxUeT3lm8d9shnr2lfJT8ImUjvAA2Xez2Mlp8cBE5awDzT0qI0n6uiP1aC'
            'N_2_jLAeQTlqRHtfa64QQSUmFAAjVKPbByi7xho0uTOcbH510a6GYmJUAfmWjwZ6o'
            'D4ifKo8DYM-X72Eaw'
        ))

        algo = RSAPSSAlgorithm(RSAPSSAlgorithm.SHA384)
        key = algo.prepare_key(load_rsa_pub_key())

        result = algo.verify(signing_input, key, signature)
        assert result
def from_base64url_uint(val):
    if isinstance(val, str):
        val = val.encode('ascii')

    data = base64url_decode(val)

    buf = struct.unpack('%sB' % len(data), data)
    return int(''.join(["%02x" % byte for byte in buf]), 16)
示例#15
0
def test_service_account_create_login_delete(dcos_api_session,
                                             noauth_api_session):

    # Create service user account, share the public key with the IAM.
    serviceuid = 'testservice'
    r = dcos_api_session.put('/acs/api/v1/users/' + serviceuid,
                             json={
                                 'description': 'foo',
                                 'public_key': default_rsa_pubkey
                             })
    assert r.status_code == 201, r.text

    # Generate short-lived service login token (RS256 JWT signed with
    # the service's private key).
    service_login_token = jwt.encode(
        {
            'uid': serviceuid,
            'exp': time.time() + 30
        },
        default_rsa_privkey,
        algorithm='RS256').decode('ascii')

    # Log in via the service login token.
    r = noauth_api_session.post('/acs/api/v1/auth/login',
                                json={
                                    'uid': serviceuid,
                                    'token': service_login_token
                                })
    assert r.status_code == 200, r.text

    # Confirm that the response body contains a DC/OS authentication token.
    token = r.json()['token']
    header_bytes, payload_bytes, signature_bytes = [
        base64url_decode(_.encode('ascii')) for _ in token.split(".")
    ]

    header_dict = json.loads(header_bytes.decode('ascii'))
    assert header_dict['alg'] == 'RS256'
    assert header_dict['typ'] == 'JWT'

    payload_dict = json.loads(payload_bytes.decode('ascii'))
    assert 'exp' in payload_dict
    assert 'uid' in payload_dict
    assert payload_dict['uid'] == serviceuid

    # Verify that the service user account appears in the users collection.
    r = dcos_api_session.get('/acs/api/v1/users', query='type=service')
    uids = [o['uid'] for o in r.json()['array']]
    assert serviceuid in uids

    # Delete the service user account.
    r = dcos_api_session.delete('/acs/api/v1/users/' + serviceuid)
    assert r.status_code == 204

    # Confirm that service does not appear in collection anymore.
    r = dcos_api_session.get('/acs/api/v1/users', query='type=service')
    uids = [o['uid'] for o in r.json()['array']]
    assert serviceuid not in uids
示例#16
0
def verify_jwt(token, jwks):
    hmac_key = get_hmac_key(token, jwks)
    if not hmac_key:
        raise ValueError("No public key found")
    hmac_key = jwk.construct(get_hmac_key(token, jwks))

    message, encoded_signature = token.rsplit(".", 1)
    decoded_signature = base64url_decode(encoded_signature.encode())
    return hmac_key.verify(message.encode(), decoded_signature)
示例#17
0
    def _get_type(self):
        raw_header = self.raw_jwt.split(".")[0]
        header: Dict[str, str] = json.loads(base64url_decode(raw_header))

        if header.get("class") not in ("access", "refresh"):
            raise JWTDecodeError(
                "Can not resolve token type by JOSE header. missing 'class'")

        return header.get("class")
示例#18
0
def verify_token(masterUrl, authToken):
    keys = requests.get('https://' + masterUrl + '/acs/api/v1/auth/jwks',
                        verify=False).json()['keys'][0]

    exponent_bytes = base64url_decode(keys['e'].encode('ascii'))
    exponent_int = bytes_to_number(exponent_bytes)

    modulus_bytes = base64url_decode(keys['n'].encode('ascii'))
    modulus_int = bytes_to_number(modulus_bytes)

    public_numbers = rsa.RSAPublicNumbers(n=modulus_int, e=exponent_int)
    public_key = public_numbers.public_key(backend=default_backend())

    payload = jwt.decode(authToken, public_key, algorithm='RS256')

    print payload
    print "expiration is: " + time.strftime('%Y-%m-%d %H:%M:%S',
                                            time.localtime(payload['exp']))
示例#19
0
    def verify_jwk_token(self, jwt_credentials):
        try:
            public_key = self.kid_to_jwk[jwt_credentials.header['kid']]
        except KeyError:
            raise HTTPException(status_code=HTTP_401_UNAUTHORIZED,
                                detail="JWT public key not found")

        key = jwk.construct(public_key)
        decoded_signature = base64url_decode(
            jwt_credentials.signature.encode())
        return key.verify(jwt_credentials.message.encode(), decoded_signature)
示例#20
0
def jwt2john(jwt):
    """
    Convert signature from base64 to hex, and separate it from the data by a #
    so that John can parse it.
    """
    jwt_bytes = jwt.encode('ascii')
    parts = jwt_bytes.split(b'.')

    data = parts[0] + b'.' + parts[1]
    signature = hexlify(base64url_decode(parts[2]))

    return (data + b'#' + signature).decode('ascii')
示例#21
0
文件: test_iam.py 项目: dcos/dcos
def test_service_account_create_login_delete(
        dcos_api_session, noauth_api_session):

    # Create service user account, share the public key with the IAM.
    serviceuid = 'testservice'
    r = dcos_api_session.put(
        '/acs/api/v1/users/' + serviceuid,
        json={'description': 'foo', 'public_key': default_rsa_pubkey}
    )
    assert r.status_code == 201, r.text

    # Generate short-lived service login token (RS256 JWT signed with
    # the service's private key).
    service_login_token = jwt.encode(
        {'uid': serviceuid, 'exp': time.time() + 30},
        default_rsa_privkey,
        algorithm='RS256'
    ).decode('ascii')

    # Log in via the service login token.
    r = noauth_api_session.post(
        '/acs/api/v1/auth/login',
        json={'uid': serviceuid, 'token': service_login_token}
    )
    assert r.status_code == 200, r.text

    # Confirm that the response body contains a DC/OS authentication token.
    token = r.json()['token']
    header_bytes, payload_bytes, signature_bytes = [
        base64url_decode(_.encode('ascii')) for _ in token.split(".")]

    header_dict = json.loads(header_bytes.decode('ascii'))
    assert header_dict['alg'] == 'RS256'
    assert header_dict['typ'] == 'JWT'

    payload_dict = json.loads(payload_bytes.decode('ascii'))
    assert 'exp' in payload_dict
    assert 'uid' in payload_dict
    assert payload_dict['uid'] == serviceuid

    # Verify that the service user account appears in the users collection.
    r = dcos_api_session.get('/acs/api/v1/users', query='type=service')
    uids = [o['uid'] for o in r.json()['array']]
    assert serviceuid in uids

    # Delete the service user account.
    r = dcos_api_session.delete('/acs/api/v1/users/' + serviceuid)
    assert r.status_code == 204

    # Confirm that service does not appear in collection anymore.
    r = dcos_api_session.get('/acs/api/v1/users', query='type=service')
    uids = [o['uid'] for o in r.json()['array']]
    assert serviceuid not in uids
示例#22
0
def jwt2john(jwt):
    """
    Convert signature from base64 to hex, and separate it from the data by a #
    so that John can parse it.
    """
    jwt_bytes = jwt.encode('ascii')
    parts = jwt_bytes.split(b'.')

    data = parts[0] + b'.' + parts[1]
    signature = hexlify(base64url_decode(parts[2]))

    return (data + b'#' + signature).decode('ascii')
示例#23
0
def jwt2john(jwt):
    """
    Converts the signature from base64 to hex, and seperates it from the data with a #
    allowing John to parse it.
    :param jwt: JWT string to johnify
    :return: johnified JWT string
    """
    parts = jwt.split('.')

    data = parts[0] + '.' + parts[1]
    signature = hexlify(base64url_decode(parts[2]))
    return f"{data}#{signature.decode('utf-8')}"
示例#24
0
文件: org_check.py 项目: butla/PyDAS
 def _user_is_admin(user_token):
     """
     :param str user_token: User's OAuth 2 token payload (containing "bearer" prefix).
     :return: True if the user is an admin.
     :rtype: bool
     """
     # get token without "bearer"
     token = user_token.split()[1]
     # take the middle part with payload
     token_payload_based = token.split('.')[1]
     token_payload_str = base64url_decode(token_payload_based.encode()).decode()
     token_payload = json.loads(token_payload_str)
     return 'console.admin' in token_payload['scope']
示例#25
0
def jwt_token_verify(id_token, client_id, issuer, autoconfig=None, jwk=None):
    """
    Verify a JWT token using public key.
    If jwk is not provided the issuer must support auto-discovery.
    This will also slow down the login process since multiple remote calls
    are required to fetch jwk.
    :param id_token: The openid id_token returned by the authorisation call
    :param client_id: The client_id, required for JWT verification
    :param issuer: The issuer, required for JWT verification and for
                   auto-configuration if necessary
    :param autoconfig: Dictionary of auto-configuration properties, if empty
                       will be fetched if required
    :param jwk: The JSON web key, if empty will be fetched using autoconfig
    :return dict: The decoded verified token
    :raises Exception: If verification failed
    """
    # https://pyjwt.readthedocs.io/en/latest/usage.html
    # https://openid.net/specs/openid-connect-core-1_0.html#IDToken

    if not jwk:
        header = jwt.get_unverified_header(id_token)
        if not autoconfig:
            autoconfig = openid_connect_discover(issuer)
        jwks = _cache_get(autoconfig['jwks_uri'])
        for jwk in jwks['keys']:
            if jwk['kid'] == header['kid']:
                break
    if not jwk:
        raise Exception('Failed to get public key for {}'.format(issuer))

    e = int(codecs.encode(base64url_decode(jwk['e']), 'hex'), 16)
    n = int(codecs.encode(base64url_decode(jwk['n']), 'hex'), 16)
    public_key = RSAPublicNumbers(e, n).public_key(backend=default_backend())
    pem = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo)
    d = jwt.decode(id_token, key=pem, algorithms=jwk['alg'],
                   audience=client_id, issuer=issuer)
    return d
    def _unpack(cls, token):
        if isinstance(token, (str, unicode)):
            token = token.encode('utf-8')

        try:
            signing_input, crypto_segment = token.rsplit(b'.', 1)
            header_segment, payload_segment = signing_input.split(b'.', 1)
        except ValueError:
            raise DecodeError('Not enough segments')

        try:
            header_data = base64url_decode(header_segment)
        except (TypeError, binascii.Error):
            raise DecodeError('Invalid header padding')

        try:
            header = json.loads(header_data.decode('utf-8'))
        except ValueError as e:
            raise DecodeError('Invalid header string: %s' % e)

        if not isinstance(header, Mapping):
            raise DecodeError('Invalid header string: must be a json object')

        try:
            payload_data = base64url_decode(payload_segment)
        except (TypeError, binascii.Error):
            raise DecodeError('Invalid payload padding')

        try:
            payload = json.loads(payload_data.decode('utf-8'))
        except ValueError as e:
            raise DecodeError('Invalid payload string: %s' % e)

        try:
            signature = base64url_decode(crypto_segment)
        except (TypeError, binascii.Error):
            raise DecodeError('Invalid crypto padding')

        return (header, payload, signature, signing_input)
示例#27
0
def dcos_adminrouter(b, opts):
    b.cluster_id()

    # Require the IAM to already be up and running. The IAM contains logic for
    # achieving consensus about a key pair, and exposes the public key
    # information via its JWKS endpoint. Talk directly to the local IAM instance
    # which is reachable via the local network interface.
    r = requests.get('http://127.0.0.1:8101/acs/api/v1/auth/jwks')

    if r.status_code != 200:
        log.info('JWKS retrieval failed. Got %s with body: %s', r, r.text)
        sys.exit(1)

    jwks = r.json()

    # The first key in the JSON Web Key Set corresponds to the current private
    # key used for signing authentiction tokens.
    key = jwks['keys'][0]

    exponent_bytes = base64url_decode(key['e'].encode('ascii'))
    exponent_int = bytes_to_number(exponent_bytes)
    modulus_bytes = base64url_decode(key['n'].encode('ascii'))
    modulus_int = bytes_to_number(modulus_bytes)
    # Generate a `cryptography` public key object instance from these numbers.
    public_numbers = rsa.RSAPublicNumbers(n=modulus_int, e=exponent_int)
    public_key = public_numbers.public_key(
        backend=cryptography.hazmat.backends.default_backend())

    # Serialize public key into the OpenSSL PEM public key format RFC 5280).
    pubkey_pem_bytes = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo)

    rundir = utils.dcos_run_path / 'dcos-adminrouter'
    rundir.mkdir(parents=True, exist_ok=True)
    pubkey_path = rundir / 'auth-token-verification-key'
    utils.write_public_file(pubkey_path, pubkey_pem_bytes)
    utils.chown(pubkey_path, user='******')
示例#28
0
    def get_by_token(self, token) -> typing.Union['Participant', None]:
        if token is None or len(token) == 0:
            return None
        try:
            token = base64url_decode(token)
            participant_id = signer.unsign(str(token, "utf-8"),
                                           max_age=86400 * 7)
        except BadSignature:
            return None
        except binascii.Error:
            return None

        participant, _ = Participant.objects.get_or_create(pk=participant_id)
        return participant
def is_admin(user_token):
    """
    :param str user_token: User's OAuth 2 token payload (containing "bearer" prefix).
    :return: True if the user is an admin.
    :rtype: bool
    """
    print('Provided token:', user_token)
    # get token without "bearer"
    token = user_token.split()[1]
    # take the middle part with payload
    token_payload_based = token.split('.')[1]
    token_payload_str = base64url_decode(token_payload_based.encode()).decode()
    token_payload = json.loads(token_payload_str)
    return 'console.admin' in token_payload['scope']
示例#30
0
文件: cli.py 项目: dcos/dcos
def dcos_adminrouter(b, opts):
    b.cluster_id()

    # Require the IAM to already be up and running. The IAM contains logic for
    # achieving consensus about a key pair, and exposes the public key
    # information via its JWKS endpoint. Talk directly to the local IAM instance
    # which is reachable via the local network interface.
    r = requests.get('http://127.0.0.1:8101/acs/api/v1/auth/jwks')

    if r.status_code != 200:
        log.info('JWKS retrieval failed. Got %s with body: %s', r, r.text)
        sys.exit(1)

    jwks = r.json()

    # The first key in the JSON Web Key Set corresponds to the current private
    # key used for signing authentiction tokens.
    key = jwks['keys'][0]

    exponent_bytes = base64url_decode(key['e'].encode('ascii'))
    exponent_int = bytes_to_number(exponent_bytes)
    modulus_bytes = base64url_decode(key['n'].encode('ascii'))
    modulus_int = bytes_to_number(modulus_bytes)
    # Generate a `cryptography` public key object instance from these numbers.
    public_numbers = rsa.RSAPublicNumbers(n=modulus_int, e=exponent_int)
    public_key = public_numbers.public_key(
        backend=cryptography.hazmat.backends.default_backend())

    # Serialize public key into the OpenSSL PEM public key format RFC 5280).
    pubkey_pem_bytes = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo)

    os.makedirs('/run/dcos/dcos-adminrouter', exist_ok=True)
    pubkey_path = '/run/dcos/dcos-adminrouter/auth-token-verification-key'
    _write_file_bytes(pubkey_path, pubkey_pem_bytes, 0o644)
    shutil.chown(pubkey_path, user='******')
示例#31
0
    def test_authtoken_rs256_anatomy(self):
        token = self.test_privkey_login_succeeds()

        header_bytes, payload_bytes, signature_bytes = [
            base64url_decode(_.encode('ascii')) for _ in token.split(".")
        ]

        assert b'typ' in header_bytes
        header_dict = json.loads(header_bytes.decode('ascii'))

        assert header_dict['alg'] == "RS256"
        assert header_dict['typ'] == "JWT"
        payload_dict = json.loads(payload_bytes.decode('ascii'))

        assert 'exp' in payload_dict
        assert 'uid' in payload_dict
        assert payload_dict['uid'] == self.service1_uid
示例#32
0
    def test_encode_headers_parameter_adds_headers(self, jws, payload):
        headers = {'testheader': True}
        token = jws.encode(payload, 'secret', headers=headers)

        if not isinstance(token, string_types):
            token = token.decode()

        header = token[0:token.index('.')].encode()
        header = base64url_decode(header)

        if not isinstance(header, text_type):
            header = header.decode()

        header_obj = json.loads(header)

        assert 'testheader' in header_obj
        assert header_obj['testheader'] == headers['testheader']
示例#33
0
    def test_encode_headers_parameter_adds_headers(self, jws, payload):
        headers = {"testheader": True}
        token = jws.encode(payload, "secret", headers=headers)

        if not isinstance(token, string_types):
            token = token.decode()

        header = token[0:token.index(".")].encode()
        header = base64url_decode(header)

        if not isinstance(header, text_type):
            header = header.decode()

        header_obj = json.loads(header)

        assert "testheader" in header_obj
        assert header_obj["testheader"] == headers["testheader"]
示例#34
0
    def test_hmac_verify_should_return_true_for_test_vector(self):
        signing_input = ensure_bytes(
            'eyJhbGciOiJIUzI1NiIsImtpZCI6IjAxOGMwYWU1LTRkOWItNDcxYi1iZmQ2LWVlZ'
            'jMxNGJjNzAzNyJ9.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ'
            '29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIG'
            'lmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmc'
            'gd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4'
        )

        signature = base64url_decode(ensure_bytes(
            's0h6KThzkfBBBkLspW1h84VsJZFTsPPqMDA7g1Md7p0'
        ))

        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
        key = algo.prepare_key(load_hmac_key())

        result = algo.verify(signing_input, key, signature)
        assert result
示例#35
0
文件: conftest.py 项目: lloesche/dcos
def forged_user_header(jwt_generator):
    """Return JWT token with a forged UID claim"""
    token = jwt_generator(uid='bozydar')

    # Decode token:
    header_bytes, payload_bytes, signature_bytes = [
        base64url_decode(_.encode('ascii')) for _ in token.split(".")]
    payload_dict = json.loads(payload_bytes.decode('ascii'))

    # Rewrite uid and invert token decode procedure.
    payload_dict['uid'] = 'fafok'
    payload_bytes = json.dumps(payload_dict).encode('utf-8')
    forged_token = '.'.join(
        base64url_encode(_).decode('ascii') for _ in (
            header_bytes, payload_bytes, signature_bytes)
        )

    header = {'Authorization': 'token={}'.format(forged_token)}
    return header
示例#36
0
def forged_user_header(jwt_generator):
    """Return JWT token with a forged UID claim"""
    token = jwt_generator(uid='bozydar')

    # Decode token:
    header_bytes, payload_bytes, signature_bytes = [
        base64url_decode(_.encode('ascii')) for _ in token.split(".")
    ]
    payload_dict = json.loads(payload_bytes.decode('ascii'))

    # Rewrite uid and invert token decode procedure.
    payload_dict['uid'] = 'fafok'
    payload_bytes = json.dumps(payload_dict).encode('utf-8')
    forged_token = '.'.join(
        base64url_encode(_).decode('ascii')
        for _ in (header_bytes, payload_bytes, signature_bytes))

    header = {'Authorization': 'token={}'.format(forged_token)}
    return header
示例#37
0
    def _validate(self):
        if not self._signatures:
            return

        payload_str = self._payload
        for signature in self._signatures:
            bytes_to_verify = "{0}.{1}".format(signature["protected"],
                                               base64url_encode(payload_str))
            signer = SIGNER_ALGS[signature["header"]["alg"]]
            key = keyrep(signature["header"]["jwk"])
            gk = key.get_key()
            sig = base64url_decode(signature["signature"].encode("utf-8"))

            try:
                verified = signer.verify(bytes_to_verify, sig, gk)
            except BadSignature:
                raise InvalidSchema1Signature()

            if not verified:
                raise InvalidSchema1Signature()
示例#38
0
    def test_authtoken_rs256_anatomy(self):
        url = Url('/auth/login')
        credentials = {'uid': self.user1_uid, 'password': self.user1_password}
        r = requests.post(url, json=credentials)
        assert r.status_code == 200
        token = r.json()['token']

        header_bytes, payload_bytes, signature_bytes = [
            base64url_decode(_.encode('ascii')) for _ in token.split(".")
        ]

        # Make sure the header is valid JSON.
        header_dict = json.loads(header_bytes.decode('ascii'))

        assert header_dict['typ'] == "JWT"
        assert header_dict['alg'] == "RS256"

        # Make sure that the payload section is valid JSON.
        payload_dict = json.loads(payload_bytes.decode('ascii'))
        return token, payload_dict
示例#39
0
    def _validate(self):
        if not self._signatures:
            return

        payload_str = self._payload
        for signature in self._signatures:
            bytes_to_verify = '{0}.{1}'.format(signature['protected'],
                                               base64url_encode(payload_str))
            signer = SIGNER_ALGS[signature['header']['alg']]
            key = keyrep(signature['header']['jwk'])
            gk = key.get_key()
            sig = base64url_decode(signature['signature'].encode('utf-8'))

            try:
                verified = signer.verify(bytes_to_verify, sig, gk)
            except BadSignature:
                raise InvalidSchema1Signature()

            if not verified:
                raise InvalidSchema1Signature()
示例#40
0
    def test_custom_json_encoder(self, jws, payload):
        class CustomJSONEncoder(json.JSONEncoder):
            def default(self, o):
                if isinstance(o, Decimal):
                    return "it worked"
                return super(CustomJSONEncoder, self).default(o)

        data = {"some_decimal": Decimal("2.2")}

        with pytest.raises(TypeError):
            jws.encode(payload, "secret", headers=data)

        token = jws.encode(payload,
                           "secret",
                           headers=data,
                           json_encoder=CustomJSONEncoder)

        header = force_bytes(force_unicode(token).split(".")[0])
        header = json.loads(force_unicode(base64url_decode(header)))

        assert "some_decimal" in header
        assert header["some_decimal"] == "it worked"
    def user_data(self, access_token, *args, **kwargs):
        response = kwargs.get('response')

        # str() to fix a bug in Python's base64 https://stackoverflow.com/a/2230623/161278
        id_token = str(response.get('id_token'))

        jwt_header_json = base64url_decode(id_token.split('.', 1)[0])

        # Decode the JWT header as JSON dict
        jwt_header = json.loads(jwt_header_json)
        key = self._get_public_key(jwt_header['kid'])  # `kid` is short for key id

        try:
            # Retrieve certificate for key_id
            return jwt_decode(
                id_token,
                key=key,
                algorithms=jwt_header['alg'],  # algorithm = 'RS256'
                audience=self.setting('KEY'),
                leeway=self.setting('JWT_LEEWAY', default=0),
            )
        except (DecodeError, ExpiredSignature) as error:
            raise AuthTokenError(self, error)
示例#42
0
        def decode_value(val):
            if hasattr(int, 'from_bytes'):
                int_from_bytes = int.from_bytes
            else:
                def int_from_bytes(data, byteorder, signed=False):
                    assert byteorder == 'big'
                    assert not signed

                    if len(data) % 4 != 0:
                        data = (b'\x00' * (4 - (len(data) % 4))) + data

                    result = 0

                    while len(data) > 0:
                        digit, = struct.unpack('>I', data[:4])
                        result = (result << 32) + digit
                        data = data[4:]
                    return result

            if isinstance(val, string_types):
                val = val.encode('utf-8')
            decoded = base64url_decode(val)
            return int_from_bytes(decoded, 'big')
示例#43
0
    def test_custom_json_encoder(self, jws, payload):

        class CustomJSONEncoder(json.JSONEncoder):

            def default(self, o):
                if isinstance(o, Decimal):
                    return 'it worked'
                return super(CustomJSONEncoder, self).default(o)

        data = {
            'some_decimal': Decimal('2.2')
        }

        with pytest.raises(TypeError):
            jws.encode(payload, 'secret', headers=data)

        token = jws.encode(payload, 'secret', headers=data,
                           json_encoder=CustomJSONEncoder)

        header = ensure_bytes(ensure_unicode(token).split('.')[0])
        header = json.loads(ensure_unicode(base64url_decode(header)))

        assert 'some_decimal' in header
        assert header['some_decimal'] == 'it worked'
示例#44
0
def load_hmac_key():
    with open(os.path.join(BASE_PATH, 'jwk_hmac.json'), 'r') as infile:
        keyobj = json.load(infile)

    return base64url_decode(ensure_bytes(keyobj['k']))
示例#45
0
def decode_value(val):
    decoded = base64url_decode(ensure_bytes(val))
    return int_from_bytes(decoded, 'big')