Example #1
0
def test_pack_jwt():
    _jwt = JWT(**{"alg": "none", "cty": "jwt"})
    jwt = _jwt.pack(parts=[{"iss": "joe", "exp": 1300819380,
                            "http://example.com/is_root": True}, ""])

    p = jwt.split(b'.')
    assert len(p) == 3
Example #2
0
def client_id_from_id_token(id_token):
    """
    Extracts the client id from a JSON Web Token (JWT).
    Returns a string or None.
    """
    payload = JWT().unpack(id_token).payload()
    return payload.get('aud', None)
Example #3
0
    def wrapper(request, *args, **kwargs):

        if request.user.is_authenticated:
            try:
                vmi = request.user.social_auth.filter(
                    provider='verifymyidentity-openidconnect')[0]
                extra_data = vmi.extra_data
                if 'id_token' in vmi.extra_data.keys():
                    id_token = extra_data.get('id_token')
                    parsed_id_token = JWT().unpack(id_token)
                    parsed_id_token = parsed_id_token.payload()
            except Exception:
                id_token = "No ID token."
                parsed_id_token = {
                    'sub': '',
                    'ial': '1',
                    "note": "No ID token for this user"
                }
            if parsed_id_token['ial'] not in ('2', '3'):
                msg = _(
                    "%s %s was defined access due to insufficient identity assurance  level (IAL). Subject=%s"
                    "" % (request.user.first_name, request.user.last_name,
                          parsed_id_token['sub']))
                logger.info(msg)
                response_string = _(
                    """Your identity assurance level (IAL) of 1 is insufficient for this action."""
                )
                return HttpResponseForbidden(response_string)

        return func(request, *args, **kwargs)
Example #4
0
    def __get_kid_from_api_response_headers(headers):
        """
        Gets `kid` property from a JWT token within the headers of a
        LaunchKey API response.
        :param headers: Response headers
        :return: string of the `kid`
        :raises launchkey.exceptions.UnexpectedAPIResponse: if unable to unpack
            the JWT or if the JWT header does not exist
        :raises launchkey.exceptions.JWTValidationFailure: if `kid` is missing
            or invalid
        """
        try:
            jwt = headers.get("X-IOV-JWT")
            jwt_headers = JWT().unpack(jwt).headers

        except (BadSyntax, IndexError, ValueError):
            raise UnexpectedAPIResponse("JWT was missing or malformed in API "
                                        "response.")

        kid = jwt_headers.get("kid")

        if not isinstance(kid, six.string_types):
            raise JWTValidationFailure("`kid` header in JWT was missing or"
                                       " invalid.")

        return kid
Example #5
0
    def test_client_secret_jwt(self, client):
        client.token_endpoint = "https://example.com/token"
        client.provider_info = {
            'issuer': 'https://example.com/',
            'token_endpoint': "https://example.com/token"
        }

        csj = ClientSecretJWT(client)
        cis = AccessTokenRequest()

        csj.construct(cis, algorithm="HS256", authn_endpoint='userinfo')
        assert cis["client_assertion_type"] == JWT_BEARER
        assert "client_assertion" in cis
        cas = cis["client_assertion"]
        _jwt = JWT().unpack(cas)
        jso = _jwt.payload()
        assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
        assert _jwt.headers == {'alg': 'HS256'}

        _rj = JWS()
        info = _rj.verify_compact(
            cas, [SYMKey(k=b64e(as_bytes(client.client_secret)))])

        assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
        assert info['aud'] == [client.provider_info['issuer']]
def client_id_from_id_token(id_token):
    """
    Extracts the client id from a JSON Web Token (JWT).
    Returns a string or None.
    """
    payload = JWT().unpack(id_token).payload()
    return payload.get('aud', None)
Example #7
0
 def test_construct(self, client):
     _key = rsa_load(os.path.join(BASE_PATH, "data/keys/rsa.key"))
     kc_rsa = KeyBundle([{
         "key": _key,
         "kty": "RSA",
         "use": "ver"
     }, {
         "key": _key,
         "kty": "RSA",
         "use": "sig"
     }])
     client.keyjar[""] = kc_rsa
     client.token_endpoint = "https://example.com/token"
     client.provider_info = {
         'issuer': 'https://example.com/',
         'token_endpoint': "https://example.com/token"
     }
     cis = AccessTokenRequest()
     pkj = PrivateKeyJWT(client)
     http_args = pkj.construct(cis,
                               algorithm="RS256",
                               authn_endpoint='token')
     assert http_args == {}
     cas = cis["client_assertion"]
     _jwt = JWT().unpack(cas)
     jso = _jwt.payload()
     assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
     assert _jwt.headers == {'alg': 'RS256'}
     assert jso['aud'] == [client.provider_info['token_endpoint']]
Example #8
0
def callback(request):

    response = OrderedDict()
    if 'error' in request.GET:
        return render(request, "access-denied.html", {"error": request.GET.get("error")})
    oas = OAuth2Session(request.session['client_id'],
                        redirect_uri=request.session['redirect_uri'])
    host = settings.HOSTNAME_URL
    if not(host.startswith("http://") or host.startswith("https://")):
        host = "https://%s" % (host)
    auth_uri = host + request.get_full_path()
    token_uri = host + reverse('oauth2_provider:token')
    try:
        token = oas.fetch_token(token_uri,
                                client_secret=get_client_secret(),
                                authorization_response=auth_uri)
    except MissingTokenError:
        logmsg = "Failed to get token from %s" % (request.session['token_uri'])
        logger.error(logmsg)
        return JsonResponse({'error': 'Failed to get token from',
                             'code': 'MissingTokenError',
                             'help': 'Try authorizing again.'}, status=500)
    request.session['token'] = token
    response['token_response'] = OrderedDict()

    for k, v in token.items():
        if k != "scope":
            response['token_response'][k] = v
        else:
            response['token_response'][k] = ' '.join(v)
    response['test_page'] = host + reverse('testclient_home')
    parsed_id_token = JWT().unpack(response['token_response']['id_token'])
    parsed_id_token = parsed_id_token.payload()
    response['id_token_payload'] = parsed_id_token
    return success(request, response)
