def test_automatic_registration_new_client_id(self): _registration_service = self.service['registration'] # This is cheating. Getting the OP's provider info _fe = _registration_service.client_get( "service_context").federation_entity statement = TrustChain() statement.metadata = self.registration_endpoint.server_get( "endpoint_context").provider_info statement.anchor = "https://feide.no" statement.verified_chain = [{'iss': "https://ntnu.no"}] self.service['discovery'].update_service_context([statement]) # and the OP's federation keys self.rp_federation_entity.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=self.registration_endpoint.server_get( "endpoint_context").provider_info['issuer']) _context = self.service['authorization'].client_get("service_context") _context.issuer = 'https://op.ntnu.no' _context.redirect_uris = ['https://foodle.uninett.no/callback'] _context.entity_id = self.rp_federation_entity.entity_id # _context.client_id = self.rp_federation_entity.entity_id _context.behaviour = {'response_types': ['code']} _context.provider_info = self.authorization_endpoint.server_get( "endpoint_context").provider_info # The client not registered and the OP not supporting automatic client registration with pytest.raises(OtherError): self.service['authorization'].construct()
def test_pushed_auth_urlencoded(self): # since all endpoint used the same endpoint_context I can grab anyone _op_context = self.registration_endpoint.server_get("endpoint_context") # This is cheating. Getting the OP's provider info _fe = self.registration_service.client_get("service_context").federation_entity trust_chain = TrustChain() trust_chain.metadata = _op_context.provider_info trust_chain.anchor = "https://feide.no" trust_chain.verified_chain = [{'iss': "https://ntnu.no"}] self.discovery_service.update_service_context([trust_chain]) # and the OP's federation keys _op_context.federation_entity.context.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=_op_context.provider_info['issuer']) # Add RP's OIDC keys to the OP's keyjar. _op_context.keyjar.import_jwks( self.discovery_service.client_get("service_context").keyjar.export_jwks(issuer_id=""), RP_ENTITY_ID ) authn_request = AuthorizationRequest( response_type="code", state="af0ifjsldkj", client_id=RP_ENTITY_ID, redirect_uri="{}/callback".format(RP_ENTITY_ID), code_challenge="K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U", code_challenge_method="S256", scope=["ais", "openid"] ) # Create the private_key_jwt assertion _jwt = JWT(self.registration_service.client_get("service_context").keyjar, iss=RP_ENTITY_ID, sign_alg="RS256") _jwt.with_jti = True _assertion = _jwt.pack( { "aud": [_op_context.provider_info["pushed_authorization_request_endpoint"]] }) authn_request.update({"client_assertion": _assertion, "client_assertion_type": JWT_BEARER}) _req = self.pushed_authorization_endpoint.parse_request(authn_request) assert isinstance(_req, AuthorizationRequest) assert set(_req.keys()) == { "state", "redirect_uri", "response_type", "scope", "code_challenge_method", "client_id", "code_challenge", "client_assertion", "client_assertion_type", '__verified_client_assertion' } # Should have a registered client now assert set(_op_context.cdb.keys()) == {RP_ENTITY_ID}
def test_explicit_registration(self): _registration_service = self.service['registration'] # Using the RP's federation entity instance _fe = _registration_service.client_get( "service_context").federation_entity _endpoint_context = self.registration_endpoint.server_get( "endpoint_context") # This is cheating. Getting the OP provider info trust_chain = TrustChain() trust_chain.metadata = _endpoint_context.provider_info trust_chain.anchor = "https://feide.no" trust_chain.verified_chain = [{'iss': "https://ntnu.no"}] with responses.RequestsMock() as rsps: _jwks = self.authorization_endpoint.server_get( "endpoint_context").keyjar.export_jwks_as_json() rsps.add("GET", 'https://op.ntnu.no/static/jwks.json', body=_jwks, adding_headers={"Content-Type": "application/json"}, status=200) self.service['discovery'].update_service_context([trust_chain]) # Fake fetching the key from op.ntnu.no over the net _fe.context.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=_endpoint_context.provider_info['issuer']) # construct the client registration request req_args = { 'entity_id': _fe.context.entity_id, 'redirect_uris': ['https://foodle.uninett.no/cb'] } _fe.context.proposed_authority_hints = ['https://ntnu.no'] jws = _registration_service.construct(request_args=req_args) # THe OP handles the registration request res = self.registration_endpoint.process_request(jws) assert res reg_resp = self.registration_endpoint.do_response(**res) assert set(reg_resp.keys()) == { 'response', 'response_code', 'http_headers', 'cookie' } # The RP parses the OP's response args = _registration_service.parse_response(reg_resp['response'], request=jws) assert set(args.keys()) == { 'entity_id', 'client_id', 'contacts', 'application_type', 'redirect_uris', 'response_types', 'client_id_issued_at', 'client_secret', 'grant_types', 'client_secret_expires_at' }
def test_explicit_registration(self): _registration_service = self.service['registration'] # Using the RP's federation entity instance _fe = _registration_service.client_get( "service_context").federation_entity _endpoint_context = self.registration_endpoint.server_get( "endpoint_context") # This is cheating. Getting the OP provider info trust_chain = TrustChain() trust_chain.metadata = _endpoint_context.provider_info trust_chain.anchor = "https://feide.no" trust_chain.verified_chain = [{'iss': "https://ntnu.no"}] self.service['discovery'].update_service_context([trust_chain]) # add the OP's federation keys self.rp_federation_entity.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=_endpoint_context.provider_info['issuer']) # construct the client registration request req_args = { 'entity_id': self.rp_federation_entity.entity_id, 'redirect_uris': ['https://foodle.uninett.no/cb'] } self.rp_federation_entity.proposed_authority_hints = [ 'https://ntnu.no' ] jws = _registration_service.construct(request_args=req_args) assert jws # THe OP handles the registration request res = self.registration_endpoint.process_request(jws) assert res reg_resp = self.registration_endpoint.do_response(**res) assert set(reg_resp.keys()) == {'response', 'http_headers', 'cookie'} # The RP parses the OP's response args = _registration_service.parse_response(reg_resp['response'], request=jws) assert set(args.keys()) == { 'entity_id', 'client_id', 'contacts', 'application_type', 'redirect_uris', 'response_types', 'client_id_issued_at', 'client_secret', 'grant_types', 'client_secret_expires_at' }
def eval_chain(chain, key_jar, entity_type, apply_policies=True): """ :param chain: A chain of entity statements :param key_jar: A :py:class:`cryptojwt.key_jar.KeyJar` instance :param entity_type: Which type of metadata you want returned :param apply_policies: Apply policies to the metadata or not :returns: A TrustChain instances """ logger.debug("Evaluate trust chain") ves = verify_trust_chain(chain, key_jar) if not ves: return None tp_exp = trust_chain_expires_at(ves) statement = TrustChain(exp=tp_exp, verified_chain=ves) if apply_policies: if len(ves) > 1: # Combine the metadata policies from the trust root and all intermediates combined_policy = gather_policies(ves[:-1], entity_type) logger.debug("Combined policy: %s", combined_policy) try: metadata = ves[-1]['metadata'][entity_type] except KeyError: statement.metadata = None else: # apply the combined metadata policies on the metadata statement.metadata = apply_policy(metadata, combined_policy) logger.debug("After applied policy: %s", statement.metadata) statement.combined_policy = combined_policy else: statement.metadata = ves[0]["metadata"][entity_type] statement.combined_policy = {} else: # accept what ever is in the statement provided by the leaf entity statement.metadata = ves[-1] iss_path = [x['iss'] for x in ves] statement.anchor = iss_path[0] iss_path.reverse() statement.iss_path = iss_path return statement
def test_automatic_registration_keep_client_id(self): # This is cheating. Getting the OP provider info _registration_service = self.service['registration'] _fe = _registration_service.client_get( "service_context").federation_entity statement = TrustChain() statement.metadata = self.registration_endpoint.server_get( "endpoint_context").provider_info statement.anchor = "https://feide.no" statement.verified_chain = [{'iss': "https://ntnu.no"}] self.service['discovery'].update_service_context([statement]) # and the OP's federation keys self.rp_federation_entity.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=self.registration_endpoint.server_get( "endpoint_context").provider_info['issuer']) service_context = self.service['authorization'].client_get( "service_context") service_context.issuer = 'https://op.ntnu.no' service_context.redirect_uris = ['https://foodle.uninett.no/callback'] service_context.entity_id = self.rp_federation_entity.entity_id service_context.client_id = self.rp_federation_entity.entity_id service_context.behaviour = {'response_types': ['code']} service_context.provider_info = self.authorization_endpoint.server_get( "endpoint_context").provider_info authn_request = self.service['authorization'].construct() # Have to provide the OP with clients keys self.authorization_endpoint.server_get( "endpoint_context").keyjar.import_jwks( _registration_service.client_get( "service_context").keyjar.export_jwks(), ENTITY_ID) _auth_endp_context = self.authorization_endpoint.server_get( "endpoint_context") # get rid of the earlier client registrations for k in _auth_endp_context.cdb.keys(): del _auth_endp_context.cdb[k] # Have to provide the OP with clients keys _auth_endp_context.keyjar.import_jwks( _registration_service.client_get( "service_context").keyjar.export_jwks(), ENTITY_ID) # set new_id to False self.authorization_endpoint.automatic_registration_endpoint.kwargs[ "new_id"] = False # THe OP handles the authorization request req = self.authorization_endpoint.parse_request( authn_request.to_dict()) assert "response_type" in req # reg_resp = self.registration_endpoint.do_response(**res) # assert set(reg_resp.keys()) == {'response', 'http_headers', 'cookie'} client_ids = list(_auth_endp_context.cdb.keys()) assert len(client_ids) == 1 assert client_ids[0] == ENTITY_ID
def test_automatic_registration_new_client_id(self): _registration_service = self.service['registration'] self.authorization_endpoint.server_get( "endpoint_context" ).provider_info['client_registration_authn_methods_supported'] = { "ar": ['request_object'] } self.authorization_endpoint.automatic_registration_endpoint.kwargs[ 'new_id'] = True # This is cheating. Getting the OP's provider info _fe = _registration_service.client_get( "service_context").federation_entity statement = TrustChain() statement.metadata = self.registration_endpoint.server_get( "endpoint_context").provider_info statement.anchor = "https://feide.no" statement.verified_chain = [{'iss': "https://ntnu.no"}] with responses.RequestsMock() as rsps: _jwks = self.authorization_endpoint.server_get( "endpoint_context").keyjar.export_jwks() rsps.add("GET", 'https://op.ntnu.no/static/jwks.json', body=_jwks, adding_headers={"Content-Type": "application/json"}, status=200) self.service['discovery'].update_service_context([statement]) # and the OP's federation keys self.rp_federation_entity.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=self.registration_endpoint.server_get( "endpoint_context").provider_info['issuer']) _context = self.service['authorization'].client_get("service_context") _context.issuer = 'https://op.ntnu.no' _context.redirect_uris = ['https://foodle.uninett.no/callback'] _context.entity_id = self.rp_federation_entity.entity_id _context.client_id = self.rp_federation_entity.entity_id _context.behaviour = {'response_types': ['code']} _context.provider_info = self.authorization_endpoint.server_get( "endpoint_context").provider_info authn_request = self.service['authorization'].construct() # Have to provide the OP with clients keys self.authorization_endpoint.server_get( "endpoint_context").keyjar.import_jwks( _registration_service.client_get( "service_context").keyjar.export_jwks(), ENTITY_ID) # The OP handles the authorization request req = self.authorization_endpoint.parse_request( authn_request.to_dict()) assert "response_type" in req client_ids = list( self.authorization_endpoint.server_get( "endpoint_context").cdb.keys()) assert len(client_ids) == 2 # dynamic and entity_id assert ENTITY_ID in client_ids