def __init__(self): self.g_config = {} with open("../src/config/config.json") as j: self.g_config = json.load(j) wkh = WellKnownHandler(self.g_config["auth_server_url"], secure=False) self.__TOKEN_ENDPOINT = wkh.get(TYPE_OIDC, KEY_OIDC_TOKEN_ENDPOINT) #Generate ID Token _rsakey = RSA.generate(2048) _private_key = _rsakey.exportKey() _public_key = _rsakey.publickey().exportKey() file_out = open("private.pem", "wb") file_out.write(_private_key) file_out.close() file_out = open("public.pem", "wb") file_out.write(_public_key) file_out.close() _rsajwk = RSAKey(kid='RSA1', key=import_rsa_key(_private_key)) _payload = { "iss": self.g_config["client_id"], "sub": self.g_config["client_secret"], "aud": self.__TOKEN_ENDPOINT, "jti": datetime.datetime.today().strftime('%Y%m%d%s'), "exp": int(time.time())+3600 } _jws = JWS(_payload, alg="RS256") self.jwt = _jws.sign_compact(keys=[_rsajwk]) self.scopes = 'public_access' self.resourceName = "TestResourcePEP10" self.PEP_HOST = "http://localhost:5566" status, self.resourceID = self.createTestResource() print(self.jwt) print(self.resourceID)
def get_jwt_keys(self) -> list[Key]: """ Takes a provider and returns the set of keys associated with it. Returns a list of keys. """ if self.jwt_alg == JWTAlgorithms.RS256: # if the user selected RS256 but didn't select a # CertificateKeyPair, we fall back to HS256 if not self.rsa_key: Event.new( EventAction.CONFIGURATION_ERROR, provider=self, message= "Provider was configured for RS256, but no key was selected.", ).save() self.jwt_alg = JWTAlgorithms.HS256 self.save() else: # Because the JWT Library uses python cryptodome, # we can't directly pass the RSAPublicKey # object, but have to load it ourselves key = import_rsa_key(self.rsa_key.key_data) keys = [RSAKey(key=key, kid=self.rsa_key.kid)] if not keys: raise Exception("You must add at least one RSA Key.") return keys if self.jwt_alg == JWTAlgorithms.HS256: return [SYMKey(key=self.client_secret, alg=self.jwt_alg)] raise Exception("Unsupported key algorithm.")
def init_oidc_provider(app): with app.app_context(): issuer = url_for('oidc_provider.index')[:-1] authentication_endpoint = url_for('oidc_provider.authentication_endpoint') jwks_uri = url_for('oidc_provider.jwks_uri') token_endpoint = url_for('oidc_provider.token_endpoint') userinfo_endpoint = url_for('oidc_provider.userinfo_endpoint') configuration_information = { 'issuer': issuer, 'authorization_endpoint': authentication_endpoint, 'jwks_uri': jwks_uri, 'token_endpoint': token_endpoint, 'userinfo_endpoint': userinfo_endpoint, 'scopes_supported': ['openid'], 'response_types_supported': ['code', 'code id_token', 'code token', 'code id_token token'], # code and hybrid 'response_modes_supported': ['query', 'fragment'], 'grant_types_supported': ['authorization_code', 'implicit'], 'subject_types_supported': ['pairwise'], 'token_endpoint_auth_methods_supported': ['client_secret_basic'], 'claims_parameter_supported': True } clients_db = OpStorageWrapper(app.config['DB_URI'], 'clients') userinfo_db = Userinfo(app.users) with open(app.config['PROVIDER_SIGNING_KEY']['PATH']) as f: key = f.read() signing_key = RSAKey(key=import_rsa_key(key), kid=app.config['PROVIDER_SIGNING_KEY']['KID'], alg='RS256') provider = Provider(signing_key, configuration_information, init_authorization_state(app), clients_db, userinfo_db) provider.authentication_request_validators.append(_request_contains_nonce) return provider
def test_jwks_endpoint(self): resp = self.app.test_client().get('/jwks') assert resp.status_code == 200 jwks = json.loads(resp.data.decode('utf-8')) assert len(jwks['keys']) == 1 jwks_key = RSAKey(**jwks['keys'][0]) basename = os.path.dirname(os.path.realpath(__file__)) with open(os.path.join(basename, '../private.pem')) as f: expected_key = RSAKey(key=import_rsa_key(f.read()), kid=jwks_key.kid, alg='RS256') assert jwks_key == expected_key
def add_issuer_key(self, private_key): """ Adds a private key to the list of keys available for decryption and signatures :return: Boolean - Whether the key is already in the list """ new_key = RSAKey(key=import_rsa_key(private_key), kid=self.__generate_key_id(private_key)) for key in self.issuer_private_keys: if new_key.kid == key.kid: return False self.issuer_private_keys.append(new_key) self.loaded_issuer_private_keys[new_key.kid] = PKCS1_OAEP.new( RSA.importKey(private_key))
def setUpClass(cls): cls.g_config = {} with open("../src/config/config.json") as j: cls.g_config = json.load(j) wkh = WellKnownHandler(cls.g_config["auth_server_url"], secure=False) cls.__TOKEN_ENDPOINT = wkh.get(TYPE_OIDC, KEY_OIDC_TOKEN_ENDPOINT) #Generate ID Token _rsakey = RSA.generate(2048) _private_key = _rsakey.exportKey() _public_key = _rsakey.publickey().exportKey() file_out = open("private.pem", "wb") file_out.write(_private_key) file_out.close() file_out = open("public.pem", "wb") file_out.write(_public_key) file_out.close() #Admin JWT _rsajwk = RSAKey(kid='RSA1', key=import_rsa_key(_private_key)) _payload = { "iss": cls.g_config["client_id"], "sub": cls.g_config["client_id"], "aud": cls.__TOKEN_ENDPOINT, "jti": datetime.datetime.today().strftime('%Y%m%d%s'), "exp": int(time.time())+3600, "isOperator": False } _jws = JWS(_payload, alg="RS256") cls.jwt_admin = _jws.sign_compact(keys=[_rsajwk]) #ROTest user JWT _payload = { "iss": cls.g_config["client_id"], "sub": "54d10251-6cb5-4aee-8e1f-f492f1105c94", "aud": cls.__TOKEN_ENDPOINT, "jti": datetime.datetime.today().strftime('%Y%m%d%s'), "exp": int(time.time())+3600, "isOperator": False } _jws = JWS(_payload, alg="RS256") cls.jwt_rotest = _jws.sign_compact(keys=[_rsajwk]) cls.scopes = 'public_access' cls.resourceName = "TestROChangePEP" cls.PEP_HOST = "http://localhost:5566"
def add_issuer_key(self, private_key): """ Adds a private key to the list of keys available for decryption and signatures :return: Boolean - Whether the key is already in the list """ new_key = RSAKey(key=import_rsa_key(private_key), kid=self.__generate_key_id(private_key)) for key in self.issuer_private_keys: if new_key.kid == key.kid: return False self.issuer_private_keys.append(new_key) self.loaded_issuer_private_keys[new_key.kid] = PKCS1_OAEP.new( RSA.importKey(private_key)) return True
def __create_jwt(self): if self.jks_path != None: _rsajwk = RSAKey(kid=self._kid, key=import_rsa_key_from_file(self.jks_path)) else: _rsajwk = RSAKey(kid=self._kid, key=import_rsa_key(self.__getRSAPrivateKey())) _payload = { "iss": self.client_id, "sub": self.client_id, "aud": self.__TOKEN_ENDPOINT, "jti": datetime.datetime.today().strftime('%Y%m%d%s'), "exp": int(time.time()) + 3600 } _jws = JWS(_payload, alg="RS256") return _jws.sign_compact(keys=[_rsajwk])
def _extract_x509_certificates(x509_certificates): keys = [] for kid, certificate in x509_certificates.iteritems(): try: if certificate.startswith(jwk.PREFIX): # The certificate is PEM-encoded der = ssl.PEM_cert_to_DER_cert(certificate) key = jwk.der2rsa(der) else: key = jwk.import_rsa_key(certificate) except Exception as exception: raise UnauthenticatedException(u"Cannot load X.509 certificate", exception) rsa_key = jwk.RSAKey().load_key(key) rsa_key.kid = kid keys.append(rsa_key) return keys
def clientPayloadCreation(self, clientName, grantTypes, redirectURIs, logoutURI, responseTypes, scopes, sectorIdentifier, token_endpoint_auth_method, useJWT=0): # Check the auth method is allowed by Auth Server. # Since this value can change dynamically, we check it each time this function is called. allowed_auth_methods = self.wkh.get( TYPE_OIDC, KEY_OIDC_SUPPORTED_AUTH_METHODS_TOKEN_ENDPOINT) if token_endpoint_auth_method not in allowed_auth_methods: raise Exception("Auth method '" + token_endpoint_auth_method + "' is not currently allowed by Auth Server: " + str(allowed_auth_methods)) payload = "{ \"client_name\": \"" + clientName + "\", \"grant_types\":[" for grant in grantTypes: payload += "\"" + grant.strip() + "\", " payload = payload[:-2] + "], \"redirect_uris\" : [" for uri in redirectURIs: payload += "\"" + uri.strip() + "\", " payload = payload[: -2] + "], \"post_logout_redirect_uris\": [\"" + logoutURI + "\"], \"scope\": \"" for scope in scopes: payload += scope.strip() + " " payload = payload[:-1] + "\", " if sectorIdentifier is not None: payload += "\"sector_identifier_uri\": " payload += "\"" + sectorIdentifier.strip() + "\", " payload = payload[:-2] + ", " payload += "\"response_types\": [ " for response in responseTypes: payload += "\"" + response.strip() + "\", " payload = payload[:-2] + "]" if useJWT == 1: payload += ", \"jwks\": {\"keys\": [ " + str( RSAKey(kid=self._kid, key=import_rsa_key(self.__getRSAPublicKey()))) + "]}" payload += ", \"token_endpoint_auth_method\": \"" + token_endpoint_auth_method + "\"" payload += "}" return payload
def _cache_public_key(self, kid, public_key): """ Generate an RSAKey with the public key, and store within the public key cache. This only occurs if an RSAKey has not already been cached for the given `kid` and public key. :param kid: string of the `kid` :param public_key: string of the public key :return: """ if not self._public_key_cache.get(kid): try: rsa_key = RSAKey(key=import_rsa_key(public_key), kid=kid) except (TypeError, ValueError): raise UnexpectedAPIResponse("RSA parsing error for public key" ": %s" % public_key) self._public_key_cache[kid] = rsa_key
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 api_public_keys(self): """The public key retrieved from the LaunchKey API. The result is cached for API_CACHE_TIME""" now = int(time()) if self._api_public_keys[ 1] is None or now - self._api_public_keys[1] > API_CACHE_TIME: response = self.get("/public/v3/public-key", None) try: key = RSAKey(key=import_rsa_key(response.data), kid=response.headers.get('X-IOV-KEY-ID')) except (IndexError, TypeError): raise UnexpectedAPIResponse( "Unexpected api public key received: %s" % response.data) except ValueError: raise UnexpectedAPIResponse( "Unexpected api public key received, RSA parsing error: %s" % response.data) if key not in self._api_public_keys[0]: self._api_public_keys[0].append(key) self._api_public_keys = self._api_public_keys[0], now return self._api_public_keys[0]
def api_public_keys(self): """ The public key retrieved from the LaunchKey API. The result is cached for API_CACHE_TIME """ now = int(time()) if self._api_public_keys[1] is None \ or now - self._api_public_keys[1] > API_CACHE_TIME: response = self.get("/public/v3/public-key", None) try: key = RSAKey(key=import_rsa_key(response.data), kid=response.headers.get('X-IOV-KEY-ID')) except (IndexError, TypeError): raise UnexpectedAPIResponse( "Unexpected api public key received: %s" % response.data) except ValueError: raise UnexpectedAPIResponse("Unexpected api public key " "received, RSA parsing error" ": %s" % response.data) if key not in self._api_public_keys[0]: self._api_public_keys[0].append(key) self._api_public_keys = self._api_public_keys[0], now return self._api_public_keys[0]
def get(self, request: HttpRequest, application_slug: str) -> HttpResponse: """Show RSA Key data for Provider""" application = get_object_or_404(Application, slug=application_slug) provider: OAuth2Provider = get_object_or_404( OAuth2Provider, pk=application.provider_id) response_data = {} if provider.jwt_alg == JWTAlgorithms.RS256: public_key = import_rsa_key(provider.rsa_key.key_data).publickey() response_data["keys"] = [{ "kty": "RSA", "alg": "RS256", "use": "sig", "kid": provider.rsa_key.kid, "n": long_to_base64(public_key.n), "e": long_to_base64(public_key.e), }] response = JsonResponse(response_data) response["Access-Control-Allow-Origin"] = "*" return response
def create_signed_sws(sws_data, pem): sws = SWSMessage(**sws_data) rsa_key = import_rsa_key(pem) key = [RSAKey().load_key(rsa_key)] alg = 'RS256' return sws.to_jwt(key=key, algorithm=alg)
def create_jwt(payload, p_key): rsajwk = RSAKey(kid="RSA1", key=import_rsa_key(p_key)) jws = JWS(payload, alg="RS256") return jws.sign_compact(keys=[rsajwk])
__TOKEN_ENDPOINT = wkh.get(TYPE_OIDC, KEY_OIDC_TOKEN_ENDPOINT) #Generate ID Token _rsakey = RSA.generate(2048) _private_key = _rsakey.exportKey() _public_key = _rsakey.publickey().exportKey() file_out = open("private.pem", "wb") file_out.write(_private_key) file_out.close() file_out = open("public.pem", "wb") file_out.write(_public_key) file_out.close() _rsajwk = RSAKey(kid='RSA1', key=import_rsa_key(_private_key)) _payload = { "iss": g_config["client_id"], "sub": g_config["client_secret"], "aud": __TOKEN_ENDPOINT, "jti": datetime.datetime.today().strftime('%Y%m%d%s'), "exp": int(time.time())+3600 } _jws = JWS(_payload, alg="RS256") jwt = _jws.sign_compact(keys=[_rsajwk]) #payload = { "resource_scopes":[ "Authenticated"], "icon_uri":"/testResourcePEP", "name":"TestResourcePEP" } headers = { 'content-type': "application/json", "cache-control": "no-cache", "Authorization": "Bearer filler" } res = requests.get("http://localhost:5566/resources/1b107ef3-36f3-44d1-adb4-fe6a073d5db", headers=headers, verify=False) print(res.status_code) print(res.text)