Example #9
0
def create_or_update_org(backend, user, response, *args, **kwargs):
    if backend.name == 'verifymyidentity-openidconnect':
        if 'id_token' in response.keys():
            id_token = response.get('id_token')
            parsed_id_token = JWT().unpack(id_token)
            payload = parsed_id_token.payload()
            org_slugs = []
            if 'organization_agent' in payload:
                for organization in payload['organization_agent']:
                    org, g_o_c = Organization.objects.get_or_create(
                        slug=organization['slug'])
                    org_slugs.append(organization['slug'])
                    org.name = organization['name']
                    org.sub = organization['sub']
                    org.website = organization['website']
                    org.phone = organization['phone_number']
                    org.picture_url = organization.get('picture', None)
                    org.agents.add(user)  # Make sure the user is an org agent.
                    org.save()

        # remove an agent from organization if they have been removed.
        all_orgs = Organization.objects.all()
        for o in all_orgs:
            if o.slug not in org_slugs:
                o.agents.remove(user)
                o.save()
    def test_access_token_contains_nonce(self):
        """
        If present in the Authentication Request, Authorization Servers MUST
        include a nonce Claim in the ID Token with the Claim Value being the
        nonce value sent in the Authentication Request.
        If the client does not supply a nonce parameter, it SHOULD not be
        included in the `id_token`.

        See http://openid.net/specs/openid-connect-core-1_0.html#IDToken
        """
        code = self._create_code()

        post_data = self._auth_code_post_data(code=code.code)

        response = self._post_request(post_data)

        response_dic = json.loads(response.content.decode('utf-8'))
        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertEqual(id_token.get('nonce'), FAKE_NONCE)

        # Client does not supply a nonce parameter.
        code.nonce = ''
        code.save()

        response = self._post_request(post_data)
        response_dic = json.loads(response.content.decode('utf-8'))

        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertEqual(id_token.get('nonce'), None)
Example #11
0
def test_pack_jwt():
    _jwt = JWT(**{"alg": "none", "cty": "jwt"})
    jwt = _jwt.pack(parts=[{"iss": "joe", "exp": 1300819380,
                            "http://example.com/is_root": True}, ""])

    p = jwt.split('.')
    assert len(p) == 3
Example #12
0
def test_unpack_pack():
    _jwt = JWT(**{"alg": "none"})
    payload = {"iss": "joe", "exp": 1300819380,
               "http://example.com/is_root": True}
    jwt = _jwt.pack(parts=[payload, ""])
    repacked = JWT().unpack(jwt).pack()

    assert jwt == repacked
