def __init__(self, kty="", alg="", use="", kid="", key=None, x5c=None, x5t="", x5u="", **kwargs): self.key = key self.extra_args = kwargs # want kty, alg, use and kid to be strings if isinstance(kty, six.string_types): self.kty = kty else: self.kty = as_unicode(kty) if isinstance(alg, six.string_types): self.alg = alg else: self.alg = as_unicode(alg) if isinstance(use, six.string_types): self.use = use else: self.use = as_unicode(use) if isinstance(kid, six.string_types): self.kid = kid else: self.kid = as_unicode(kid) self.x5c = x5c or [] self.x5t = x5t self.x5u = x5u self.inactive_since = 0 self._hash = None
def left_hash(msg, func="HS256"): """ 128 bits == 16 bytes """ if func == 'HS256': return as_unicode(b64e(sha256_digest(msg)[:16])) elif func == 'HS384': return as_unicode(b64e(sha384_digest(msg)[:24])) elif func == 'HS512': return as_unicode(b64e(sha512_digest(msg)[:32]))
def request(self, location, fragment_enc=False): _l = as_unicode(location) _qp = as_unicode(self.to_urlencoded()) if fragment_enc: return "%s#%s" % (_l, _qp) else: if "?" in location: return "%s&%s" % (_l, _qp) else: return "%s?%s" % (_l, _qp)
def elements_to_unicode(b): """ Tries to convert all elements in a list/dict from a byte string to an unicode string :param b: list / dict :return: list / dict """ if isinstance(b, list): return [as_unicode(v) for v in b] if isinstance(b, dict): conv_dict = dict() for key in b.keys(): conv_dict[key] = as_unicode(b[key]) return conv_dict
def extract_from_request(environ, kwargs=None): if kwargs is None: kwargs = {} request = None try: request = environ["QUERY_STRING"] except KeyError: pass if not request: try: request = as_unicode(get_post(environ)) except KeyError: pass kwargs["request"] = request # authentication information try: kwargs["authn"] = environ["HTTP_AUTHORIZATION"] except KeyError: pass try: kwargs["cookie"] = environ["HTTP_COOKIE"] except KeyError: pass # intended audience kwargs["requrl"] = geturl(environ) kwargs["url"] = geturl(environ, query=False) kwargs["baseurl"] = geturl(environ, query=False, path=False) kwargs["path"] = getpath(environ) return kwargs
def encryption_key(self, alg, **kwargs): """ Return an encryption key as per http://openid.net/specs/openid-connect-core-1_0.html#Encryption :param alg: encryption algorithm :param kwargs: :return: encryption key as byte string """ if not self.key: self.deserialize() tsize = ALG2KEYLEN[alg] #_keylen = len(self.key) if tsize <= 32: # SHA256 _enc_key = sha256_digest(self.key)[:tsize] elif tsize <= 48: # SHA384 _enc_key = sha384_digest(self.key)[:tsize] elif tsize <= 64: # SHA512 _enc_key = sha512_digest(self.key)[:tsize] else: raise JWKException("No support for symmetric keys > 512 bits") logger.debug('Symmetric encryption key: {}'.format( as_unicode(b64e(_enc_key)))) return _enc_key
def verify_self_signed_jwks(sjwt): """ Verify the signature of a signed JWT containing a JWKS. The JWT is signed by one of the keys in the JWKS. In the JWT the JWKS is stored using this format :: 'jwks': { 'keys': [ ] } :param sjwt: Signed Jason Web Token :return: Dictionary containing 'jwks' (the JWKS) and 'iss' (the issuer of the JWT) """ _jws = factory(sjwt) _json = _jws.jwt.part[1] _body = json.loads(as_unicode(_json)) iss = _body['iss'] _jwks = _body['jwks'] _kj = jwks_to_keyjar(_jwks, iss) try: _kid = _jws.jwt.headers['kid'] except KeyError: _keys = _kj.get_signing_key(owner=iss) else: _keys = _kj.get_signing_key(owner=iss, kid=_kid) _ver = _jws.verify_compact(sjwt, _keys) return {'jwks': _ver['jwks'], 'iss': iss}
def backchannel_logout(self, **kwargs): logger.debug('Back channel logout: {}'.format(kwargs)) self.sh['conv'].events.store(EV_HTTP_REQUEST, kwargs) if cherrypy.request.process_request_body is True: _request = as_unicode(cherrypy.request.body.read()) if _request: logger.info('back_channel logout request: {}'.format(_request)) if kwargs['entity_id'] != self.tester.conv.entity.entity_id: self.sh['conv'].events.store(EV_FAULT, "Not for me!") logger.debug('Not for me') self.opresult() else: return self._endpoint(ref='backchannel_logout', request=_request) else: _request_args = cherrypy.request.params if not _request_args: raise cherrypy.HTTPError( 400, 'Missing Back channel Logout request body') logger.info('back_channel logout request_args: {}'.format( _request_args)) if kwargs['entity_id'] != self.tester.conv.entity.entity_id: self.sh['conv'].events.store(EV_FAULT, "Not for me!") logger.debug('Not for me') self.opresult() else: return self._endpoint(ref='backchannel_logout', request_args=_request_args) else: raise cherrypy.HTTPError( 400, 'Missing Back channel Logout request body')
def static(environ, start_response, path): logger.info("[static]sending: %s" % (path,)) headers = [] try: bytes = open(path, 'rb').read() if path.endswith(".ico"): headers.append(('Content-Type', "image/x-icon")) elif path.endswith(".html"): headers.append(('Content-Type', 'text/html')) elif path.endswith(".json"): headers.append(('Content-Type', 'application/json')) elif path.endswith(".txt"): headers.append(('Content-Type', 'text/plain')) elif path.endswith(".css"): headers.append(('Content-Type', 'text/css')) elif path.endswith(".tar"): headers.append(('Content-Type', 'application/x-tar')) else: headers.append(('Content-Type', 'text/plain')) start_response('200 OK', headers) try: text = as_unicode(bytes) text = as_bytes(text.encode('utf8')) except (ValueError, UnicodeDecodeError): text = bytes except AttributeError: text = bytes resp = do_response(Response, text) except IOError: resp = do_response(NotFound, path) return resp(environ, start_response)
def encryption_key(self, alg, **kwargs): """ Return an encryption key as per http://openid.net/specs/openid-connect-core-1_0.html#Encryption :param alg: encryption algorithm :param kwargs: :return: encryption key as byte string """ if not self.key: self.deserialize() tsize = ALG2KEYLEN[alg] # _keylen = len(self.key) if tsize <= 32: # SHA256 _enc_key = sha256_digest(self.key)[:tsize] elif tsize <= 48: # SHA384 _enc_key = sha384_digest(self.key)[:tsize] elif tsize <= 64: # SHA512 _enc_key = sha512_digest(self.key)[:tsize] else: raise JWKException("No support for symmetric keys > 512 bits") logger.debug('Symmetric encryption key: {}'.format( as_unicode(b64e(_enc_key)))) return _enc_key
def registration(self, **kwargs): logger.debug('Request headers: {}'.format(cherrypy.request.headers)) if cherrypy.request.method == "OPTIONS": cherrypy_cors.preflight( allowed_methods=["POST", "GET"], origins='*', allowed_headers=['Authorization', 'content-type']) elif cherrypy.request.method == "GET": _cinfo = self.op.cdb[kwargs['client_id']] for attr in ['redirect_uris', 'post_logout_redirect_uris']: try: _cinfo[attr] = unpack_redirect_uri(_cinfo[attr]) except KeyError: pass rr = RegistrationResponse(**_cinfo) cherrypy.response.headers['Content-Type'] = 'application/json' return as_bytes(json.dumps(rr.to_dict())) else: logger.debug('ClientRegistration kwargs: {}'.format(kwargs)) _request = None if cherrypy.request.process_request_body is True: _request = as_unicode(cherrypy.request.body.read()) logger.debug('request_body: {}'.format(_request)) try: if _request: resp = self.op.registration_endpoint(_request) else: resp = self.op.registration_endpoint(kwargs) except Exception as err: logger.error(err) raise cherrypy.HTTPError(message=str(err)) return conv_response(resp)
def check_key_availability(inst, jwt): _rj = jws.factory(jwt) payload = json.loads(as_unicode(_rj.jwt.part[1])) _cid = payload['iss'] if _cid not in inst.keyjar: cinfo = inst.cdb[_cid] inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig']) inst.keyjar.add(_cid, cinfo['jwks_uri'])
def modified_idtoken_hint(oper, arg): """ Context: EndSession Action: Sets the 'id_token_hint' argument in a end_session request. The value of the argument is a incorrect signed JWT. Example: "create_idtoken_hint_other_issuer": null """ res = get_signed_id_tokens(oper.conv) if res: _jws = jws_factory(res[-1]) header = as_unicode(b64e(as_bytes(json.dumps({'alg': 'none'})))) oper.req_args["id_token_hint"] = '.'.join( [header, as_unicode(_jws.jwt.b64part[1]), ''])
def jwks(self): self._uptodate() keys = list() for k in self._keys: key = k.to_dict() for k, v in key.items(): key[k] = as_unicode(v) keys.append(key) return json.dumps({"keys": keys})
def request(self, location, fragment_enc=False): """ Given a URL this method will add a fragment, a query part or extend a query part if it already exists with the information in this instance. :param location: A URL :param fragment_enc: Whether the information should be placed in a fragment (True) or in a query part (False) :return: The extended URL """ _l = as_unicode(location) _qp = as_unicode(self.to_urlencoded()) if fragment_enc: return "%s#%s" % (_l, _qp) else: if "?" in location: return "%s&%s" % (_l, _qp) else: return "%s?%s" % (_l, _qp)
def val_hash(self, alg): halg = "HS%s" % alg[-3:] for attr, hash_attr in self.hashable.items(): try: self[hash_attr] = jws.left_hash(as_unicode(self[attr]), halg) except KeyError: pass else: del self[attr]
def is_lesser(a, b): """ Verify that a in lesser then b :param a: :param b: :return: True or False """ if type(a) != type(b): if PY2: # one might be unicode and the other str return as_unicode(a) == as_unicode(b) return False if isinstance(a, string_types) and isinstance(b, string_types): return a == b elif isinstance(a, bool) and isinstance(b, bool): return a == b elif isinstance(a, list) and isinstance(b, list): for element in a: flag = 0 for e in b: if is_lesser(element, e): flag = 1 break if not flag: return False return True elif isinstance(a, dict) and isinstance(b, dict): if is_lesser(list(a.keys()), list(b.keys())): for key, val in a.items(): if not is_lesser(val, b[key]): return False return True return False elif isinstance(a, int) and isinstance(b, int): return a <= b elif isinstance(a, float) and isinstance(b, float): return a <= b return False
def is_lesser(a, b): """ Verify that a is <= then b :param a: An item :param b: Another item :return: True or False """ if type(a) != type(b): if PY2: # one might be unicode and the other str return as_unicode(a) == as_unicode(b) return False if isinstance(a, string_types) and isinstance(b, string_types): return a == b elif isinstance(a, bool) and isinstance(b, bool): return a == b elif isinstance(a, list) and isinstance(b, list): for element in a: flag = 0 for e in b: if is_lesser(element, e): flag = 1 break if not flag: return False return True elif isinstance(a, dict) and isinstance(b, dict): if is_lesser(list(a.keys()), list(b.keys())): for key, val in a.items(): if not is_lesser(val, b[key]): return False return True return False elif isinstance(a, int) and isinstance(b, int): return a <= b elif isinstance(a, float) and isinstance(b, float): return a <= b return False
def test_pack_metadata_statement_other_alg(): _keyjar = build_keyjar(KEYDEFS)[1] op = Operator(keyjar=_keyjar, iss='https://example.com/') req = MetadataStatement(issuer='https://example.org/op') sms = op.pack_metadata_statement(req, alg='ES256') assert sms # Should be a signed JWT _jwt = factory(sms) _body = json.loads(as_unicode(_jwt.jwt.part[1])) assert _body['iss'] == 'https://example.com/' # verify signature r = _jwt.verify_compact(sms, _keyjar.get_signing_key()) assert r
def test_create_fed_provider_info(self): fedpi = self.op.create_fed_providerinfo() assert 'signing_keys' not in fedpi assert len(fedpi['metadata_statements']) == 1 _js = jws.factory(fedpi['metadata_statements'][FO['swamid']]) assert _js assert _js.jwt.headers['alg'] == 'RS256' _body = json.loads(as_unicode(_js.jwt.part[1])) assert _body[ 'iss'] == self.op.federation_entity.signer.signing_service.iss
def jwks(self, private=False): self._uptodate() keys = list() for k in self._keys: if private: key = k.serialize(private) else: key = k.to_dict() for k, v in key.items(): key[k] = as_unicode(v) keys.append(key) return json.dumps({"keys": keys})
def test_encryption_key(): sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b') _enc = sk.encryption_key(alg='A128KW') _v = as_unicode(b64e(_enc)) assert _v == 'xCo9VhtommCTGMWi-RyWBw' sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b') _enc = sk.encryption_key(alg='A192KW') _v = as_unicode(b64e(_enc)) assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86' sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b') _enc = sk.encryption_key(alg='A256KW') _v = as_unicode(b64e(_enc)) assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86vweU_Pi62X8' ek = sha256_digest( 'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY')[ :16] assert as_unicode(b64e(ek)) == 'yf_UUkAFZ8Pn_prxPPgu9w' sk = SYMKey( key='YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY') _enc = sk.encryption_key(alg='A128KW') _v = as_unicode(b64e(_enc)) assert _v == as_unicode(b64e(ek))
def test_encryption_key(): sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b') _enc = sk.encryption_key(alg='A128KW') _v = as_unicode(b64e(_enc)) assert _v == 'xCo9VhtommCTGMWi-RyWBw' sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b') _enc = sk.encryption_key(alg='A192KW') _v = as_unicode(b64e(_enc)) assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86' sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b') _enc = sk.encryption_key(alg='A256KW') _v = as_unicode(b64e(_enc)) assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86vweU_Pi62X8' ek = sha256_digest( 'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY' )[:16] assert as_unicode(b64e(ek)) == 'yf_UUkAFZ8Pn_prxPPgu9w' sk = SYMKey( key= 'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY' ) _enc = sk.encryption_key(alg='A128KW') _v = as_unicode(b64e(_enc)) assert _v == as_unicode(b64e(ek))
def get_client_id(cdb, req, authn): """ Verify the client and return the client id :param req: The request :param authn: Authentication information from the HTTP header :return: """ logger.debug("REQ: %s" % req.to_dict()) if authn: if authn.startswith("Basic "): logger.debug("Basic auth") (_id, _secret) = base64.b64decode( authn[6:].encode("utf-8")).decode("utf-8").split(":") _id = as_unicode(_id) if _id not in cdb: logger.debug("Unknown client_id") raise FailedAuthentication("Unknown client_id") else: if not valid_client_info(cdb[_id]): logger.debug("Invalid Client info") raise FailedAuthentication("Invalid Client") if _secret != cdb[_id]["client_secret"]: logger.debug("Incorrect secret") raise FailedAuthentication("Incorrect secret") else: if authn[:6].lower() == "bearer": logger.debug("Bearer auth") _token = authn[7:] else: raise FailedAuthentication("AuthZ type I don't know") try: _id = cdb[_token] except KeyError: logger.debug("Unknown access token") raise FailedAuthentication("Unknown access token") else: try: _id = str(req["client_id"]) if _id not in cdb: logger.debug("Unknown client_id") raise FailedAuthentication("Unknown client_id") if not valid_client_info(cdb[_id]): raise FailedAuthentication("Invalid client_id") except KeyError: raise FailedAuthentication("Missing client_id") return _id
def payload(self): _msg = as_unicode(self.part[1]) # If not JSON web token assume JSON if "cty" in self.headers and self.headers["cty"].lower() != "jwt": pass else: try: _msg = json.loads(_msg) except ValueError: pass return _msg
def test_provider_endpoint(self): pi_resp = self.op.providerinfo_endpoint() assert isinstance(pi_resp, Response) assert pi_resp.status == "200 OK" _info = json.loads(pi_resp.message) assert list(_info['metadata_statements'].keys()) == [FO['swamid']] _js = jws.factory(_info['metadata_statements'][FO['swamid']]) assert _js assert _js.jwt.headers['alg'] == 'RS256' _body = json.loads(as_unicode(_js.jwt.part[1])) assert _body[ 'iss'] == self.op.federation_entity.signer.signing_service.iss
def index(self, op, **kwargs): if cherrypy.request.method == "OPTIONS": cherrypy_cors.preflight( allowed_methods=["POST"], origins='*', allowed_headers=['Authorization', 'content-type']) else: logger.debug('AccessTokenRequest') try: authn = cherrypy.request.headers['Authorization'] except KeyError: authn = None logger.debug('Authorization: {}'.format(authn)) resp = op.token_endpoint(as_unicode(kwargs), authn, 'dict') return conv_response(resp)
def index(self, op, **kwargs): if cherrypy.request.method == "OPTIONS": cherrypy_cors.preflight( allowed_methods=["POST"], origins='*', allowed_headers=['Authorization', 'content-type']) else: store_request(op, 'AccessTokenRequest') try: authn = cherrypy.request.headers['Authorization'] except KeyError: authn = None logger.debug('Authorization: {}'.format(authn)) resp = op.token_endpoint(as_unicode(kwargs), authn, 'dict') if resp.status_code < 300: set_content_type(resp, 'application/json') return conv_response(op, resp)
def index(self, op): if cherrypy.request.method == "OPTIONS": logger.debug('Request headers: {}'.format(cherrypy.request.headers)) cherrypy_cors.preflight( allowed_methods=["POST"], origins='*', allowed_headers=['Authorization', 'content-type']) else: logger.debug('ClientRegistration request') if cherrypy.request.process_request_body is True: _request = cherrypy.request.body.read() else: raise cherrypy.HTTPError(400, 'Missing Client registration body') logger.debug('request_body: {}'.format(_request)) resp = op.registration_endpoint(as_unicode(_request)) return conv_response(resp)
def check_key_availability(inst, jwt): """ If the server is restarted it will NOT load keys from jwks_uris for all the clients that has been registered. So this function is there to get a clients keys when needed. :param inst: OP instance :param jwt: A JWT that has to be verified or decrypted """ _rj = jws.factory(jwt) payload = json.loads(as_unicode(_rj.jwt.part[1])) _cid = payload['iss'] if _cid not in inst.keyjar: cinfo = inst.cdb[_cid] inst.keyjar.add_symmetric(_cid, cinfo['client_secret'], ['enc', 'sig']) inst.keyjar.add(_cid, cinfo['jwks_uri'])
def test_pack_metadata_statement(): jb = FSJWKSBundle('', None, 'fo_jwks', key_conv={'to': quote_plus, 'from': unquote_plus}) _keyjar = build_keyjar(KEYDEFS)[1] op = Operator(keyjar=_keyjar, jwks_bundle=jb, iss='https://example.com/') req = MetadataStatement(issuer='https://example.org/op') sms = op.pack_metadata_statement(req) assert sms # Should be a signed JWT _jwt = factory(sms) assert _jwt assert _jwt.jwt.headers['alg'] == 'RS256' _body = json.loads(as_unicode(_jwt.jwt.part[1])) assert _body['iss'] == op.iss assert _body['issuer'] == 'https://example.org/op' # verify signature r = _jwt.verify_compact(sms, _keyjar.get_signing_key()) assert r
def authenticated_as(self, cookie=None, authorization="", **kwargs): """ :param cookie: A HTTP Cookie :param authorization: The HTTP Authorization header :param args: extra args :param kwargs: extra key word arguments :return: """ if authorization.startswith("Basic"): authorization = authorization[6:] _decoded = as_unicode(base64.b64decode(authorization)) (user, pwd) = _decoded.split(":") user = unquote_plus(user) pwd = unquote_plus(pwd) self.verify_password(user, pwd) return {"uid": user}, time.time()
def jwks(self, private=False): """ Create a JWKS :param private: Whether private key information should be included. :return: A JWKS representation of the keys in this bundle """ self._uptodate() keys = list() for k in self._keys: if private: key = k.serialize(private) else: key = k.to_dict() for k, v in key.items(): key[k] = as_unicode(v) keys.append(key) return json.dumps({"keys": keys})
def index(self, op): if cherrypy.request.method == "OPTIONS": logger.debug('Request headers: {}'.format(cherrypy.request.headers)) cherrypy_cors.preflight( allowed_methods=["POST"], origins='*', allowed_headers=['Authorization', 'content-type']) else: store_request(op, 'ClientRegistration') if cherrypy.request.process_request_body is True: _request = cherrypy.request.body.read() else: raise cherrypy.HTTPError(400, 'Missing Client registration body') logger.debug('request_body: {}'.format(_request)) resp = op.registration_endpoint(as_unicode(_request)) if resp.status_code < 300: set_content_type(resp, 'application/json') return conv_response(op, resp)
def index(self, op, **kwargs): if cherrypy.request.method == "OPTIONS": cherrypy_cors.preflight( allowed_methods=["GET", "POST"], origins='*', allowed_headers=['Authorization', 'content-type']) else: store_request(op, 'CheckSessionIframe') logger.debug('CheckSessionIframe: {}'.format(kwargs)) if cherrypy.request.method == "POST": _req = cherrypy.request.body.read() kwargs = json.loads(as_unicode(_req)) # will contain client_id and origin if kwargs['client_id'] not in op.cdb: return b'error' # Should have some intelligent check for origin return b'ok' else: doc = open('templates/check_session_iframe.html').read() return as_bytes(doc)
def __call__(self, req, **kwargs): r = requests.post(self.url, json=req, verify=False) if 200 <= r.status_code < 300: _jw = factory(r.text) # First Just checking the issuer ID *not* verifying the Signature body = json.loads(as_unicode(_jw.jwt.part[1])) assert body['iss'] == self.iss # Now verifying the signature try: _jw.verify_compact(r.text, self.keyjar.get_verify_key(owner=self.iss)) except AssertionError: raise JWSException('JWS signature verification error') return r.text else: raise SigningServiceError("{}: {}".format(r.status_code, r.text))
def do_left_hash(cls, input, alg, base64_func): hash_funcs = { 'HS256' : [16, jwk.sha256_digest], 'hs256' : [16, jwk.sha256_digest], 'RS256' : [16, jwk.sha256_digest], 'rs256' : [16, jwk.sha256_digest], 'HS384' : [24, jwk.sha384_digest], 'hs384' : [24, jwk.sha384_digest], 'RS384' : [24, jwk.sha384_digest], 'rs384' : [24, jwk.sha384_digest], 'HS512' : [32, jwk.sha512_digest], 'hs512' : [32, jwk.sha512_digest], 'RS512' : [32, jwk.sha512_digest], 'rs512' : [32, jwk.sha512_digest] } hash_info = hash_funcs.get(alg) if hash_info == None: raise OAuth2ProtocolError("unknown hash algorithm: " + alg) hash_size, hash_func = hash_info return jwkest.as_unicode(base64_func(hash_func(input)[:hash_size]))
def serialize(self, private=True): res = self.common() res["k"] = as_unicode(b64e(bytes(self.key))) return res
try: jwks = keyjar_init(OAS, config.keys, kid_template="op%d") except Exception as err: LOGGER.error("Key setup failed: {}".format(err)) print("Key setup failed: {}".format(err)) exit() #OAS.key_setup("static", sig={"format": "jwk", "alg": "rsa"}) else: jwks_file_name = JWKS_FILE_NAME f = open(jwks_file_name, "w") for key in jwks["keys"]: for k in key.keys(): key[k] = as_unicode(key[k]) f.write(json.dumps(jwks)) f.close() OAS.jwks_uri = "{}/{}".format(OAS.baseurl, jwks_file_name) # Initiate the SessionDB _token = JWTToken('T', OAS.keyjar, {'code': 3600, 'token': 900}, iss=config.issuer, sign_alg= 'RS256') _refresh_token = JWTToken('R', OAS.keyjar, {'': 86400}, iss=config.issuer, sign_alg='RS256') OAS.sdb = SessionDB(config.SERVICE_URL, token_factory=_token, refresh_token_factory=_refresh_token) # set some parameters try:
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 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)