diff --git a/maap_jupyter/maap_utils/L1_MSI_pixel_value_Composite_123.tif b/maap_jupyter/maap_utils/L1_MSI_pixel_value_Composite_123.tif
index 5447e95147c80263594956abd221e88699450e74..196d9a657e5be335fd1a8828f1b548908f3b4770 100644
Binary files a/maap_jupyter/maap_utils/L1_MSI_pixel_value_Composite_123.tif and b/maap_jupyter/maap_utils/L1_MSI_pixel_value_Composite_123.tif differ
diff --git a/maap_jupyter/maap_utils/__pycache__/maap_authenticator.cpython-310.pyc b/maap_jupyter/maap_utils/__pycache__/maap_authenticator.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2a41a6ea83c4aca778f723e844bbc89b51d4924d
Binary files /dev/null and b/maap_jupyter/maap_utils/__pycache__/maap_authenticator.cpython-310.pyc differ
diff --git a/maap_jupyter/maap_utils/__pycache__/maap_wpst.cpython-310.pyc b/maap_jupyter/maap_utils/__pycache__/maap_wpst.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6a3a1eaa8eb27f2ec9c4b2bc40fe32810da25cdd
Binary files /dev/null and b/maap_jupyter/maap_utils/__pycache__/maap_wpst.cpython-310.pyc differ
diff --git a/maap_jupyter/maap_utils/maap_authenticator.py b/maap_jupyter/maap_utils/maap_authenticator.py
new file mode 100644
index 0000000000000000000000000000000000000000..24b94b6a56dd02add5bd109136cf618b439a6f85
--- /dev/null
+++ b/maap_jupyter/maap_utils/maap_authenticator.py
@@ -0,0 +1,140 @@
+import configparser
+import requests
+import json
+import base64
+import hashlib
+import re
+from bs4 import BeautifulSoup
+from urllib.parse import urlparse
+from urllib.parse import parse_qs
+import os
+
+
+class MaapAuthenticator(object):
+
+    def __init__(self,auth_config_path,maap_config_path) -> None:
+
+        config = configparser.ConfigParser()
+        config.read(auth_config_path)
+
+        #Retrieve auth values
+        self.login = config['auth']['email']
+        self.password = config['auth']['password']
+
+        config = configparser.ConfigParser()
+        config.read(maap_config_path)
+
+        #Retrieve maap values
+        self.client_id = config['maap']['client_id']
+        self.url_token = config['maap']['url_token']
+
+
+    
+    def get_esa_token_with_esa_cred(self) -> str:
+
+        response = requests.post(self.url_token, data={'client_id': self.client_id, 'username': self.login, 'password': self.password,
+                                                        "grant_type": "password", "scope": "profile"})
+        data = json.loads(response.text)
+        return data['access_token']
+    
+
+    def get_esa_token_with_nasa_cred(self) -> str:
+        
+        session = requests.Session()
+
+        response = session.get("https://auth.val.esa-maap.org/realms/maap/.well-known/openid-configuration")
+        openid_config = json.loads(response.text)
+
+        response = session.get(openid_config["jwks_uri"])
+        certs = json.loads(response.text)
+
+
+
+        code_verifier = base64.urlsafe_b64encode(os.urandom(40)).decode('utf-8')
+        code_verifier = re.sub('[^a-zA-Z0-9]+', '', code_verifier)
+
+        code_challenge = hashlib.sha256(code_verifier.encode('utf-8')).digest()
+        code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8')
+        code_challenge = code_challenge.replace('=', '')
+
+        response = session.get(openid_config["authorization_endpoint"],
+                                params={"redirect_uri":"https://portal.val.esa-maap.org/portal-val/ESA/home",
+                                        "response_type":"code",
+                                        "client_id":"portal",
+                                        "scope":"openid profile offline_access email",
+                                        "code_challenge_method":"S256",
+                                        "code_challenge":code_challenge})
+
+        soup = BeautifulSoup(response.text, 'html.parser')
+        nasa_broker_url = ""
+        for link in soup.find_all('a'):
+            if 'broker/NASA/' in link.get('href'):
+                nasa_broker_url = link.get('href')
+
+        # Click on NASA in keycloak
+        response = session.get("https://auth.val.esa-maap.org"+nasa_broker_url)
+
+        soup = BeautifulSoup(response.text, 'html.parser')
+
+        redirect_url = ""
+        for link in soup.find_all('a'):
+            if'EarthData' in link.text:
+                redirect_url = link.get("href")
+
+
+        # Click on Earth data in CAS
+        response = session.get("https://auth.maap-project.org/cas/"+redirect_url)
+
+        soup = BeautifulSoup(response.text, 'html.parser')
+
+        authenticity_token=""
+        client_id=""
+        redirect_uri=""
+
+        for tag in soup.find_all("input", type="hidden"):
+            if tag.get("name") == "authenticity_token":
+                authenticity_token = tag.get("value")
+            if tag.get("name") == "client_id":
+                client_id = tag.get("value")
+            if tag.get("name") == "redirect_uri":
+                redirect_uri = tag.get("value")
+    
+        
+
+        data_urs = {
+            "authenticity_token": authenticity_token,
+            "username":self.login,
+            "password": self.password,
+            "client_id": client_id,
+            "redirect_uri":redirect_uri,
+            "response_type":"code",
+            }
+
+        # Click on login in URS
+        response = session.post("https://urs.earthdata.nasa.gov/login",data = data_urs)
+
+
+        soup = BeautifulSoup(response.text, 'html.parser')
+
+        for tag in soup.find_all("a", id="redir_link"):
+            redirect_url = tag.get("href")
+
+        # Follow redirection
+        response = session.get(redirect_url)
+
+        parsed_url  = urlparse(response.history[-1].headers['Location'])
+        code = parse_qs(parsed_url.query)['code'][0]
+
+
+
+        response = session.post("https://auth.val.esa-maap.org/realms/maap/protocol/openid-connect/token",
+                                data={
+                                    "grant_type":"authorization_code",
+                                    "code":code,
+                                    "client_id":"portal",
+                                    "code_verifier":code_verifier,
+                                    "redirect_uri":"https://portal.val.esa-maap.org/portal-val/ESA/home"
+                                
+        })
+
+        return json.loads(response.text)['access_token']
diff --git a/maap_jupyter/maap_utils/maap_wpst.py b/maap_jupyter/maap_utils/maap_wpst.py
new file mode 100644
index 0000000000000000000000000000000000000000..e9d832d6d76a2380437e2f01a746ec35a5795e4e
--- /dev/null
+++ b/maap_jupyter/maap_utils/maap_wpst.py
@@ -0,0 +1,114 @@
+import requests
+import json
+import time
+from typing import List
+
+
+class MaapProcess(object):
+
+    def __init__(self,id:str, title:str) -> None:
+        self.id = id
+        self.title = title
+
+class MaapJob(object):
+
+    def __init__(self,p_id:str, job_id:str) -> None:
+        self.p_id = p_id
+        self.job_id = job_id
+        self.status = "NONE"
+
+
+
+class MaapWPST(object):
+
+    def __init__(self,copa_backend_url: str,oauth_token: str) -> None:
+
+        self.copa_backend_url = copa_backend_url
+        self.oauth_token = oauth_token
+        self.process_list = self.__load_process()
+        
+
+
+    def __load_process(self) -> List[MaapProcess]:
+
+        response = requests.get(self.copa_backend_url+'wpst/processes',headers = {'Authorization': 'Bearer '+ self.oauth_token})
+        response.raise_for_status()
+
+        results = []
+        for process_json in response.json()['processes']:
+            results.append(MaapProcess(process_json['id'],process_json['title']))
+
+        return results
+    
+    
+    def job_status(self,maap_job: MaapJob) -> str:
+
+        response = requests.get(self.copa_backend_url+'wpst/processes/'+maap_job.p_id+'/jobs/'+maap_job.job_id,headers = {'Authorization': 'Bearer '+ self.oauth_token})
+        response.raise_for_status()
+
+        res_json = response.json()
+        if 'status' in res_json:
+            result = res_json['status']
+
+        return result
+
+
+    def launch_process(self,title,inputs) -> MaapJob:
+
+        p_id = None
+        for process in self.process_list:
+            if title == process.title:
+                p_id = process.id
+
+        job_id = None
+
+        if p_id is not None:                             
+            payload = {'inputs':inputs,'outputs':[],'mode':'ASYNC','response':'RAW'}
+            response = requests.post(self.copa_backend_url+'wpst/processes/'+p_id+'/jobs',json=payload,headers = {'Authorization': 'Bearer '+ self.oauth_token})
+            response.raise_for_status()
+
+            res_json = response.json()
+
+            if 'jobId' in res_json:
+                job_id = response.json()['jobId']
+
+            
+        else:
+            print("ERROR : Can not launch job for process :"+title+" !")
+
+        return MaapJob(p_id,job_id)
+    
+    def wait_for_final_status(self, maap_job):
+            
+        job_status = 'RUNNING'
+
+        while job_status not in ['SUCCEEDED','FAILED']:
+
+            response = requests.get(self.copa_backend_url+'wpst/processes/{}/jobs/{}'.format(maap_job.p_id, maap_job.job_id),
+                              headers = {'Authorization': 'Bearer '+ self.oauth_token})
+            job_status = json.loads(response.content).get('status')
+            time.sleep(30)
+
+        maap_job.status = job_status
+
+    
+    def write_outputs(self,maap_job, out_dir):
+
+        if maap_job.status == 'SUCCEEDED':
+            result_proc = requests.get('{}wpst/processes/{}/jobs/{}/result'.format(self.copa_backend_url, maap_job.p_id, maap_job.job_id), 
+                               headers = {'Authorization': 'Bearer '+ self.oauth_token})
+            json_res = json.loads(result_proc.content)
+            
+            if 'outputs' in json_res :
+
+                for out in json_res['outputs']:
+                    name = out['href'].split('?')[0].split('/')[-1]
+ 
+                    r =  requests.get(out['href'])
+                    open(out_dir+'/'+name, 'wb').write(r.content)
+    
+    def delete_job(self,maap_job):
+        requests.delete('{}wpst/processes/{}/jobs/{}'.format(self.copa_backend_url, maap_job.p_id, maap_job.job_id),
+                        headers = {'Authorization': 'Bearer '+ self.oauth_token})
+
+