Example #13
0
def verify_id_token(instance, check_hash=False, **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in TOKEN_VERIFY_ARGS:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = str(instance["id_token"])

    # It can be encrypted, so try to decrypt first
    _jwe = JWE_factory(_jws)
    if _jwe is not None:
        try:
            _jws = _jwe.decrypt(keys=kwargs["keyjar"].get_decrypt_key())
        except JWEException as err:
            raise VerificationError("Could not decrypt id_token", err)
    _packer = JWT()
    _body = _packer.unpack(_jws).payload()

    if "keyjar" in kwargs:
        try:
            if _body["iss"] not in kwargs["keyjar"]:
                raise ValueError("Unknown issuer")
        except KeyError:
            raise MissingRequiredAttribute("iss")

    if _jwe is not None:
        # Use the original encrypted token to set correct headers
        idt = IdToken().from_jwt(str(instance["id_token"]), **args)
    else:
        idt = IdToken().from_jwt(_jws, **args)
    if not idt.verify(**kwargs):
        raise VerificationError("Could not verify id_token", idt)

    if check_hash:
        _alg = idt.jws_header["alg"]
        if _alg != "none":
            hfunc = "HS" + _alg[-3:]
        else:
            # This is allowed only for `code` and it needs to be checked by a Client
            hfunc = None

        if "access_token" in instance and hfunc is not None:
            if "at_hash" not in idt:
                raise MissingRequiredAttribute("Missing at_hash property", idt)
            if idt["at_hash"] != jws.left_hash(instance["access_token"],
                                               hfunc):
                raise AtHashError("Failed to verify access_token hash", idt)

        if "code" in instance and hfunc is not None:
            if "c_hash" not in idt:
                raise MissingRequiredAttribute("Missing c_hash property", idt)
            if idt["c_hash"] != jws.left_hash(instance["code"], hfunc):
                raise CHashError("Failed to verify code hash", idt)

    return idt
Example #14
0
def get_username(strategy, details, backend, user, response, *args, **kwargs):
    # The subject id is the username.
    if backend.name == 'verifymyidentity-openidconnect':
        if 'id_token' in response.keys():
            id_token = response.get('id_token')
            parsed_id_token = JWT().unpack(id_token)
            payload = parsed_id_token.payload()
            return {'username': payload['sub']}
    return
Example #15
0
def test_unpack_str():
    _jwt = JWT(**{"alg": "none"})
    payload = {"iss": "joe", "exp": 1300819380,
               "http://example.com/is_root": True}
    jwt = _jwt.pack(parts=[payload, ""])

    _jwt2 = JWT().unpack(jwt)
    assert _jwt2
    out_payload = _jwt2.payload()
Example #16
0
def verify_id_token(instance, check_hash=False, **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in ["key", "keyjar", "algs", "sender"]:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = str(instance["id_token"])

    # It can be encrypted, so try to decrypt first
    _jwe = JWE_factory(_jws)
    if _jwe is not None:
        try:
            _jws = _jwe.decrypt(keys=kwargs['keyjar'].get_decrypt_key())
        except JWEException as err:
            raise VerificationError("Could not decrypt id_token", err)
    _packer = JWT()
    _body = _packer.unpack(_jws).payload()

    if 'keyjar' in kwargs:
        try:
            if _body['iss'] not in kwargs['keyjar']:
                raise ValueError('Unknown issuer')
        except KeyError:
            raise MissingRequiredAttribute('iss')

    if _jwe is not None:
        # Use the original encrypted token to set correct headers
        idt = IdToken().from_jwt(str(instance['id_token']), **args)
    else:
        idt = IdToken().from_jwt(_jws, **args)
    if not idt.verify(**kwargs):
        raise VerificationError("Could not verify id_token", idt)

    if check_hash:
        _alg = idt.jws_header["alg"]
        # What if _alg == 'none'

        hfunc = "HS" + _alg[-3:]

        if "access_token" in instance:
            if "at_hash" not in idt:
                raise MissingRequiredAttribute("Missing at_hash property", idt)
            if idt["at_hash"] != jws.left_hash(instance["access_token"],
                                               hfunc):
                raise AtHashError("Failed to verify access_token hash", idt)

        if "code" in instance:
            if "c_hash" not in idt:
                raise MissingRequiredAttribute("Missing c_hash property", idt)
            if idt["c_hash"] != jws.left_hash(instance["code"], hfunc):
                raise CHashError("Failed to verify code hash", idt)

    return idt
Example #17
0
def save_profile(backend, user, response, *args, **kwargs):
    if backend.name == 'verifymyidentity-openidconnect':

        profile, g_o_c = UserProfile.objects.get_or_create(user=user)

        if 'id_token' in response.keys():
            id_token = response.get('id_token')
            parsed_id_token = JWT().unpack(id_token)
            payload = parsed_id_token.payload()
            if 'given_name' in payload:
                profile.user.first_name = payload['given_name']

            if 'family_name' in payload:
                profile.user.last_name = payload['family_name']

            if 'sub' in payload:
                profile.subject = payload['sub']

            if 'nickname' in payload:
                profile.nickname = payload['nickname']

            if 'phone_number' in payload:
                profile.mobile_phone_number = payload['phone_number']

            if 'birthdate' in payload:
                if payload['birthdate'] not in ("None", ""):
                    profile.birth_date = payload['birthdate']

            if 'gender' in payload:
                profile.gender = payload['gender']

            if 'email_verified' in payload:
                profile.email_verified = payload['email_verified']

            if 'gender_identity' in payload:
                profile.gender_identity = payload['gender_identity']

            if 'middle_name' in payload:
                profile.middle_name = payload['middle_name']

            if 'phone_verified' in payload:
                profile.phone_verified = payload['phone_verified']

            if 'ial' in payload:
                profile.identity_assurance_level = payload['ial']

            if ('picture' in payload and 'None' not in payload['picture']
                    and 'no-img' not in payload['picture']):
                profile.picture_url = payload['picture']

            profile.most_recent_id_token_payload = json.dumps(payload,
                                                              indent=4)

        profile.user.save()
        profile.save()
Example #18
0
def verify_id_token(instance, check_hash=False, **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in ["key", "keyjar", "algs", "sender"]:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = str(instance["id_token"])

    # It can be encrypted, so try to decrypt first
    _jwe = JWE_factory(_jws)
    if _jwe is not None:
        try:
            _jws = _jwe.decrypt(keys=kwargs['keyjar'].get_decrypt_key())
        except JWEException as err:
            raise VerificationError("Could not decrypt id_token", err)
    _packer = JWT()
    _body = _packer.unpack(_jws).payload()

    if 'keyjar' in kwargs:
        try:
            if _body['iss'] not in kwargs['keyjar']:
                raise ValueError('Unknown issuer')
        except KeyError:
            raise MissingRequiredAttribute('iss')

    if _jwe is not None:
        # Use the original encrypted token to set correct headers
        idt = IdToken().from_jwt(str(instance['id_token']), **args)
    else:
        idt = IdToken().from_jwt(_jws, **args)
    if not idt.verify(**kwargs):
        raise VerificationError("Could not verify id_token", idt)

    if check_hash:
        _alg = idt.jws_header["alg"]
        # What if _alg == 'none'

        hfunc = "HS" + _alg[-3:]

        if "access_token" in instance:
            if "at_hash" not in idt:
                raise MissingRequiredAttribute("Missing at_hash property", idt)
            if idt["at_hash"] != jws.left_hash(instance["access_token"], hfunc):
                raise AtHashError("Failed to verify access_token hash", idt)

        if "code" in instance:
            if "c_hash" not in idt:
                raise MissingRequiredAttribute("Missing c_hash property", idt)
            if idt["c_hash"] != jws.left_hash(instance["code"], hfunc):
                raise CHashError("Failed to verify code hash", idt)

    return idt
Example #19
0
def test_unpack_pack():
    _jwt = JWT(**{"alg": "none"})
    payload = {
        "iss": "joe",
        "exp": 1300819380,
        "http://example.com/is_root": True
    }
    jwt = _jwt.pack(parts=[payload, ""])
    repacked = JWT().unpack(jwt).pack()

    assert jwt == repacked
Example #20
0
def jwt_payload(request):
    if 'jwt' not in request.GET:
        return JsonResponse({"error": "you just supply a jwt as a GET parmeter."})
    myjwt = request.GET.get("jwt")

    try:
        parsed_id_token = JWT().unpack(myjwt)
        parsed_id_token = parsed_id_token.payload()
    except Exception:
        parsed_id_token = {
            "error": "you just supply a valid jwt as a GET parmeter."}
    return JsonResponse(parsed_id_token)
Example #21
0
def client_id_from_id_token(id_token):
    """
    Extracts the client id from a JSON Web Token (JWT).
    Returns a string or None.
    """
    payload = JWT().unpack(id_token).payload()
    aud = payload.get('aud', None)
    if aud is None:
        return None
    if isinstance(aud, list):
        return aud[0]
    return aud
Example #22
0
def client_id_from_id_token(id_token):
    """
    Extracts the client id from a JSON Web Token (JWT).
    Returns a string or None.
    """
    payload = JWT().unpack(id_token).payload()
    aud = payload.get('aud', None)
    if aud is None:
        return None
    if isinstance(aud, list):
        return aud[0]
    return aud
    def test_id_token_contains_at_hash(self):
        """
        If access_token is included, the id_token SHOULD contain an at_hash.
        """
        code = self._create_code()

        post_data = self._auth_code_post_data(code=code.code)

        response = self._post_request(post_data)

        response_dic = json.loads(response.content.decode('utf-8'))
        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertTrue(id_token.get('at_hash'))
    def test_id_token_contains_at_hash(self):
        """
        If access_token is included, the id_token SHOULD contain an at_hash.
        """
        code = self._create_code()

        post_data = self._auth_code_post_data(code=code.code)

        response = self._post_request(post_data)

        response_dic = json.loads(response.content.decode('utf-8'))
        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertTrue(id_token.get('at_hash'))
    def test_custom_sub_generator(self):
        """
        Test custom function for setting OIDC_IDTOKEN_SUB_GENERATOR.
        """
        code = self._create_code()

        post_data = self._auth_code_post_data(code=code.code)

        response = self._post_request(post_data)

        response_dic = json.loads(response.content.decode('utf-8'))
        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertEqual(id_token.get('sub'), self.user.email)
    def test_custom_sub_generator(self):
        """
        Test custom function for setting OIDC_IDTOKEN_SUB_GENERATOR.
        """
        code = self._create_code()

        post_data = self._auth_code_post_data(code=code.code)

        response = self._post_request(post_data)

        response_dic = json.loads(response.content.decode('utf-8'))
        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertEqual(id_token.get('sub'), self.user.email)
    def test_additional_idtoken_processing_hook(self):
        """
        Test custom function for setting OIDC_IDTOKEN_PROCESSING_HOOK.
        """
        code = self._create_code()

        post_data = self._auth_code_post_data(code=code.code)

        response = self._post_request(post_data)

        response_dic = json.loads(response.content.decode('utf-8'))
        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertEqual(id_token.get('test_idtoken_processing_hook'), FAKE_RANDOM_STRING)
 def unpack_jwt(jwt: str, keys: list):
     """
     Unpacks a signed jwt question
     :type keys: list[str]
     :rtype: dict[str, str]
     :param jwt: A signed jwt containing the question (the idp, id and redirect_endpoint)
     :param keys: A list of keys to use when verifying the signature
     :return: The unpacked jwt
     """
     JWTHandler._verify_jwt(jwt, keys)
     _jwt = JWT().unpack(jwt)
     jso = _jwt.payload()
     if "sp" not in jso or "idp" not in jso or "ticket" not in jso:
         return None
     return jso
Example #29
0
def save_profile(backend, user, response, *args, **kwargs):
    # make sure there is a UserProfile object for the given User
    profile, created = UserProfile.objects.get_or_create(user=user)
    if backend.name == 'verifymyidentity-openidconnect':

        # Save the id_token 'sub' to the UserProfile.subject
        if 'id_token' in response.keys():
            id_token = response.get('id_token')
            id_token_payload = JWT().unpack(id_token).payload()
            profile.verifying_agent_email = id_token_payload.get(
                'verifying_agent_email')
            profile.save()
            logger.info('Verifying Agent Email set as %r from %r' %
                        (profile.verifying_agent_email,
                         id_token_payload.get("verifying_agent_email")))
    def test_additional_idtoken_processing_hook_one_element_in_list(self):
        """
        Test custom function for setting OIDC_IDTOKEN_PROCESSING_HOOK.
        """
        code = self._create_code()

        post_data = self._auth_code_post_data(code=code.code)

        response = self._post_request(post_data)

        response_dic = json.loads(response.content.decode('utf-8'))
        id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload()

        self.assertEqual(id_token.get('test_idtoken_processing_hook'), FAKE_RANDOM_STRING)
        self.assertEqual(id_token.get('test_idtoken_processing_hook_user_email'), self.user.email)
 def unpack_jwt(jwt: str, keys: list):
     """
     Unpacks a signed jwt question
     :type keys: list[str]
     :rtype: dict[str, str]
     :param jwt: A signed jwt containing the question (the idp, id and redirect_endpoint)
     :param keys: A list of keys to use when verifying the signature
     :return: The unpacked jwt
     """
     JWTHandler._verify_jwt(jwt, keys)
     _jwt = JWT().unpack(jwt)
     jso = _jwt.payload()
     if "sp" not in jso or "idp" not in jso or "ticket" not in jso:
         return None
     return jso
Example #32
0
def test_pack_unpack():
    _jwt = JWT(**{"alg": "none"})
    payload = {"iss": "joe", "exp": 1300819380,
               "http://example.com/is_root": True}
    jwt = _jwt.pack(parts=[payload, ""])

    _jwt2 = JWT().unpack(jwt)

    assert _jwt2
    out_payload = _jwt2.payload()
    assert _eq(out_payload.keys(), ["iss", "exp", "http://example.com/is_root"])
    assert out_payload["iss"] == payload["iss"]
    assert out_payload["exp"] == payload["exp"]
    assert out_payload["http://example.com/is_root"] == payload[
        "http://example.com/is_root"]
Example #33
0
def authenticated_home(request):
    name = _('Authenticated Home')
    if request.user.is_authenticated:

        # Get the ID Token and parse it.
        try:
            vmi = request.user.social_auth.filter(
                provider='verifymyidentity-openidconnect')[0]
            extra_data = vmi.extra_data
            if 'id_token' in vmi.extra_data.keys():
                id_token = extra_data.get('id_token')
                parsed_id_token = JWT().unpack(id_token)
                parsed_id_token = parsed_id_token.payload()

        except Exception:
            id_token = "No ID token."
            parsed_id_token = {'sub': '', 'ial': '1'}

        hp, g_o_c = HIEProfile.objects.get_or_create(user=request.user)

        if parsed_id_token.get('ial') not in ('2', '3'):
            # redirect to get verified
            messages.warning(
                request, 'Your identity has not been verified. \
                             This must be completed prior to access to personal health information.'
            )

        try:
            profile = request.user.userprofile
        except Exception:
            profile = None

        # this is a GET
        context = {
            'name': name,
            'profile': profile,
            'hp': hp,
            'id_token': id_token,
            'id_token_payload': parsed_id_token
        }

        template = 'authenticated-home.html'
    else:
        name = ('home')
        context = {'name': name}
        template = 'index.html'

    return render(request, template, context)
    def validate_and_decode(self, token):
        """
        Check if a message sent by the tool is valid.

        From https://www.imsglobal.org/spec/security/v1p0/#using-oauth-2-0-client-credentials-grant:

        The authorization server decodes the JWT and MUST validate the values for the
        iss, sub, exp, aud and jti claims.
        """
        try:
            # Get KID from JWT header
            jwt = JWT().unpack(token)

            # Verify message signature
            message = JWS().verify_compact(token,
                                           keys=self._get_keyset(
                                               jwt.headers.get('kid')))

            # If message is valid, check expiration from JWT
            if 'exp' in message and message['exp'] < time.time():
                raise exceptions.TokenSignatureExpired()

            # TODO: Validate other JWT claims

            # Else returns decoded message
            return message

        except NoSuitableSigningKeys as err:
            raise exceptions.NoSuitableKeys() from err
        except BadSyntax as err:
            raise exceptions.MalformedJwtToken() from err
        except WrongNumberOfParts as err:
            raise exceptions.MalformedJwtToken() from err
Example #35
0
    def test_idtoken_at_hash(self):
        """
        Implicit client requesting `id_token` should not receive
        `at_hash` in `id_token`.
        """
        data = {
            'client_id': self.client_no_access.client_id,
            'redirect_uri': self.client_no_access.default_redirect_uri,
            'response_type': next(self.client_no_access.response_type_values()),
            'scope': 'openid email',
            'state': self.state,
            'nonce': self.nonce,
            'allow': 'Accept',
        }

        response = self._auth_request('post', data, is_user_authenticated=True)

        self.assertIn('id_token', response['Location'])

        # obtain `id_token` portion of Location
        components = urlsplit(response['Location'])
        fragment = parse_qs(components[4])
        id_token = JWT().unpack(fragment["id_token"][0].encode('utf-8')).payload()

        self.assertNotIn('at_hash', id_token)
Example #36
0
    def test_make_id_token(self):
        self.srv.keyjar["http://oic.example/idp"] = KC_RSA

        session = {"sub": "user0", "client_id": "http://oic.example/rp"}
        issuer = "http://oic.example/idp"
        code = "abcdefghijklmnop"
        _idt = self.srv.make_id_token(session,
                                      loa="2",
                                      issuer=issuer,
                                      code=code,
                                      access_token="access_token")

        algo = "RS256"
        ckey = self.srv.keyjar.get_signing_key(alg2keytype(algo), issuer)
        _signed_jwt = _idt.to_jwt(key=ckey, algorithm="RS256")

        idt = IdToken().from_jwt(_signed_jwt, keyjar=self.srv.keyjar)
        _jwt = JWT().unpack(_signed_jwt)

        lha = left_hash(code.encode("utf-8"),
                        func="HS" + _jwt.headers["alg"][-3:])
        assert lha == idt["c_hash"]

        atr = AccessTokenResponse(id_token=_signed_jwt,
                                  access_token="access_token",
                                  token_type="Bearer")
        atr["code"] = code
        assert atr.verify(keyjar=self.srv.keyjar)
Example #37
0
    def test_get_user_by_id_django_user_exists(self):
        settings.OIDC_AUTH = {'OIDC_AUDIENCES': ['client_id']}

        UserModel = get_user_model()
        existing_user = UserModel.objects.create(username='******')
        # No or incorrect KeycloakModel mapping of this user to the Keycloak UID

        token = {
            'sub': 'uid',
            'preferred_username': '******',
            'aud': ['client_id'],
        }

        request = MagicMock()
        request.session.get.return_value = JWT().pack([token], JWT_HEADERS)

        user = backend.get_user_by_id(request, token)

        self.assertNotEqual(user, existing_user)

        with self.assertRaises(UserModel.DoesNotExist):
            UserModel.objects.get(id=existing_user.id)

        self.assertEqual(user.username, 'username')
        self.assertEqual(user.keycloak.UID, 'uid')
Example #38
0
def get_id_token_payload(user):
    # Get the ID Token and parse it.
    try:
        vmi = user.social_auth.filter(provider='vmi')[0]
        extra_data = vmi.extra_data
        if 'id_token' in vmi.extra_data.keys():
            id_token = extra_data.get('id_token')
            parsed_id_token = JWT().unpack(id_token)
            parsed_id_token = parsed_id_token.payload()
        else:
            parsed_id_token = {'sub': '', 'ial': '1'}

    except Exception:
        parsed_id_token = {'sub': '', 'ial': '1'}

    return parsed_id_token
Example #39
0
    def test_get_user_by_id(self, mLoadRoles, mUserData):
        settings.OIDC_AUTH = {'OIDC_AUDIENCES': ['client_id']}

        token = {
            'sub': 'uid',
            'preferred_username': '******',
            'aud': ['client_id'],
            'realm_access': {
                'roles': ['one', 'two', 'three']
            }
        }

        request = MagicMock()
        request.session.get.return_value = JWT().pack([token], JWT_HEADERS)

        user = backend.get_user_by_id(request, token)

        self.assertEqual(user.username, 'username')
        self.assertEqual(user.keycloak.UID, 'uid')
        self.assertEqual(user.first_name, '')
        self.assertEqual(user.last_name, '')
        self.assertEqual(user.email, '')
        self.assertFalse(user.is_staff)
        self.assertFalse(user.is_superuser)

        expected = [call(user, ['one', 'two', 'three'])]
        self.assertEqual(mLoadRoles.mock_calls, expected)

        expected = [call(user, token)]
        self.assertEqual(mUserData.mock_calls, expected)
Example #40
0
def set_user_type(backend, user, response, *args, **kwargs):

    user_type = "M"
    up, g_o_c = UserProfile.objects.get_or_create(user=user)
    if backend.name == 'vmi':
        user_type = "M"
        up, g_o_c = UserProfile.objects.get_or_create(user=user)
        if 'id_token' in response.keys():
            id_token = response.get('id_token')
            parsed_id_token = JWT().unpack(id_token)
            payload = parsed_id_token.payload()
            if 'organization_agent' in payload:
                if len(payload['organization_agent']) > 0:
                    user_type = "O"
    up.user_type = user_type
    up.save()
Example #41
0
    def test_construct(self, client):
        _key = rsa_load(
            os.path.join(BASE_PATH, "data/keys/rsa.key"))
        kc_rsa = KeyBundle([{"key": _key, "kty": "RSA", "use": "ver"},
                            {"key": _key, "kty": "RSA", "use": "sig"}])
        client.keyjar[""] = kc_rsa
        client.token_endpoint = "https://example.com/token"

        cis = AccessTokenRequest()
        pkj = PrivateKeyJWT(client)
        http_args = pkj.construct(cis, algorithm="RS256")
        assert http_args == {}
        cas = cis["client_assertion"]
        _jwt = JWT().unpack(cas)
        jso = _jwt.payload()
        assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
        assert _jwt.headers == {'alg': 'RS256'}
Example #42
0
def map_user(request):
    if (request.authorization is not None):
        if (JWSig().unpack(request.authorization.params).valid()):
            username = JWT().unpack(request.authorization.params).payload()['preferred_username']
            #map username to userid
            user = DBSession.query(User).filter_by(name=username).first()
            return user
    return None
Example #43
0
def id_token_payload_json(request):

    try:
        vmi = request.user.social_auth.filter(
            provider='verifymyidentity-openidconnect')[0]
        extra_data = vmi.extra_data
        if 'id_token' in vmi.extra_data.keys():
            id_token = extra_data.get('id_token')
            parsed_id_token = JWT().unpack(id_token)
            parsed_id_token = parsed_id_token.payload()
    except Exception:
        id_token = "No ID token."
        parsed_id_token = {
            'sub': '',
            'ial': '1',
            "note": "No ID token for this user"
        }
    return JsonResponse(parsed_id_token)
Example #44
0
    def test_client_secret_jwt(self, client):
        client.token_endpoint = "https://example.com/token"

        csj = ClientSecretJWT(client)
        cis = AccessTokenRequest()

        http_args = csj.construct(cis, algorithm="HS256")
        assert cis["client_assertion_type"] == JWT_BEARER
        assert "client_assertion" in cis
        cas = cis["client_assertion"]
        _jwt = JWT().unpack(cas)
        jso = _jwt.payload()
        assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
        assert _jwt.headers == {'alg': 'HS256'}

        _rj = JWS()
        info = _rj.verify_compact(cas, [SYMKey(key=client.client_secret)])

        assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
    def test_construct_authz_req_with_request_object(self, tmpdir):
        path = tmpdir.strpath
        request_uri_args = {
            "local_dir": path,
            "base_path": "http://example.com/"
        }
        areq = self.client.construct_AuthorizationRequest(request_method="file",
                                                          **request_uri_args)
        p = urlparse(areq["request_uri"])
        local_path = os.path.join(path, p.path.lstrip("/"))
        with open(local_path) as f:
            data = f.read()
        jwt = JWT().unpack(data)
        payload = jwt.payload()

        assert payload["redirect_uri"] == "http://example.com/redirect"
        assert payload["client_id"] == CLIENT_ID
        assert "nonce" in payload

        os.remove(local_path)
Example #46
0
    def assert_registstration_req(self, request, sign_key_str):
        split_path = request.path_url.lstrip("/").split("/")
        assert len(split_path) == 2

        jwks = split_path[1]

        # Verify signature
        public_key = import_rsa_key(private_to_public_key(sign_key_str))
        sign_key = RSAKey().load_key(public_key)
        sign_key.use = "sig"
        _jw = jws.factory(jwks)
        _jw.verify_compact(jwks, [sign_key])

        # Verify JWT
        _jwt = JWT().unpack(jwks)
        consent_args = _jwt.payload()

        assert "attr" in consent_args
        assert "redirect_endpoint" in consent_args
        assert "id" in consent_args
def verify_poet_via_url(my_jws):

    # load the Signed JWT (JWS)
    my_jws = my_jws.rstrip().lstrip()
    signed_token = JWS(my_jws)

    # create aplain old JWT so we can fish out the 'iss'
    t = JWT()
    unpacked = t.unpack(token=my_jws)
    payload = unpacked.payload()
    if "iss" not in payload:
        print("Missing 'iss' claim in the JWS payload.")
        exit(1)
    else:
        iss = payload['iss']

    # Fetch the public key from iss

    url = "https://%s/.well-known/poet.jwk" % (iss)
    r = requests.get(url)

    if r.status_code != 200:
        print("The key could not be fetched.")
        exit(1)

    # load the JWK into an RSA Key structure
    rsak = RSAKey(**r.json())
    try:
        vt = signed_token.verify_compact(signed_token.msg, keys=[rsak])
        retval = vt
    except BadSignature:
        retval = {"error": "The signature did not match"}
    except NoSuitableSigningKeys:
        retval = {"error": str(sys.exc_info()[1])}
    except DeSerializationNotPossible:
        retval = {"error": str(sys.exc_info()[1])}
    except:
        retval = {"error": str(sys.exc_info())}
    return retval
def verify_signed_id_token(token, key=None, jwks=None):
    jwt = JWT().unpack(token)
    payload = jwt.payload()
    issuer = payload['iss']
    provider_keys = None

    if jwt.headers['alg'].startswith('HS') and not key:
        raise IDTokenVerificationError(
            'No symmetric key provided for signature using \'{}\' algorithm.'.format(
                jwt.headers['alg']))

    if key:
        provider_keys = _create_symmetric_key(issuer, key)
    elif jwks:
        provider_keys = _parse_provider_keys_from_jwks(issuer, jwks)
    elif jwt.headers['alg'] != 'none':  # don't fetch keys for unsigned JWT
        provider_keys = _fetch_provider_keys(issuer)

    try:
        return IdToken().from_jwt(token, keyjar=provider_keys).to_json()
    except (BadSignature, NoSuitableSigningKeys) as e:
        raise IDTokenVerificationError(
            'No key that could be used to verify the signature could be found.')
Example #49
0
    def test_client_secret_jwt(self, client):
        client.token_endpoint = "https://example.com/token"
        client.provider_info = {'issuer': 'https://example.com/',
                                'token_endpoint': "https://example.com/token"}

        csj = ClientSecretJWT(client)
        cis = AccessTokenRequest()

        csj.construct(cis, algorithm="HS256",
                      authn_endpoint='userinfo')
        assert cis["client_assertion_type"] == JWT_BEARER
        assert "client_assertion" in cis
        cas = cis["client_assertion"]
        _jwt = JWT().unpack(cas)
        jso = _jwt.payload()
        assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
        assert _jwt.headers == {'alg': 'HS256'}

        _rj = JWS()
        info = _rj.verify_compact(
            cas, [SYMKey(k=b64e(as_bytes(client.client_secret)))])

        assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
        assert info['aud'] == [client.provider_info['issuer']]
Example #50
0
    def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs):
        """
        Given a signed and/or encrypted JWT, verify its correctness and then
        create a class instance from the content.

        :param txt: The JWT
        :param key: keys that might be used to decrypt and/or verify the
            signature of the JWT
        :param verify: Whether the signature should be verified or not
        :param keyjar: A KeyJar that might contain the necessary key.
        :param kwargs: Extra key word arguments
        :return: A class instance
        """
        if key is None and keyjar is not None:
            key = keyjar.get_verify_key(owner="")
        elif key is None:
            key = []

        if keyjar is not None and "sender" in kwargs:
            key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

        _jw = jwe.factory(txt)
        if _jw:
            if "algs" in kwargs and "encalg" in kwargs["algs"]:
                try:
                    assert kwargs["algs"]["encalg"] == _jw["alg"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["alg"], kwargs["algs"]["encalg"]))
                try:
                    assert kwargs["algs"]["encenc"] == _jw["enc"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["enc"], kwargs["algs"]["encenc"]))
            if keyjar:
                dkeys = keyjar.get_decrypt_key(owner="")
            elif key:
                dkeys = key
            else:
                dkeys = []

            txt = _jw.decrypt(txt, dkeys)
            self.jwe_header = _jw.jwt.headers

        _jw = jws.factory(txt)
        if _jw:
            if "algs" in kwargs and "sign" in kwargs["algs"]:
                _alg = _jw.jwt.headers["alg"]
                try:
                    assert kwargs["algs"]["sign"] == _alg
                except AssertionError:
                    raise WrongSigningAlgorithm("%s != %s" % (
                        _alg, kwargs["algs"]["sign"]))
            try:
                _jwt = JWT().unpack(txt)
                jso = _jwt.payload()
                _header = _jwt.headers

                logger.debug("Raw JSON: {}".format(jso))
                logger.debug("header: {}".format(_header))
                if _header["alg"] == "none":
                    pass
                else:
                    if keyjar:
                        logger.debug("Issuer keys: {}".format(keyjar.keys()))
                        try:
                            _iss = jso["iss"]
                        except KeyError:
                            pass
                        else:
                            if "jku" in _header:
                                if not keyjar.find(_header["jku"], _iss):
                                    # This is really questionable
                                    try:
                                        if kwargs["trusting"]:
                                            keyjar.add(jso["iss"], _header["jku"])
                                    except KeyError:
                                        pass

                            if "kid" in _header and _header["kid"]:
                                _jw["kid"] = _header["kid"]
                                try:
                                    _key = keyjar.get_key_by_kid(_header["kid"],
                                                                 _iss)
                                    if _key:
                                        key.append(_key)
                                except KeyError:
                                    pass

                        try:
                            self._add_key(keyjar, kwargs["opponent_id"], key)
                        except KeyError:
                            pass

                    if verify:
                        if keyjar:
                            for ent in ["iss", "aud", "client_id"]:
                                if ent not in jso:
                                    continue
                                if ent == "aud":
                                    # list or basestring
                                    if isinstance(jso["aud"], six.string_types):
                                        _aud = [jso["aud"]]
                                    else:
                                        _aud = jso["aud"]
                                    for _e in _aud:
                                        self._add_key(keyjar, _e, key)
                                else:
                                    self._add_key(keyjar, jso[ent], key)

                        if "alg" in _header and _header["alg"] != "none":
                            if not key:
                                raise MissingSigningKey(
                                    "alg=%s" % _header["alg"])

                        logger.debug("Verify keys: {}".format(key))
                        _jw.verify_compact(txt, key)
            except Exception:
                raise
            else:
                self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        return self.from_dict(jso)
