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)
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']]
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 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)
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_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()
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
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()
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)
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
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"]
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 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
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()
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'}
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)
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"] == "https://example.com/redirect" assert payload["client_id"] == CLIENT_ID assert "nonce" in payload os.remove(local_path)
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'} 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, 'id_token': id_token, 'id_token_payload': parsed_id_token } template = settings.HOMEPAGE_AUTHENTICATED_TEMPLATE else: name = ('home') context = {'name': name} template = settings.HOMEPAGE_TEMPLATE return render(request, template, context)
def save_profile(backend, user, response, *args, **kwargs): if backend.name == 'vmi': 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 'sub' in payload: profile.subject = payload['sub'] if 'nickname' in payload: profile.nicname = 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 'phone_verified' in payload: profile.phone_verified = payload['phone_verified'] if 'ial' in payload: profile.identity_assurance_level = payload['ial'] if 'picture' in payload: profile.picture_url = payload['picture'] else: profile.picture_url = '' profile.most_recent_id_token_payload = json.dumps( payload, indent=4) profile.save()
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 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 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)
def set_crosswalk_with_id_token(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() if 'document' in payload: for doc in payload['document']: # Does it already exist? cw, g_o_c = Crosswalk.objects.get_or_create( user=user, user_identifier=doc['num'], user_id_type=doc['type']) if "azurehealthcareapis.com" in doc['uri']: cw.use_client_credentials = True cw.fhir_source = doc['uri'] if doc['type'] == "PATIENT_ID_FHIR": cw.fhir_patient_id = doc['num'] cw.save()
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.')
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 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: logger.debug("JWE headers: {}".format(_jw.jwt.headers)) if "algs" in kwargs and "encalg" in kwargs["algs"]: if kwargs["algs"]["encalg"] != _jw["alg"]: raise WrongEncryptionAlgorithm("%s != %s" % (_jw["alg"], kwargs["algs"]["encalg"])) if kwargs["algs"]["encenc"] != _jw["enc"]: raise WrongEncryptionAlgorithm("%s != %s" % (_jw["enc"], kwargs["algs"]["encenc"])) if keyjar: dkeys = keyjar.get_decrypt_key(owner="") if "sender" in kwargs: dkeys.extend(keyjar.get_verify_key(owner=kwargs["sender"])) elif key: dkeys = key else: dkeys = [] logger.debug('Decrypt class: {}'.format(_jw.__class__)) _res = _jw.decrypt(txt, dkeys) logger.debug('decrypted message:{}'.format(_res)) if isinstance(_res, tuple): txt = as_unicode(_res[0]) elif isinstance(_res, list) and len(_res) == 2: txt = as_unicode(_res[0]) else: txt = as_unicode(_res) 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"] if kwargs["algs"]["sign"] != _alg: raise WrongSigningAlgorithm("%s != %s" % (_alg, kwargs["algs"]["sign"])) try: _jwt = JWT().unpack(txt) jso = _jwt.payload() _header = _jwt.headers 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"])) logger.debug("Raw JSON: {}".format(sanitize(jso))) logger.debug("JWS header: {}".format(sanitize(_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("Found signing 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) self.jwt = txt return self.from_dict(jso)
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)
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)
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)