def test_client_secret_jwt(self, client): _ci = client.client_info _ci.token_endpoint = "https://example.com/token" _ci.provider_info = { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" } csj = ClientSecretJWT() request = AccessTokenRequest() csj.construct(request, cli_info=client.client_info, algorithm="HS256", authn_endpoint='userinfo') assert request["client_assertion_type"] == JWT_BEARER assert "client_assertion" in request cas = request["client_assertion"] _skey = [SYMKey(k=b64e(as_bytes(_ci.client_secret)), use='sig')] jso = JWT(rec_keys={client.client_id: _skey}).unpack(cas) assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) _rj = JWS() info = _rj.verify_compact( cas, [SYMKey(k=b64e(as_bytes(_ci.client_secret)))]) assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert info['aud'] == [_ci.provider_info['issuer']]
def cookie_signature(key, *parts): """Generates a cookie signature. :param key: The HMAC key to use. :type key: bytes :param parts: List of parts to include in the MAC :type parts: list of bytes or strings :returns: hexdigest of the HMAC """ sha1 = hmac.new(as_bytes(key), digestmod=hashlib.sha1) for part in parts: if part: sha1.update(as_bytes(part)) return str(sha1.hexdigest())
def service_endpoint(self, name, **kwargs): logger.info(kwargs) logger.info('At the {} endpoint'.format(name)) endpoint = self.endpoint_context.endpoint[name] try: authn = cherrypy.request.headers['Authorization'] except KeyError: pr_args = {} else: pr_args = {'auth': authn} if endpoint.request_placement == 'body': if cherrypy.request.process_request_body is True: _request = cherrypy.request.body.read() else: raise cherrypy.HTTPError(400, 'Missing HTTP body') if not _request: _request = kwargs req_args = endpoint.parse_request(_request, **pr_args) else: req_args = endpoint.parse_request(kwargs, **pr_args) logger.info('request: {}'.format(req_args)) if isinstance(req_args, ResponseMessage) and 'error' in req_args: return as_bytes(req_args.to_json()) args = endpoint.process_request(req_args) return self.do_response(endpoint, req_args, **args)
def acb(self, op_hash='', **kwargs): logger.debug('Callback kwargs: {}'.format(kwargs)) rp = self.get_rp(op_hash) try: session_info = self.rph.session_interface.get_state( kwargs['state']) except KeyError: raise cherrypy.HTTPError(400, 'Unknown state') logger.debug('Session info: {}'.format(session_info)) # rp.service_context.provider_info['issuer'] != state_info['iss']: # raise cherrypy.HTTPError(400, 'Wrong Issuer') res = self.rph.finalize(session_info['iss'], kwargs) if is_error_message(res): raise cherrypy.HTTPError(400, res['error']) else: fname = os.path.join(self.html_home, 'opresult.html') _pre_html = open(fname, 'r').read() _html = _pre_html.format(result=create_result_page( userinfo=res['userinfo'], access_token=res['token'], client=rp)) return as_bytes(_html)
def test_client_secret_basic(): _token = '{}:{}'.format(client_id, client_secret) token = as_unicode(base64.b64encode(as_bytes(_token))) authz_token = 'Basic {}'.format(token) authn_info = ClientSecretBasic(endpoint_context).verify({}, authz_token) assert authn_info['client_id'] == client_id
def metadata(self): cherrypy.response.headers['Content-Type'] = 'application/jws' metadata_statement = MetadataStatement() fe = self.endpoint_context.federation_entity fe.add_signing_keys(metadata_statement) try: sms = fe.self_signer.sign(metadata_statement, aud=fe.fo_priority) except Exception as err: logger.exception(err) raise return as_bytes(sms)
def metadata(self): cherrypy.response.headers['Content-Type'] = 'application/jws' _info = self.rph.client_configs['']['client_preferences'] metadata_statement = MetadataStatement(**_info) fe = self.rph.extra['federation_entity'] fe.add_signing_keys(metadata_statement) try: sms = fe.self_signer.sign(metadata_statement, aud=fe.fo_priority) except Exception as err: logger.exception(err) raise return as_bytes(sms)
def encrypt(self, key, iv="", cek="", **kwargs): """ Produces a JWE using RSA algorithms :param key: RSA key :param context: :param iv: :param cek: :return: A jwe """ _msg = as_bytes(self.msg) if "zip" in self: if self["zip"] == "DEF": _msg = zlib.compress(_msg) else: raise ParameterError("Zip has unknown value: %s" % self["zip"]) kwarg_cek = cek or None _enc = self["enc"] iv = self._generate_iv(_enc, iv) cek = self._generate_key(_enc, cek) self["cek"] = cek logger.debug("cek: %s, iv: %s" % ([c for c in cek], [c for c in iv])) _encrypt = RSAEncrypter(self.with_digest).encrypt _alg = self["alg"] if kwarg_cek: jwe_enc_key = '' elif _alg == "RSA-OAEP": jwe_enc_key = _encrypt(cek, key, 'pkcs1_oaep_padding') elif _alg == "RSA-OAEP-256": jwe_enc_key = _encrypt(cek, key, 'pkcs1_oaep_256_padding') elif _alg == "RSA1_5": jwe_enc_key = _encrypt(cek, key) else: raise NotSupportedAlgorithm(_alg) jwe = JWEnc(**self.headers()) try: _auth_data = kwargs['auth_data'] except KeyError: _auth_data = jwe.b64_encode_header() ctxt, tag, key = self.enc_setup(_enc, _msg, key=cek, iv=iv, auth_data=_auth_data) return jwe.pack(parts=[jwe_enc_key, iv, ctxt, tag])
def _make_hashed_key(parts, hashfunc='sha256'): """ Construct a key via hashing the parts If the parts do not have enough entropy of their own, this doesn't help. The size of the hash digest determines the size. """ h = hashlib.new(hashfunc) for part in parts: if part: h.update(as_bytes(part)) return h.digest()
def do_response(self, endpoint, req_args, **args): info = endpoint.do_response(request=req_args, **args) for key, value in info['http_headers']: cherrypy.response.headers[key] = value try: _response_placement = info['response_placement'] except KeyError: _response_placement = endpoint.response_placement if _response_placement == 'body': logger.info('Response: {}'.format(info['response'])) return as_bytes(info['response']) elif _response_placement == 'url': logger.info('Redirect to: {}'.format(info['response'])) raise cherrypy.HTTPRedirect(info['response'])
def repost_fragment(self, **kwargs): logger.debug('repost_fragment kwargs: {}'.format(kwargs)) args = compact(parse_qs(kwargs['url_fragment'])) op_hash = kwargs['op_hash'] rp = self.get_rp(op_hash) x = rp.service_context.state_db[args['state']] logger.debug('State info: {}'.format(x)) res = self.rph.finalize(x['as'], args) if res[0] is True: fname = os.path.join(self.html_home, 'opresult.html') _pre_html = open(fname, 'r').read() _html = _pre_html.format(result=create_result_page(*res[1:])) return as_bytes(_html) else: raise cherrypy.HTTPError(400, res[1])
def __init__(self, kty="oct", alg="", use="", kid="", key=None, x5c=None, x5t="", x5u="", k="", mtrl="", **kwargs): Key.__init__(self, kty, alg, use, kid, as_bytes(key), x5c, x5t, x5u, **kwargs) self.k = k if not self.key and self.k: if isinstance(self.k, str): self.k = self.k.encode("utf-8") self.key = b64d(bytes(self.k))
def create_callbacks(self, issuer): """ To mitigate some security issues the redirect_uris should be OP/AS specific. This method creates a set of redirect_uris unique to the OP/AS. :param issuer: Issuer ID :return: A set of redirect_uris """ _hash = hashlib.sha256() _hash.update(self.hash_seed) _hash.update(as_bytes(issuer)) _hex = _hash.hexdigest() self.hash2issuer[_hex] = issuer return { 'code': "{}/authz_cb/{}".format(self.base_url, _hex), 'implicit': "{}/authz_im_cb/{}".format(self.base_url, _hex), 'form_post': "{}/authz_fp_cb/{}".format(self.base_url, _hex), '__hex': _hex }
def index(self, uid='', iss=''): link = '' if iss: link = iss elif uid: pass else: fname = os.path.join(self.html_home, 'opbyuid.html') return as_bytes(open(fname, 'r').read()) if link or uid: if uid: args = {'user_id': uid} else: args = {} try: result = self.rph.begin(link, **args) except Exception as err: raise cherrypy.HTTPError(err) else: raise cherrypy.HTTPRedirect(result['url'])
def __init__(self, base_url='', hash_seed="", keyjar=None, verify_ssl=True, services=None, service_factory=None, client_configs=None, client_authn_factory=None, client_cls=None, state_db=None, **kwargs): self.base_url = base_url self.hash_seed = as_bytes(hash_seed) self.verify_ssl = verify_ssl self.keyjar = keyjar if state_db: self.state_db = state_db else: self.state_db = InMemoryStateDataBase() self.session_interface = StateInterface(self.state_db) try: self.jwks_uri = add_path(base_url, kwargs['jwks_path']) except KeyError: pass self.extra = kwargs self.client_cls = client_cls or oidc.RP self.services = services self.service_factory = service_factory or factory self.client_authn_factory = client_authn_factory self.client_configs = client_configs # keep track on which RP instance that serves with OP self.issuer2rp = {} self.hash2issuer = {}
def encrypt(self, iv="", cek="", **kwargs): _msg = as_bytes(self.msg) _args = self._dict try: _args["kid"] = kwargs["kid"] except KeyError: pass if 'params' in kwargs: if 'apu' in kwargs['params']: _args['apu'] = kwargs['params']['apu'] if 'apv' in kwargs['params']: _args['apv'] = kwargs['params']['apv'] if 'epk' in kwargs['params']: _args['epk'] = kwargs['params']['epk'] jwe = JWEnc(**_args) ctxt, tag, cek = super(JWE_EC, self).enc_setup(self["enc"], _msg, auth_data=jwe.b64_encode_header(), key=cek, iv=iv) if 'encrypted_key' in kwargs: return jwe.pack(parts=[kwargs['encrypted_key'], iv, ctxt, tag]) return jwe.pack(parts=[iv, ctxt, tag])
def sha512_digest(msg): return hashlib.sha512(as_bytes(msg)).digest()
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" % sanitize(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(":") _bid = as_bytes(_id) _cinfo = None try: _cinfo = cdb[_id] except KeyError: try: _cinfo[_bid] except AttributeError: pass if not _cinfo: logger.debug("Unknown client_id") raise FailedAuthentication("Unknown client_id") else: if not valid_client_info(_cinfo): logger.debug("Invalid Client info") raise FailedAuthentication("Invalid Client") if _secret != _cinfo["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 hash(value): _hash = hashlib.sha256() _hash.update(as_bytes(value)) return _hash.hexdigest()
def sha256_digest(msg): return hashlib.sha256(as_bytes(msg)).digest()
def sha384_digest(msg): return hashlib.sha384(as_bytes(msg)).digest()