Example #51
0
def test_pack_with_headers():
    _jwt = JWT()
    jwt = _jwt.pack(parts=["", ""], headers={"foo": "bar"})
    assert JWT().unpack(jwt).headers["foo"] == "bar"
Example #52
0
# The JWS class can not work directly with rsa keys.
# In this case the rsa key is wrapped in a RSAKey
keys = [RSAKey(key=import_rsa_key_from_file("foo"))]

_jws = JWS(payload, alg="RS512")
_jwt = _jws.sign_compact(keys)

print("Signed jwt:",  _jwt)
print()

# The JWT class can be used to peek into a JWT, whether is is signed or
# encrypted. It will not do any verificiation or decryption just unpacking
# the JWT.

jwt = JWT()
jwt.unpack(_jwt)
print("jwt headers:", jwt.headers)

# Part 0 is the headers
# Part 1 is the payload message
print("jwt part 1:", jwt.part[1])
print()

# If you want to verify the signature you have to use the JWS class
_rj = JWS()

# If everything is OK the verify_compact method will return the payload message
info = _rj.verify_compact(_jwt, keys)

print("Verified info:", info)
    def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs):
        """
        Given a signed and/or encrypted JWT, verify its correctness and then
        create a class instance from the content.

        :param txt: The JWT
        :param key: keys that might be used to decrypt and/or verify the
            signature of the JWT
        :param verify: Whether the signature should be verified or not
        :param keyjar: A KeyJar that might contain the necessary key.
        :param kwargs: Extra key word arguments
        :return: A class instance
        """
        if key is None and keyjar is not None:
            key = keyjar.get_verify_key(owner="")
        elif key is None:
            key = []

        if keyjar is not None and "sender" in kwargs:
            key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

        _jw = jwe.factory(txt)
        if _jw:
            if "algs" in kwargs and "encalg" in kwargs["algs"]:
                try:
                    assert kwargs["algs"]["encalg"] == _jw["alg"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["alg"], kwargs["algs"]["encalg"]))
                try:
                    assert kwargs["algs"]["encenc"] == _jw["enc"]
                except AssertionError:
                    raise WrongEncryptionAlgorithm("%s != %s" % (
                        _jw["enc"], kwargs["algs"]["encenc"]))
            if keyjar:
                dkeys = keyjar.get_decrypt_key(owner="")
            elif key:
                dkeys = key
            else:
                dkeys = []

            txt = as_unicode(_jw.decrypt(txt, dkeys))
            self.jwe_header = _jw.jwt.headers

        _jw = jws.factory(txt)
        if _jw:
            if "algs" in kwargs and "sign" in kwargs["algs"]:
                _alg = _jw.jwt.headers["alg"]
                try:
                    assert kwargs["algs"]["sign"] == _alg
                except AssertionError:
                    raise WrongSigningAlgorithm("%s != %s" % (
                        _alg, kwargs["algs"]["sign"]))
            try:
                _jwt = JWT().unpack(txt)
                jso = _jwt.payload()
                _header = _jwt.headers

                logger.debug("Raw JSON: {}".format(jso))
                logger.debug("header: {}".format(_header))
                if _header["alg"] == "none":
                    pass
                elif verify:
                    if keyjar:
                        key = self.get_verify_keys(keyjar, key, jso, _header,
                                                   _jw, **kwargs)

                    if "alg" in _header and _header["alg"] != "none":
                        if not key:
                            raise MissingSigningKey(
                                "alg=%s" % _header["alg"])

                    logger.debug("Verify keys: {}".format(key))
                    try:
                        _jw.verify_compact(txt, key)
                    except NoSuitableSigningKeys:
                        if keyjar:
                            update_keyjar(keyjar)
                            key = self.get_verify_keys(keyjar, key, jso,
                                                       _header, _jw, **kwargs)
                            _jw.verify_compact(txt, key)
            except Exception:
                raise
            else:
                self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        return self.from_dict(jso)
Example #54
0
# $ ssh-keygen -t rsa -b 4096
# and provide the foo filename with requested.
#
# Now a JWS can be created as follow:
# - retrieve the rsa key (the example below will also print it in the JWK section)
# - use the JWS object to create the token specifying the algorithm to be used for signing
# - call the method sign_compact providing an array of keys (eventually containing 1 key only) to be used for signing
# - the example belows shows the content of the JWT, by printing it
# - the signature can be verified with the method verify_compact (of course providing the same keys used for signing)

payload = {"iss": "jow",
           "exp": 1300819380,
           "http://example.com/is_root": True}

keys = [RSAKey(key=import_rsa_key_from_file("foo"))]
jws = JWS(payload, alg="RS512").sign_compact(keys)
print "jwt signed:", jws
print

########################################

jwt_received = JWT()
jwt_received.unpack(jws)
print "jwt headers:", jwt_received.headers
print "jwt part 1:", jwt_received.part[1]
print

_rj = JWS()
info = _rj.verify_compact(jws, keys)
print "Verified info:", info