diff --git a/.gitignore b/.gitignore
index 92ba930c3c845d19f6c0381172e7c735a4747002..fd006da959e1846dde839a58b9dc708c1ea8261f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,20 @@ app.key
 key.pem
 openssl.conf
 cert.pem
+
+
+app.csr
+ca.cnf
+ca.crt
+ca.key
+junk/
+pytest.py
+src/app/.tes.service.ts.swn
+src/app/Why Strudel2.md
+src/assets/config/computesites.json.bk
+src/assets/params.json
+src/assets/uischema.json
+src/deployments/mlerp/assets/config/combined.json
+ssl.cnf
+yarnlist.local
+
diff --git a/src/app/accountinfo/accountinfo.component.ts b/src/app/accountinfo/accountinfo.component.ts
index 06bd7502d2a6e7524d73f37d1658fe80b55c8809..27e8d0fd8b0e97eceb02938473827f7de76b8226 100644
--- a/src/app/accountinfo/accountinfo.component.ts
+++ b/src/app/accountinfo/accountinfo.component.ts
@@ -25,7 +25,7 @@ export class AccountinfoComponent implements OnInit {
   }
 
   ngOnInit() {
-    this.identity.accountalerts.subscribe((v) => {console.log('account alerts',v)});
+    //this.identity.accountalerts.subscribe((v) => {console.log('account alerts',v)});
   }
 
   cssClass(h) {
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 6fd338881ccfee12e1c1df03428aab5538750253..d99e53500a166ca02de41cf2ab90c3fb97b7ec49 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -2,8 +2,6 @@ import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
 import { LauncherComponent } from './launcher/launcher.component';
 import { KeygenComponent } from './keygen/keygen.component';
-import { TransferComponent } from './transfer/transfer.component';
-import { ShareconnectComponent } from './shareconnect/shareconnect.component';
 import { JoblistComponent } from './joblist/joblist.component';
 
 import {LoginComponent} from './login/login.component';
@@ -33,7 +31,6 @@ const routes: Routes = [
   //{ path: 'cancellaunch', component: LauncherComponent},
   { path: 'sshauthz_callback', component: KeygenComponent},
   { path: 'sshauthz_callback*', component: KeygenComponent},
-  { path: 'transfer', component: TransferComponent },
   { path: 'noaccount/:site', component: NoaccountComponent},
   { path: '**', component: LauncherComponent},
   //{ path: 'shareconnect', component: ShareconnectComponent }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 815b2b3d6141708d24889de2e00b29aa05702852..334a46ef35f4061051bbe74d33b258f9104a2a01 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -57,9 +57,6 @@ import { MatChipsModule } from '@angular/material/chips';
 import { MatSlideToggleModule } from '@angular/material/slide-toggle';
 import { StrudelapplistComponent } from './strudelapplist/strudelapplist.component';
 import { KeygenComponent } from './keygen/keygen.component';
-import { TransferComponent } from './transfer/transfer.component';
-import { Sv2SideNavComponent } from './sv2-side-nav/sv2-side-nav.component';
-import { ShareconnectComponent } from './shareconnect/shareconnect.component';
 import { LaunchDialogComponent } from './launch-dialog/launch-dialog.component';
 import { ModaldialogComponent } from './modaldialog/modaldialog.component'
 import {OverlayModule} from '@angular/cdk/overlay';
@@ -97,9 +94,6 @@ import { LaunchformComponent } from './launchform/launchform.component';
         // LaunchdialogComponent,
         StrudelapplistComponent,
         KeygenComponent,
-        TransferComponent,
-        Sv2SideNavComponent,
-        ShareconnectComponent,
         LaunchDialogComponent,
         ModaldialogComponent,
         LoginComponent,
diff --git a/src/app/authorisation.service.ts b/src/app/authorisation.service.ts
index 5b4b4e205f261fca549960b3d308b117cb895c8f..25b0f45a014ae3cf70d8126d13dc4a0966b1da41 100644
--- a/src/app/authorisation.service.ts
+++ b/src/app/authorisation.service.ts
@@ -1,7 +1,25 @@
+// Authoriations server
+// On load checks for a session token
+// if a sesiontoken exists get the loggedinauthz/loggedoutauthz observables
+//
+// exposes function updateFragment ... if the fragment is updated, 
+//   1. generate a new key
+//   2. request a certificate
+//   3. add the certificate to the agent
+//  4. update the loggedin/loggedout data
+//
+// exposes function refresh() ... if called, recalculates loggedin/loggedout
+//
+// exposes storeSshAuthZServer ... if called adds a new entry to the possible loggedin/loggedout and stores in localStorage
+//
+// maintains behavioursubject loggedinauthz and loggedin (list and count of sites that we have logged in to/have a valid cert in the agent for)
+// maintains behavioursubject loggedoutauthz and loggedout (list and count of sites that we could log in to)
+
+
 import { Injectable } from '@angular/core';
 import { HttpClientModule, HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
 import { ActivatedRoute, Router } from '@angular/router';
-import { Observable, Subject, BehaviorSubject, concat, forkJoin } from 'rxjs';
+import { Observable, Subject, BehaviorSubject, concat, forkJoin, ReplaySubject } from 'rxjs';
 import { catchError, map, tap, take,filter,skip, switchMap, shareReplay } from 'rxjs/operators';
 import {LocationStrategy, Location} from '@angular/common';
 import { Identity, AuthToken, KeyCert, SshAuthzServer } from './identity';
@@ -20,136 +38,146 @@ export class SshauthzServer {}
   providedIn: 'root'
 })
 export class AuthorisationService {
-  // public token: BehaviorSubject<AuthToken>;
-  //public readonly sshAuthzServers: BehaviorSubject<SshAuthzServer[]>;
-  //public readonly agentContents: BehaviorSubject<any>;
-  //public loggedInAuthZ: BehaviorSubject<SshAuthzServer[]>;
-  //public loggedOutAuthZ: BehaviorSubject<SshAuthzServer[]>;
-  public loggedInAuthZ$: Observable<SshAuthzServer[]>;
-  public loggedOutAuthZ$: Observable<SshAuthzServer[]>;
-  //public progress: Subject<string>;
-  // private keyCert: Subject<KeyCert>;
-  public backendURI: string;
-  public keys: KeyCert[];
-  private fragment$: BehaviorSubject<string> = new BehaviorSubject(null);
-  public agentContents$: Observable<any>;
-  private backendURI$: Observable<string>;
+
+
+  public loggedInAuthZ$: BehaviorSubject<SshAuthzServer[]>;
+  public loggedOutAuthZ$: BehaviorSubject<SshAuthzServer[]>;
   public loggedin$: BehaviorSubject<number>;
   public loggedout$: BehaviorSubject<number>;
-  public sshAuthzServers$: Observable<SshAuthzServer[]>;
-  public refresh$: Subject<boolean> = new Subject();
-  public reAdd$: Subject<any> = new Subject();
+  public sessionToken: string | null = null
+  public availableKeys$: BehaviorSubject<any>;
+
+  private backendURI: string;
+  private fragment$: BehaviorSubject<string> = new BehaviorSubject(null);
+  private sshAuthzServers$: BehaviorSubject<SshAuthzServer[]>;
+  private refresh$: Subject<boolean> = new Subject();
+
+
+
 
 
   constructor(private http: HttpClient,
-              private locationStrategy: LocationStrategy,
               private router: Router, 
               private backendSelectionService: BackendSelectionService,
-              private location: Location, 
               private notifications: NotificationsService,
               private ipcService: IpcService) {
-                
-                //this.sshAuthzServers = new BehaviorSubject<SshAuthzServer[]>([]);
-                //this.loggedInAuthZ = new BehaviorSubject<SshAuthzServer[]>(null);
-                //this.loggedOutAuthZ = new BehaviorSubject<SshAuthzServer[]>([]);
-                this.backendURI = null;
-                //this.agentContents = new BehaviorSubject(null);
-                this.keys = [];
-                //this.getSshAuthzServers();
-                this.keys = [];
-               
-                this.sshAuthzServers$ = this.getSshAuthzServersObservable();
+
+    this.backendURI = null;
+    this.sshAuthzServers$ = new BehaviorSubject<SshAuthzServer[]>(null);
     this.loggedin$= new BehaviorSubject<number>(null);
     this.loggedout$= new BehaviorSubject<number>(null);
-    this.backendSelectionService.apiserver.pipe(
-      filter((v) => v !== null && v !== undefined),
-    )
-      .subscribe((value) => { this.backendURI = value.tes }); // Once we have a value for backend, store that value locally
+    this.loggedInAuthZ$ = new BehaviorSubject<any>([]);
+    this.loggedOutAuthZ$ = new BehaviorSubject<any>([]);
+    this.availableKeys$ = new BehaviorSubject<any>([]);
 
-    // // Once we have backend server, check what our ssh agent has in it
-    // this.backendSelectionService.apiserver.pipe(
-    //   filter((v) => v !== null && v !== undefined),
-    //   tap(() => console.log('backendSelectionService fired causing agent contents to update')),
-    //   switchMap((v) => this.updateAgentContents(v.tes)),
-    // ).subscribe((_) => { return }, (err) => console.error(err));  // An empty subscription is necessary for the observables to fire
+    
+    // Get the list of configured sshauthz servers
+    this.getSshAuthzServersObservable().subscribe((v) => this.sshAuthzServers$.next(v))
 
-    this.backendURI$ = this.backendSelectionService.apiserver.pipe(
+    // every time the backend changes, refresh the list of certs in the agent
+    this.backendSelectionService.apiserver.pipe(
       filter((v) => v !== null && v !== undefined),
-      map((v) => (<APIServer>v).tes)
     )
-
-    this.agentContents$ = this.backendURI$.pipe(
-      tap((v) => console.log('backendURI changed, causing agent contents to update',v)),
-      switchMap((v) => this.updateAgentContents(v)),
+      .subscribe((value) => { this.backendURI = value.tes ; this.refresh() }); // Once we have a value for backend, store that value locally
+    this.backendSelectionService.apiserver.pipe(
       filter((v) => v !== null && v !== undefined),
-      shareReplay()
-    )
-
-
-    /* Once we have a value for agent Conents, and a list of servers, we can figure out which ones we hav elogged into and which ones we haven't */
-
-    var authZ$: Observable<any>;
-    authZ$ = combineLatest([this.agentContents$,this.sshAuthzServers$.pipe(filter((v) => v !== null && v !== undefined))]).pipe(
+      take(1),
+      switchMap((v) => this.getSessionToken(v))
+    ).subscribe((v) => { this.sessionToken = v; window.localStorage.setItem('strudel2_session', v); this.refresh() } );
+    
+    // every time the list of certs/keys changes update the list of whats logged in and out
+    // sshAuthzServers$ won't really "change" except that it needs to be retrieved first time
+    combineLatest([this.availableKeys$, this.sshAuthzServers$.pipe(filter((v) => v !== null ))]).pipe(
       map(([agentContents,authzServers]) => { return this.updateLoggedAuthZ(agentContents,authzServers)}),
-      tap((v) => { this.loggedin$.next(v[0].length); this.loggedout$.next(v[1].length)} ),
-      catchError((e) => { console.error('errort getting values for logged in and out',e); return throwError(e) }),
-      tap((v) => console.log('authZ observable fired')),
-      shareReplay()
-    );
-    //authZ$.subscribe(([loggedin,loggedout]) => { this.loggedInAuthZ.next(loggedin); this.loggedOutAuthZ.next(loggedout);  })
-    this.loggedInAuthZ$ = authZ$.pipe(map((v) => v[0]));
-    this.loggedOutAuthZ$ = authZ$.pipe(map((v) => v[1]));
+    ).subscribe((v) => {this.loggedInAuthZ$.next(v[0]); this.loggedin$.next(v[0].length) ; this.loggedOutAuthZ$.next(v[1]); this.loggedout$.next(v[1].length)})
+
 
-    const apiserver$: Observable<APIServer> = this.backendSelectionService.apiserver.pipe(
-      filter((v) => v !== undefined),filter((v) => v !== null),
-    );
-    combineLatest([this.reAdd$.pipe(
-      filter((v) => v !== undefined && v !== null)), apiserver$]).subscribe(
-      ([id, apiserver]) => { this.addKeysFromStorage(apiserver)})
-    
     this.initKeygenPipelines();
  }
 
- private addKeysFromStorage(apiserver: APIServer) {
-  var req: Observable<any>[] = [] 
-  var keys: KeyCert[];
-  keys = this.getKeys();
-  if (keys.length>0) {
-    for (let k of this.getKeys()) {
-      console.log('addKeysFromStorage',k);
-      req.push(this.sshAdd(k,apiserver))
-    }
-    forkJoin(req).subscribe((v) => { this.refresh$.next(true)})
+//  private addKeysFromStorage(apiserver: APIServer) {
+//   var req: Observable<any>[] = [] 
+//   var keys: KeyCert[];
+//   keys = this.getKeys();
+//   if (keys.length>0) {
+//     for (let k of this.getKeys()) {
+//       console.log('addKeysFromStorage',k);
+//       req.push(this.sshAdd(k,apiserver))
+//     }
+//     forkJoin(req).subscribe((v) => { this.refresh$.next(true)})
+//   } else {
+//     this.refresh$.next(true);
+//   }
+//  }
+ 
+
+ public refresh() {
+  this.refresh$.next(true);
+  if (this.backendURI !== null) {
+    this.updateAgentContents(this.backendURI).subscribe((v) => this.availableKeys$.next(v));
   } else {
-    this.refresh$.next(true);
+    this.backendSelectionService.apiserver.pipe(
+      take(1)
+    ).subscribe((apiserver) => this.updateAgentContents(apiserver.tes).subscribe((v) => this.availableKeys$.next(v)))
   }
  }
- 
- updateFragment(frag) {
-  this.fragment$.next(frag);
- }
 
- storeLocalAuthZ(authz: any) {
+ public storeLocalAuthZ(authz: any) {
+  // called from settings
    try {
      localStorage.setItem('localauthservers',JSON.stringify(authz));
    } catch {
    }
-   //this.getSshAuthzServers();
  }
 
- removeLocalAuthZ() {
+ public removeLocalAuthZ() {
    localStorage.removeItem('localauthservers');
-   //this.getSshAuthzServers();
  }
 
-/*  getSshAuthzServers() {
-   let headers = new HttpHeaders();
-   let options = { headers: headers, withCredentials: false};
-   this.http.get<SshAuthzServer[]>('./assets/config/authservers.json',options)
-                    .pipe(catchError(this.handleError('getSshAuthzServers')))
-                    .subscribe(resp => this.updateSshAuthzServers(resp));
- } */
- getSshAuthzServersObservable(): Observable<SshAuthzServer[]> {
+public updateFragment(frag) {
+  // The second half of login. After we have returned from the authorization server
+  // called from keygen
+  this.fragment$.next(frag);
+ }
+
+
+public logout() {
+  // clear the ssh agent and remove all keys
+  // remove the sessionToken from localstorage and memory
+  // get a new session token
+  sessionStorage.removeItem('keys');
+  return this.killAgent().pipe(
+    tap((v)=>window.localStorage.removeItem('strudel2_session')),
+    tap((v) => this.sessionToken = null),
+    switchMap((v) => this.getSessionToken(this.backendURI))
+  ).
+    subscribe((v) =>{ this.sessionToken = v ; window.localStorage.setItem('strudel2_session',v) ; this.refresh() } )
+}
+
+private getSessionToken(apiserver: any): Observable<any> {
+ console.log('getting the session token eithe rfrom loca sotrage or a new one')
+
+ let access_token = window.localStorage.getItem('strudel2_session');
+ if (access_token) {
+   let headers = new HttpHeaders({
+     'Authorization': `Bearer ${access_token}`
+   })
+   let options = { headers: headers, withCredentials: true};
+   let pipe = this.http.get<any>(apiserver.tes+'/authping', options).pipe(
+     tap((v) => console.log('found a token, refreshing it')),
+     switchMap((v) => this.http.get<any>(apiserver.tes+'/refreshsession', options)),
+     tap((v) => console.log('refreshed the token')),
+     catchError((e) => this.http.get<any>(apiserver.tes+'/newsession'))
+   )
+   return pipe
+ } else {
+  console.log('getting a new token from', apiserver.tes)
+   return this.http.get<any>(apiserver.tes+'/newsession')
+ }
+}
+
+
+ private getSshAuthzServersObservable(): Observable<SshAuthzServer[]> {
   let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: false};
   return this.http.get<SshAuthzServer[]>('./assets/config/authservers.json',options)
@@ -203,69 +231,29 @@ export class AuthorisationService {
      return [loggedin, loggedout]
  }
         
+// private getKeys(id?: Identity): KeyCert[] {
+//   try{
+//     return JSON.parse(sessionStorage.getItem('keys'));
+//   } catch {
+//     return [];
+//   }
+// }
 
- updateSshAuthzServers(resp) {
-   var auths: SshAuthzServer[];
-   var localauths: SshAuthzServer[] = [];
-   var server: SshAuthzServer;
-   auths = <SshAuthzServer[]>resp;
-   try {
-       localauths = JSON.parse(localStorage.getItem('localauthservers'))
-   } catch {
-       localauths = []
-   }
-   if (localauths !== null) {
-       for (server of localauths) {
-           auths.push(server);
-       }
-   }
-   //this.sshAuthzServers.next(auths);
- }
 
-public getKeys(id?: Identity): KeyCert[] {
-  try{
-    return JSON.parse(sessionStorage.getItem('keys'));
-  } catch {
-    return [];
-  }
-}
 
-    /* makeKeyCert(key: string, resp, sshauthzservice: SshAuthzServer) {
-   let keyCert = new KeyCert()
-   keyCert.key = key;
-   keyCert.cert = resp['cert'];
-   var keys: KeyCert[] = [];
-   try{
-     keys = JSON.parse(sessionStorage.getItem('keys'));
-   } catch {
-     keys = [];
-   }
-   if (keys === null) {
-     keys = [];
-   }
-   keys.push(keyCert);
-   sessionStorage.setItem('keys',JSON.stringify(keys))
-   // this.tesService.keyCert.next(keyCert);
-   // As soon as the certificate has been generated, we log back out of the signing server
-   if (!(sshauthzservice.logout === null)) {
-     window.open(sshauthzservice.logout);
-   }
-   let path=sessionStorage.getItem('path');
-   //skip1 because loggedInAuthZ is a behaviour subject and we don't want the current value but the value
-   this.loggedInAuthZ.pipe(skip(1),take(1)).subscribe( () => {this.readyToNavigate.next([true,path])});
-   this.sshAdd(keyCert);
-   // only navigate once the agent contents has been refreshed
- }*/
-
- public querySshAgentError(error: any) {
+ private querySshAgentError(error: any) {
    //this.agentContents.next([]);
    if (error.status == 0) {
      this.notifications.notify("A network error occured. Are you connected to the internet?")
    }
+   if (error.stats == 401) {
+    this.sessionToken = null;
+    console.log('session expired, why hasnt it refreshed automatically?')
+   }
    this.notifications.notify("Error querying ssh agent");
  }
 
-  public updateAgentContents(apiserver?: string): Observable<any> {
+  private updateAgentContents(apiserver: string): Observable<any> {
     /* Query ssh agent running on the apiserver 
      * Tap the even stream to update the notifications 
      */
@@ -282,24 +270,20 @@ public getKeys(id?: Identity): KeyCert[] {
      }
    }
 
-   let headers = new HttpHeaders();
+   if (this.sessionToken === null) {
+    return of([])
+   }
+
+   let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.sessionToken}`
+  });
    let options = { headers: headers, withCredentials: true};
-   var anyvar: any;
    let agentquery$ = this.http.get<any>(apiserver+'/sshagent',options)
    let agentpipe$ = agentquery$.pipe(
      catchError((e) => { this.querySshAgentError(e); return of([])}),
-     switchMap((resp) => of(this.addExpiryField(resp))),
-     tap((resp) => { 
-      //  if (this.agentContents.value !== null && this.agentContents.value.length > resp.length) {
-      //    this.notifications.notify("Your login expired. Please login again");
-      //  } else {
-      //    this.notifications.notify("");
-      //  };
-      this.notifications.notify("");
-      //this.agentContents.next(resp)
-     }),
+     map((v) => this.addExpiryField(v)),
+     tap((resp) => { this.notifications.notify("");}),
      catchError((e) => { console.error('updateAgentContents error',e) ; return of([])}),
-     //tap((_) => this.notifications.notify(""))
      tap((v)=>console.log('agent contents',v))
    )
    return agentpipe$
@@ -320,41 +304,23 @@ public getKeys(id?: Identity): KeyCert[] {
 
  private killAgent() {
    this.notifications.notify("Logging out")
-   let headers = new HttpHeaders();
-   let options = { headers: headers, withCredentials: true};
    var anyvar: any;
+   if (this.sessionToken === null) {
+    return throwError('cant get the agent contents without a session');
+   }
+   let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.sessionToken}`
+  });
+  let options = { headers: headers, withCredentials: true};
+
    return this.http.delete<any>(this.backendURI+'/sshagent',options)
      .pipe(
        catchError(this.handleError(anyvar)),
-       switchMap((v) => this.updateAgentContents()))
-    
+       switchMap((v) => this.updateAgentContents(this.backendURI)),
+       catchError((e) => { return of([])}))
  }
 
- public logout(): Observable<any> {
-   sessionStorage.removeItem('keys');
-   return this.killAgent();
- }
 
- public login(authservice: SshAuthzServer) {
-   let redirect_uri = window.location.origin+this.locationStrategy.getBaseHref()+"sshauthz_callback";
-   if (redirect_uri.includes("file:///")) {
-     redirect_uri = "http://localhost:4200/sshauthz_callback";
-   }
-   let nonce=Math.random().toString(36).substring(2, 15)
-
-   sessionStorage.setItem('authservice', JSON.stringify([authservice,nonce]));
-   sessionStorage.setItem('path', '/launch');
-   if (authservice.scope == null) {
-     window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id);
-   } else {
-     window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id+"&scope="+authservice.scope);
-   }
- }
-
- private httperror(error: any) {
-   this.notifications.notify('There was an error logging in or generating crypto tokens');
-   console.error(error);
- }
 
  private handleError<T> (result?: T) {
    return (error: any): Observable<T> => {
@@ -366,7 +332,10 @@ public getKeys(id?: Identity): KeyCert[] {
    };
  }
 
- initKeygenPipelines() {
+ private initKeygenPipelines() {
+
+    // every time the fragment changes, extract the token
+    // every time the token changes, 
 
     const token$: Observable<AuthToken> = this.fragment$.pipe(
       filter((v) => v !== null),
@@ -397,8 +366,9 @@ public getKeys(id?: Identity): KeyCert[] {
 
     let agent$ = combineLatest([keycert$.pipe(filter((v) => v !== null)),apiserver$]).pipe(
       switchMap(([keycert,apiserver]) => this.addCert(keycert,apiserver)),
+      tap((v) => this.refresh()),
       tap((v)=>console.log('posted cert to agent',v)),
-      switchMap((_) => this.updateAgentContents()),
+      //switchMap((_) => this.updateAgentContents()),
       //switchMap((_) => this.loggedInAuthZ),
       switchMap((_) => of([null])),
     );
@@ -412,7 +382,7 @@ public getKeys(id?: Identity): KeyCert[] {
                                  } )
   }
 
- extractToken(frag: string) {
+ private extractToken(frag: string) {
    if (frag === undefined || frag == null) {
        return;
    }
@@ -437,13 +407,13 @@ public getKeys(id?: Identity): KeyCert[] {
 
  }
 
-  logout_sshauthz(sshauthzserver) {
+  private logout_sshauthz(sshauthzserver) {
    if (sshauthzserver !== undefined && sshauthzserver.logout !== null) {
      window.open(sshauthzserver.logout);
    }
   }
 
-  getCert(token: AuthToken, key: any, apiserver: APIServer): Observable<any> {
+  private getCert(token: AuthToken, key: any, apiserver: APIServer): Observable<any> {
     let headers = new HttpHeaders({'Authorization':'Bearer '+token.token});
     let options = { headers: headers, withCredentials: false};
     var now = new Date()
@@ -458,26 +428,32 @@ public getKeys(id?: Identity): KeyCert[] {
     )
   }
 
-  addCert(kclist: any, apiserver: APIServer): Observable<any> {
+  private addCert(kclist: any, apiserver: APIServer): Observable<any> {
     let keyCert = new KeyCert()
     keyCert.key = kclist[0].private
     keyCert.cert = kclist[1]
-    return this.sshAdd(keyCert,apiserver);
+    this.storeKey(keyCert); 
+     let data = {'key': keyCert.key, 'cert': keyCert.cert};
+      if (this.ipcService.useIpc) {
+        return this.ipcService.addCert(data);
+      } else {
+  
+        if (this.sessionToken === null) {
+          throwError('Session token is null how is this possible')
+        }
+  
+        let headers = new HttpHeaders({
+          'Authorization': `Bearer ${this.sessionToken}`
+        });
+        let options = { headers: headers, withCredentials: true};
+        let data = {'key': keyCert.key, 'cert': keyCert.cert};
+        return this.http.post<any>(apiserver.tes+'/sshagent',data,options);
+
+      }
   }
 
- public sshAdd(keyCert: KeyCert, apiserver): Observable<any> {
-  this.storeKey(keyCert); 
-  let headers = new HttpHeaders();
-   let options = { headers: headers, withCredentials: true};
-   let data = {'key': keyCert.key, 'cert': keyCert.cert};
-    if (this.ipcService.useIpc) {
-      return this.ipcService.addCert(data);
-    } else {
-      return this.http.post<any>(apiserver.tes+'/sshagent',data,options);
-    }
- }
 
-  storeKey(keyCert: KeyCert) {
+  private storeKey(keyCert: KeyCert) {
     var keys: KeyCert[] = [];
     try{
       keys = JSON.parse(sessionStorage.getItem('keys'));
@@ -488,6 +464,10 @@ public getKeys(id?: Identity): KeyCert[] {
       keys = [];
     }
     keys.push(keyCert);
+    if (keys.length > 10) {
+      console.error('keys is growing too fast')
+      keys = keys.slice(-9)
+    }
     sessionStorage.setItem('keys',JSON.stringify(keys))
   }
 
diff --git a/src/app/computesites.service.ts b/src/app/computesites.service.ts
index 10d54677354616aadc3ac809423274d50c8af677..e457387890465d5d31ac0700f5b0e1537b607d28 100644
--- a/src/app/computesites.service.ts
+++ b/src/app/computesites.service.ts
@@ -25,7 +25,7 @@ export class ComputesitesService {
     this.computesites = new BehaviorSubject<Computesite[]>([]);
     this.getComputeSites();
 
-    this.identities$ = combineLatest([this.authorisationService.agentContents$,this.computesites.pipe(filter((v) => v.length !== 0))])
+    this.identities$ = combineLatest([this.authorisationService.availableKeys$,this.computesites.pipe(filter((v) => v.length !== 0))])
                           .pipe( 
                             switchMap((v) => this.combine_cert_site(v[0],v[1]))
                           ) 
diff --git a/src/app/jobs.service.ts b/src/app/jobs.service.ts
index 680cf8ee0ec9761d90ae4ee189160bf1f162611c..573087943aa12fa1ee1e302eddb38febb778cc5f 100644
--- a/src/app/jobs.service.ts
+++ b/src/app/jobs.service.ts
@@ -75,13 +75,9 @@ export class JobsService {
     if (identity.expiry < Date.now() && (error.hasOwnProperty("status") && error.status == 401)) {
       console.error('login expired while refreshing job list expiry',identity.expiry,'current time',Date.now() );
       this.cancelRequests$.next(true);
-      this.notifications.notify("Your login has expired. Please log in again",   () => { this.authService.refresh$.next(true) }  );
+      this.notifications.notify("Your login has expired. Please log in again",   () => { this.authService.refresh() }  );
       return throwError(error);
     }
-    if (identity.expiry > Date.now() && error.hasOwnProperty("status") && error.status == 401) {
-      this.authService.reAdd$.next(identity);
-      return of([]);
-    }
   
     if (error.hasOwnProperty("status") && error.status == 500) {
       this.notifications.notify("The Strudel2 API server had an error.\n Please report this via the contact us link.\nThe error message was"+emsg);
diff --git a/src/app/launcher/launcher.component.ts b/src/app/launcher/launcher.component.ts
index c6adc28aa20d4d3fa6427bc00d61b9a50925a1c8..a1e469c4a425a5d5e7854282ccd7bf205228f5b6 100644
--- a/src/app/launcher/launcher.component.ts
+++ b/src/app/launcher/launcher.component.ts
@@ -72,7 +72,7 @@ export class LauncherComponent implements OnInit {
 
   ngOnInit() {
     this.pipelines();
-    this.sub = this.authService.refresh$.subscribe( () => {this.destroy$.next(true); this.pipelines()})
+    this.sub = this.authService.loggedInAuthZ$.subscribe( () => {this.destroy$.next(true); this.pipelines()})
   }
 
   pipelines() {
diff --git a/src/app/launchform/launchform.component.ts b/src/app/launchform/launchform.component.ts
index 2eb944497a0886d625bbf8e9590c80747981bea4..39b9a892f56409b870281e56446b3a62234798ba 100644
--- a/src/app/launchform/launchform.component.ts
+++ b/src/app/launchform/launchform.component.ts
@@ -1,13 +1,14 @@
 import { Component, EventEmitter, Input, Output } from '@angular/core';
 import { angularMaterialRenderers } from '@jsonforms/angular-material';
 import { and, createAjv, isControl, optionIs, rankWith, schemaTypeIs, scopeEndsWith, Tester } from '@jsonforms/core';
-import { Observable } from 'rxjs';
-import { tap} from 'rxjs/operators';
+import { Observable, of, throwError } from 'rxjs';
+import { catchError, tap} from 'rxjs/operators';
 import { TesService } from '../tes.service';
 import { Strudelapp, AppAction } from '../strudelapp';
 import { Job } from '../job';
 import { BatchInterface } from '../batchinterface';
 import { Identity } from '../identity';
+import { HttpErrorResponse } from '@angular/common/http';
 
 
 
@@ -47,9 +48,33 @@ export class LaunchformComponent {
 
   }
 
+  private handleLaunchFormError(e: HttpErrorResponse): Observable<any> {
+    const errordataschema: any = {
+      "properties": {
+          "msg": {
+              "default": "Something went wrong",
+              "title": "Msg",
+              "type": "string"
+          }
+      },
+      "title": "ErrorMsg",
+      "type": "object"
+    };
+    const erroruischema: any = {
+      "type": "Control",
+      "scope": "#"
+    };
+    if (e.status == 500) {
+      return of({'schema': errordataschema, 'uischema': erroruischema, 'data': {'msg': e.message}})
+    }
+    throwError(e)
+  }
+
   ngOnInit(): void {
+  
     this.schemaObs$ = this.tes.runCommand(this.identity, this.app.submitcmd, {'input': ""}).pipe(
       tap((v) => console.log(v)),
+      catchError((e) => this.handleLaunchFormError(e)),
       tap((v) => { this.schema = v.schema ; this.uischema = v.uischema; this.data = v.data }),
       tap(() => {console.log('data for the form is set to ',this.data)})
     )
diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts
index 7b00d4a37662faf9350c900f0c7df2eb1cbd863f..ee1f9f5d601d4db76bd1c617202ddbed87d35e9c 100644
--- a/src/app/login/login.component.ts
+++ b/src/app/login/login.component.ts
@@ -18,7 +18,7 @@ import { IpcService } from '../ipc.service';
 
 import {DomSanitizer} from '@angular/platform-browser';
 import {PipeTransform, Pipe} from "@angular/core";
-import { ThisReceiver } from '@angular/compiler';
+import { LocationStrategy } from '@angular/common';
 
 @Pipe({ name: 'safeHtml'})
 export class SafeHtmlPipe implements PipeTransform  {
@@ -52,6 +52,7 @@ export class LoginComponent implements OnInit {
                 public overlayContainer: OverlayContainer,
                 private router: Router,
                 private ipcService: IpcService,
+                private locationStrategy: LocationStrategy,
                 ) {
 
 
@@ -90,9 +91,28 @@ export class LoginComponent implements OnInit {
   }
  */
 
-  login () {
+//  login () {
     //localStorage.setItem('strudel-navlaunch','true');
-    this.authService.login(this.selected);
+    //this.authService.login(this.selected);
+//  }
+
+  public login() {
+    let authservice = this.selected;
+    // Initiate Login
+    let redirect_uri = window.location.origin+this.locationStrategy.getBaseHref()+"sshauthz_callback";
+    if (redirect_uri.includes("file:///")) {
+      redirect_uri = "http://localhost:4200/sshauthz_callback";
+    }
+    let nonce=Math.random().toString(36).substring(2, 15)
+  
+    sessionStorage.setItem('authservice', JSON.stringify([authservice,nonce]));
+    sessionStorage.setItem('path', '/launch');
+    if (authservice.scope == null) {
+      window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id);
+    } else {
+      window.location.assign(authservice.authorise+"?response_type=token&redirect_uri="+redirect_uri+"&state="+nonce+"&client_id="+authservice.client_id+"&scope="+authservice.scope);
+    }
   }
+
 }
 
diff --git a/src/app/logout/logout.component.ts b/src/app/logout/logout.component.ts
index d9e2f54be9191c28c092239edf29412c1572615b..80d6476694fdf2dac51f1eb8df0e84161adf22cf 100644
--- a/src/app/logout/logout.component.ts
+++ b/src/app/logout/logout.component.ts
@@ -2,6 +2,8 @@ import { Component, OnInit } from '@angular/core';
 import { Router, NavigationStart } from '@angular/router';
 
 import { AuthorisationService } from '../authorisation.service';
+import { catchError } from 'rxjs/operators';
+import { of } from 'rxjs';
 
 @Component({
   selector: 'app-logout',
@@ -20,8 +22,8 @@ export class LogoutComponent implements OnInit {
   }
 
   logout() {
-    this.authService.logout().subscribe(() => this.router.navigate(['/login']));
-    //this.router.navigate(['/login']);
+    this.authService.logout();
+    this.authService.loggedInAuthZ$.subscribe(() => this.router.navigate(['/login']));
   }
 
 }
diff --git a/src/app/noaccount/noaccount.component.ts b/src/app/noaccount/noaccount.component.ts
index 02be12ec12d65f8912972448517b8d1e312d98d7..3f534508056ad01b13af60355fafa6c5bde6ea4f 100644
--- a/src/app/noaccount/noaccount.component.ts
+++ b/src/app/noaccount/noaccount.component.ts
@@ -21,7 +21,7 @@ export class NoaccountComponent implements OnInit {
   }
 
   ngOnInit() {
-    this.subscription = combineLatest([ this.route.paramMap.pipe(filter((v) => v !== null)), this.authService.sshAuthzServers$.pipe(filter((v) => v !== null))])
+    this.subscription = combineLatest([ this.route.paramMap.pipe(filter((v) => v !== null)), this.authService.loggedOutAuthZ$.pipe(filter((v) => v !== null))])
                             .subscribe(([m,s]) => this.setSite(m,s));
   }
   
diff --git a/src/app/shareconnect/shareconnect.component.css b/src/app/shareconnect/shareconnect.component.css
deleted file mode 100644
index 683ae23faeb400f1a70bacba6e68504c296bc4ef..0000000000000000000000000000000000000000
--- a/src/app/shareconnect/shareconnect.component.css
+++ /dev/null
@@ -1,3 +0,0 @@
-:host {
-  height: 100%;
-}
diff --git a/src/app/shareconnect/shareconnect.component.html b/src/app/shareconnect/shareconnect.component.html
deleted file mode 100644
index c80d908b49e1ca8b4d7f01fb4d1b8fdff2bfadb3..0000000000000000000000000000000000000000
--- a/src/app/shareconnect/shareconnect.component.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<div fxFlex style="flex: 1 1 0%; box-sizing: border-box">
-<div fxLayout="column" fxLayoutAlign="space-around stretch" style="height: 100%; width: 100%" >
-    <mat-toolbar color="primary">
-      <mat-toolbar-row>
-          <!--<button mat-icon-button (click)=idSideNav.toggle()><mat-icon>menu</mat-icon></button>-->
-
-        <span>Strudel v2.0</span>
-        <span class="fill-horizontal-space"></span>
-      </mat-toolbar-row>
-    </mat-toolbar>
-
-<mat-sidenav-container #idSideNav autosize style="height: 100%; width: 100%">
-  <mat-sidenav #idSideNav mode="side" opened>
-      <app-sv2-side-nav></app-sv2-side-nav>
-  </mat-sidenav>
-
-    <div fxLayout="column" fxLayoutAlign="none" style="height: 100%; width: 100%">
-
-    <!-- <div style="height: 600px"></div> -->
-      <form>
-        <mat-form-field style="width: 100%; height: 100%">
-          <textarea fxFlex matInput placeholder="Paste the data sent via email" style="width: 100%; height: 100%" [(ngModel)]="data" name="data"></textarea>
-        </mat-form-field>
-      </form>
-
-    <div  style="width: 100%" fxLayout="row" fxLayoutAlign="none">
-      <div fxFlex></div>
-      <button mat-button (click)="onSubmit()">Connect</button>
-      <div fxFlex></div>
-    </div>
-  </div>
-
-
-
-    <!-- <mat-card style="width: 100%; box-sizing: border-box">Transfer tasks</mat-card> -->
-</mat-sidenav-container>
-</div>
-</div>
diff --git a/src/app/shareconnect/shareconnect.component.spec.ts b/src/app/shareconnect/shareconnect.component.spec.ts
deleted file mode 100644
index faea16e7afa4891ff43e14a3fe573f72afd4d2d4..0000000000000000000000000000000000000000
--- a/src/app/shareconnect/shareconnect.component.spec.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-
-import { ShareconnectComponent } from './shareconnect.component';
-
-describe('ShareconnectComponent', () => {
-  let component: ShareconnectComponent;
-  let fixture: ComponentFixture<ShareconnectComponent>;
-
-  beforeEach(waitForAsync(() => {
-    TestBed.configureTestingModule({
-      declarations: [ ShareconnectComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(ShareconnectComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/src/app/shareconnect/shareconnect.component.ts b/src/app/shareconnect/shareconnect.component.ts
deleted file mode 100644
index f1bea48d6e5b436be6a21d1cd35f9c514d26ce16..0000000000000000000000000000000000000000
--- a/src/app/shareconnect/shareconnect.component.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Strudelapp } from '../strudelapp';
-import { TesService } from '../tes.service';
-import { AuthorisationService } from '../authorisation.service';
-import { Computesite } from '../computesite';
-import { ComputesitesService } from '../computesites.service';
-import { Router } from '@angular/router';
-import { Job } from '../job';
-import { Subscription } from 'rxjs';
-import {Identity, KeyCert} from '../identity';
-
-
-@Component({
-  selector: 'app-shareconnect',
-  templateUrl: './shareconnect.component.html',
-  styleUrls: ['./shareconnect.component.css']
-})
-export class ShareconnectComponent implements OnInit {
-
-  data: string = "";
-  invalid: boolean = false;
-  subscription: Subscription;
-  constructor(private computesitesService: ComputesitesService,
-              private tesService: TesService,
-              private authService: AuthorisationService,
-              private router: Router) { }
-
-  ngOnInit() {
-    setTimeout( () => this.authService.updateAgentContents() )
-  }
-
-  connect(jobdata: Job) {
-    //this.tesService.connect(jobdata);
-  }
-
-  onSubmit() {
-    var dataobject: Object;
-    var jobdata: Job;
-    var site: Computesite;
-    var id: Identity;
-    try {
-      dataobject = JSON.parse(this.data);
-      jobdata = <Job>dataobject['job'];
-      site = <Computesite>dataobject['site'];
-      id = <Identity>dataobject['identity'];
-      id.site = site;
-      jobdata.identity = new Identity(id.username, site, id.expiry);
-
-      let keycert = dataobject['keycert'];
-      if (keycert !== null) {
-        this.subscription = this.authService.agentContents$.subscribe(() => this.connect(jobdata))
-        //this.authService.sshAdd(keycert);
-      } else {
-        this.connect(jobdata);
-      }
-      this.invalid=false;
-    } catch {
-      if (this.subscription !== undefined) {
-        this.subscription.unsubscribe();
-      }
-      this.invalid=true;
-    }
-  }
-
-}
diff --git a/src/app/sv2-side-nav/sv2-side-nav.component.css b/src/app/sv2-side-nav/sv2-side-nav.component.css
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/app/sv2-side-nav/sv2-side-nav.component.html b/src/app/sv2-side-nav/sv2-side-nav.component.html
deleted file mode 100644
index 3fd6edc304c3496af54a5b87124ee1f4318c2b0a..0000000000000000000000000000000000000000
--- a/src/app/sv2-side-nav/sv2-side-nav.component.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!-- <mat-accordion> -->
-<mat-expansion-panel>
-  <mat-expansion-panel-header>
-    <mat-panel-title>
-    More Services
-  </mat-panel-title>
-  </mat-expansion-panel-header>
-  <div *ngFor="let sshauthzserver of (authService.loggedInAuthZ$ | async)" style="width: 100%">
-      <button mat-button (click) =logout()>Logout {{ sshauthzserver.name }}</button>
-  </div>
-  <div *ngFor="let sshauthzserver of (authService.loggedOutAuthZ$ | async)" style="width: 100%">
-      <button mat-button (click)=login(sshauthzserver) fxFlex style="text-align: left"> Run on {{ sshauthzserver.name }}</button>
-      <button mat-icon-button *ngIf="sshauthzserver.userdefined === true"><mat-icon>remove</mat-icon></button>
-  </div>
-  <div style="width: 100%">
-      <button mat-button (click) ="authService.updateAgentContents()"> Refresh </button>
-  </div>
-</mat-expansion-panel>
-<!-- </mat-accordion> -->
diff --git a/src/app/sv2-side-nav/sv2-side-nav.component.spec.ts b/src/app/sv2-side-nav/sv2-side-nav.component.spec.ts
deleted file mode 100644
index 97de6bd25450a1d151558df33ed8fc869c823a4c..0000000000000000000000000000000000000000
--- a/src/app/sv2-side-nav/sv2-side-nav.component.spec.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-
-import { Sv2SideNavComponent } from './sv2-side-nav.component';
-
-describe('Sv2SideNavComponent', () => {
-  let component: Sv2SideNavComponent;
-  let fixture: ComponentFixture<Sv2SideNavComponent>;
-
-  beforeEach(waitForAsync(() => {
-    TestBed.configureTestingModule({
-      declarations: [ Sv2SideNavComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(Sv2SideNavComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/src/app/sv2-side-nav/sv2-side-nav.component.ts b/src/app/sv2-side-nav/sv2-side-nav.component.ts
deleted file mode 100644
index 212c88cbddffc1a2d828d36852ad146c38b1ee07..0000000000000000000000000000000000000000
--- a/src/app/sv2-side-nav/sv2-side-nav.component.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatDialogModule, MatDialogConfig } from '@angular/material/dialog';
-
-import { AuthorisationService } from '../authorisation.service';
-import { LogoutdialogComponent } from '../logoutdialog/logoutdialog.component';
-
-
-@Component({
-  selector: 'app-sv2-side-nav',
-  templateUrl: './sv2-side-nav.component.html',
-  styleUrls: ['./sv2-side-nav.component.css']
-})
-export class Sv2SideNavComponent implements OnInit {
-
-  constructor(public authService: AuthorisationService,  public dialog: MatDialog,) { }
-
-  ngOnInit() {
-  }
-  logout() {
-      let dialogRef = this.dialog.open(LogoutdialogComponent, {
-        width: '250px',
-        height: '400px',
-      });
-  }
-
-  login (sshauthzserver) {
-    this.authService.login(sshauthzserver);
-  }
-
-}
diff --git a/src/app/tes.service.ts b/src/app/tes.service.ts
index 16b76687ed0bccb0246ce47433c82e776117322b..9920712cf4d37e7971699ddc984bc4781daa2a5b 100644
--- a/src/app/tes.service.ts
+++ b/src/app/tes.service.ts
@@ -76,7 +76,7 @@ public openWindow$: Subject<any>;
  private getUserHealthError(error: any, identity: Identity) {
    identity.accountalerts.next([]);
    if (identity.expiry < Date.now() || (error.hasOwnProperty("status") && error.status == 401)) {
-    this.notifications.notify("Your login to "+identity.site.name+ " has expired. Please log in again",   () => { this.authorisationService.refresh$.next(true); });
+    this.notifications.notify("Your login to "+identity.site.name+ " has expired. Please log in again",   () => { this.authorisationService.refresh(); });
     
     this.cancelHealthRequests();
     return;
@@ -87,7 +87,10 @@ public openWindow$: Subject<any>;
 
 
 getUserHealth(identity: Identity)  {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: true};
   let params = new URLSearchParams();
   if (identity === undefined || identity === null) {
@@ -109,7 +112,10 @@ getUserHealth(identity: Identity)  {
 }
 
 getUserHealthObservable(identity: Identity)  {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: true};
   let params = new URLSearchParams();
   if (identity === undefined || identity === null) {
@@ -154,7 +160,10 @@ public getHealthAlertsObservable(identity: Identity) {
 }
 
 public getCachetIncidentsObservable(identity: Identity) {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: false};
   let params = new URLSearchParams();
   if (identity.site.cacheturis === undefined ||  identity.site.cacheturis.length == 0) {
@@ -209,7 +218,7 @@ public addUserHealth(identity,resp) {
    console.error(error);
    if (error.status == 401) {
      console.error('getCacheIncidentsError');
-    this.notifications.notify("Your login has expired. Please log in again",   () => { this.authorisationService.refresh$.next(true); }  );
+    this.notifications.notify("Your login has expired. Please log in again",   () => { this.authorisationService.refresh(); }  );
      return
    }
    if (error.status == 400) {
@@ -222,7 +231,9 @@ public addUserHealth(identity,resp) {
  submissionError(identity: Identity, error: any) {
   if (identity.expiry < Date.now()) {
     console.error('submissionError');
-    this.notifications.notify("Your login has expired. Please log in again",   () => { this.authorisationService.updateAgentContents().subscribe( () => {return} ) }  );
+    console.log(error);
+    //this.notifications.notify("Your login has expired. Please log in again",   () => { this.authorisationService.updateAgentContents().subscribe( () => {return} ) }  );
+    this.notifications.notify("Your login has expired. Please log in again", () => this.authorisationService.refresh())
     return;
   }
    if (error.status != 0) {
@@ -249,7 +260,10 @@ public addUserHealth(identity,resp) {
  }
 
  submit(app: Strudelapp, identity: Identity, batchinterface: BatchInterface, ftidentities?: Identity[], appparams?: any) {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: true};
   this.notifications.notify('Submitting job');
   //let keys = JSON.stringify(this.authorisationService.getKeys());
@@ -272,7 +286,10 @@ public addUserHealth(identity,resp) {
 
 
  cancel(job: Job) {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: true};
   let cmd = job.identity.site.cancelcmd.replace("{jobid}",job.jobid);
 
@@ -299,25 +316,31 @@ public addUserHealth(identity,resp) {
    let username = job.identity.username;
    let loginhost = job.identity.site.host;
    let batchhost = job.batch_host;
+   let port = appinst.port;
    let params = new URLSearchParams;
-   let headers = new HttpHeaders();
+   let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+   //let headers = new HttpHeaders();
    job.connectionState = 2;
 
+   let body = {
+    'user': username,
+    'host': batchhost,
+    'bastion': loginhost,
+    'appinst': appinst,
+    'port': port,
+    'appname': job.appname
+  }
    if ((action.notunnel != undefined) && (action.notunnel == true)) {
      return of('')
    }
    let options = { headers: headers, withCredentials: true};
-   let paramstr = params.toString();
    if (this.ipcService.useIpc) {
-     let body = {
-       'user': username,
-       'host': batchhost,
-       'bastion': loginhost,
-       'appinst': appinst
-     }
+
      return this.ipcService.createTunnel(body)
    } else {
-    return this.http.post<string>(apiserver.tes+'/createtunnel/'+username+'/'+loginhost+'/'+batchhost+'?'+paramstr, appinst, options)
+    return this.http.post<string>(apiserver.tes+'/createtunnel', body, options)
    }
  }
 
@@ -339,31 +362,52 @@ public addUserHealth(identity,resp) {
    return of(url);
  }
 
- public getAppUrl(job: Job, appinst: any, action: AppAction, apiserver: APIServer): Observable<any> {
-   let params = new URLSearchParams;
-   let headers = new HttpHeaders();
-   let options = { headers: headers, withCredentials: true};
-   console.log('in getAppUrl');
-   if (this.ipcService.useIpc) {
-     console.log('try local');
-     return this.getAppUrlLocal(job, appinst, action).pipe(
-       tap((v)=>console.log('try to open url',v))
-     )
-   }
-   let pseudoapp = {'client':{'redir':action.client.redir,'cmd':action.client.cmd}};
-   params.set('app',JSON.stringify(pseudoapp));
-   params.set('appinst',JSON.stringify(appinst));
-   let paramstr = params.toString();
-   job.connectionState = 3;
-   if (action.client.cmd !== undefined && action.client.cmd !== null) {
-      return this.http.get<string>(apiserver.tes+'/applaunch?'+paramstr,options)
-   }
-   console.log('getting appurl from the api server');
-   return this.http.get<string>(apiserver.tes+'/appurl?'+paramstr,options)
+ private getAppUrl(job: Job, appinst: any, action: AppAction, apiserver: APIServer): string {
+
+  console.log('in app urlLocal',appinst);
+  let url = apiserver.tws+'/'+action.client.redir;
+  for (let key in appinst) {
+    if (appinst.hasOwnProperty(key)) {
+     let value = appinst[key]
+     url = url.replace("{"+key+"}",value)
+    }
+  }
+  console.log('appUrlLocal will be',url);
+  return url;
+
  }
 
+//  public getAppUrl(job: Job, appinst: any, action: AppAction, apiserver: APIServer): Observable<any> {
+//    let params = new URLSearchParams;
+//    let headers = new HttpHeaders({
+//     'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+//   });
+//    //let headers = new HttpHeaders();
+//    let options = { headers: headers, withCredentials: true};
+//    console.log('in getAppUrl');
+//    if (this.ipcService.useIpc) {
+//      console.log('try local');
+//      return this.getAppUrlLocal(job, appinst, action).pipe(
+//        tap((v)=>console.log('try to open url',v))
+//      )
+//    }
+//    let pseudoapp = {'client':{'redir':action.client.redir,'cmd':action.client.cmd}};
+//    params.set('app',JSON.stringify(pseudoapp));
+//    params.set('appinst',JSON.stringify(appinst));
+//    let paramstr = params.toString();
+//    job.connectionState = 3;
+//    if (action.client.cmd !== undefined && action.client.cmd !== null) {
+//       return this.http.get<string>(apiserver.tes+'/applaunch?'+paramstr,options)
+//    }
+//    console.log('getting appurl from the api server');
+//    return this.http.get<string>(apiserver.tes+'/appurl?'+paramstr,options)
+//  }
+
  public contactUs(form: any) {
-   let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+   //let headers = new HttpHeaders();
    let options = { headers: headers, withCredentials: true};
    return this.backendSelectionService.apiserver.pipe(
      filter((v) => v !== undefined && v !== null),
@@ -403,7 +447,9 @@ public addUserHealth(identity,resp) {
 
 
  public connect(job: Job, action: AppAction, appinst?: any) {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
   let options = { headers: headers, withCredentials: true};
 
   job.connectionState=1
@@ -426,15 +472,19 @@ public addUserHealth(identity,resp) {
                 catchError(err => this.handleTunnelError(job,action,err)),
                 map((v) => 
                 { 
-                  appinst['localport'] = v['localport']; 
+                  if (v !== null && v.hasOwnProperty('localport')) {
+                    appinst['localport'] = v['localport']; 
+                  }
                   return [apiserver, appinst];
                 }))
             } ),
     tap((_) => job.connectionState=3),
-    switchMap(([apiserver,appinst]) => 
-            { return this.getAppUrl(job,appinst,action,<APIServer>apiserver)
-              .pipe(map((url) => [apiserver, appinst, url]))
-            }),
+
+    map( ([apiserver, appinst]) => {
+      let url = this.getAppUrl(job,appinst,action,<APIServer>apiserver);
+      return [apiserver, appinst, url]
+    }),
+
     tap((_) => job.connectionState=4),
   ).subscribe(([apiserver,appinst,url]) => { if (url !== null) {
                                          this.openWindow$.next( {'job':job, 
@@ -448,7 +498,10 @@ public addUserHealth(identity,resp) {
 }
 
   public runCommand(identity: Identity, command: string, optional?: any): Observable<any> {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+      'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+    });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: true};
   if (identity === undefined || identity === null) {
     return
@@ -481,7 +534,10 @@ public addUserHealth(identity,resp) {
 
 
 public postMkDir(id: Identity, path: string, name: string ) {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: true};
   let params = new URLSearchParams;
   params.set('identity',JSON.stringify(id));
@@ -491,7 +547,10 @@ public postMkDir(id: Identity, path: string, name: string ) {
 }
 
 public getSftpData(id: Identity, path: string, cd: string ) {
-  let headers = new HttpHeaders();
+  let headers = new HttpHeaders({
+    'Authorization': `Bearer ${this.authorisationService.sessionToken}`
+  });
+  //let headers = new HttpHeaders();
   let options = { headers: headers, withCredentials: true};
   let params = new URLSearchParams;
   params.set('identity',JSON.stringify(id));
@@ -559,13 +618,10 @@ private handleGenericError(job: Job, action: AppAction, error: HttpErrorResponse
   }
   if (job.identity.expiry < Date.now() && (error.hasOwnProperty("status") && error.status == 401)) {
     console.error('handleGenericError');
-    this.notifications.notify("Your login has expired. Please log in again",   () => { this.authorisationService.refresh$.next(true); }  );
+    this.notifications.notify("Your login has expired. Please log in again",   () => { this.authorisationService.refresh(); }  );
     return throwError(error);
   }
-  if (job.identity.expiry > Date.now() && error.hasOwnProperty("status") && error.status == 401) {
-    this.authorisationService.reAdd$.next(job.identity);
-    this.notifications.notify("Your login expired. Logging you back in again automatically. Please rety what you were doing");
-  }
+
 
   if (error.hasOwnProperty("status") && error.status == 500) {
     this.notifications.notify("The Strudel2 API server had an error.\n Please report this via the contact us link.\nThe error message was"+emsg);
diff --git a/src/app/transfer/transfer.component.css b/src/app/transfer/transfer.component.css
deleted file mode 100644
index 683ae23faeb400f1a70bacba6e68504c296bc4ef..0000000000000000000000000000000000000000
--- a/src/app/transfer/transfer.component.css
+++ /dev/null
@@ -1,3 +0,0 @@
-:host {
-  height: 100%;
-}
diff --git a/src/app/transfer/transfer.component.html b/src/app/transfer/transfer.component.html
deleted file mode 100644
index 5f4163b660c4c5eaf2fb8550425c816366c87cda..0000000000000000000000000000000000000000
--- a/src/app/transfer/transfer.component.html
+++ /dev/null
@@ -1,48 +0,0 @@
-
-<div fxLayout="column" fxLayoutAlign="flex-start stretch" style="height: 100%; width: 100%" >
-
-    <!--<div fxLayout="row" fxLayout="space-around stretch"  fxLayoutGap="1%" style="height: 90%">-->
-    <!--<div fxLayout="row" fxLayout="space-around stretch" fxLayoutGap="1%"  style="height: 90%">-->
-    <div fxLayout="row" fxLayout="space-around stretch" fxLayoutGap="1%"  style="height: 75%">
-      - <div fxFlex *ngFor="let idx of [0,1]" style="height: 100%;"> 
-        <!--  <div *ngFor="let idx of [0,1]" style="height: 100% " fxFlex>-->
-        <!--<div fxLayout="column" fxLayoutAlign="none stretch" style="width: 100%; height: 100%" >-->
-        <!--<div style="width: 100%; height: 100%" >-->
-                <mat-form-field style="width:100%">
-                    <mat-select (selectionChange)="setId(idx,$event)" placeholder="Choose a server">
-                      <mat-option *ngFor="let s of computesitesService.ftidentities | async" [value]="s">
-                        {{ s.username }}@{{s.site.name }}
-                      </mat-option>
-                    </mat-select>
-                 </mat-form-field>
-                 <span class="mat-body"> {{ path[idx] }}</span>
-                 <div *ngIf="working[idx] | async">
-                    <mat-spinner></mat-spinner>
-                 </div>
-                 <!--<div *ngIf="!(working[idx] | async)" style="height: 100%; overflow-y: auto">-->
-                 <div *ngIf="!(working[idx] | async)" style="height: 100%">
-                    <div  style="height: 100%; width: 100%; overflow-y: auto">
-                        <file-explorer [fileElements]="fileElements[idx] | async"
-                                     [path]="pathSubject[idx] | async"
-                                     (navigatedDown)="navigateToFolder(idx,$event)"
-                                     (navigatedUp)="navigateUp(idx,$event)"
-                                     [canNavigateUp]="canNavigateUp[idx] | async"
-                                     (sendFile)="queueFile(idx,$event)"
-                                     (folderAdded)="newDirectory(idx,$event)">
-                        </file-explorer>
-                    </div>
-                 </div>
-                 <!--</div>-->
-        </div>
-    </div>
-    <div style="height: 25%; overflow-y: auto">
-        <h3>Transfer list</h3>
-        <mat-list>
-            <div *ngFor="let t of transferlist">
-                <mat-list-item>
-                  {{ t.srcpath }} {{ t.dstpath }}
-                </mat-list-item>
-            </div>
-        </mat-list>
-    </div>
-</div>
diff --git a/src/app/transfer/transfer.component.spec.ts b/src/app/transfer/transfer.component.spec.ts
deleted file mode 100644
index 153d995690cfc97878655298081dc04601a63482..0000000000000000000000000000000000000000
--- a/src/app/transfer/transfer.component.spec.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
-
-import { TransferComponent } from './transfer.component';
-
-describe('TransferComponent', () => {
-  let component: TransferComponent;
-  let fixture: ComponentFixture<TransferComponent>;
-
-  beforeEach(waitForAsync(() => {
-    TestBed.configureTestingModule({
-      declarations: [ TransferComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(TransferComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/src/app/transfer/transfer.component.ts b/src/app/transfer/transfer.component.ts
deleted file mode 100644
index bd754650a49fbb82d2ad23cdb31a09de158ba1c3..0000000000000000000000000000000000000000
--- a/src/app/transfer/transfer.component.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { BehaviorSubject } from 'rxjs';
-import { FileElement } from '../file-explorer/model/element';
-import { TesService } from '../tes.service';
-import { ComputesitesService } from '../computesites.service';
-import { AuthorisationService } from '../authorisation.service';
-import { Computesite } from '../computesite';
-import { Identity } from '../identity';
-import { Router } from '@angular/router';
-import {NotificationsService } from '../notifications.service';
-
-
-export class Transfer {
-  srcpath: string;
-  dstpath: string;
-  name: string;
-  direction: number;
-  constructor(srcpath: string, dstpath: string, name: string, direction: number) {
-    this.srcpath = srcpath;
-    this.dstpath = dstpath;
-    this.name = name;
-    this.direction = direction;
-  }
-}
-
-
-
-@Component({
-  selector: 'app-transfer',
-  templateUrl: './transfer.component.html',
-  styleUrls: ['./transfer.component.css']
-})
-export class TransferComponent implements OnInit {
-
-  fileElements: BehaviorSubject<FileElement[]>[];
-  pathSubject: BehaviorSubject<string>[];
-  path: string[];
-  working: BehaviorSubject<Boolean>[];
-  canNavigateUp: BehaviorSubject<Boolean>[];
-  id: Identity[];
-  site: Computesite[];
-  disableSend: Boolean;
-  redirecturi: string;
-  appevent: any;
-  transferlist: Transfer[];
-
-
-  constructor(public computesitesService: ComputesitesService,
-              private tesService: TesService,
-              private authService: AuthorisationService,
-              private router: Router,
-              private notifications: NotificationsService) {
-    this.path = ['',''];
-    this.fileElements = [new BehaviorSubject([]), new BehaviorSubject([])];
-    this.working = [ new BehaviorSubject<Boolean>(false), new BehaviorSubject<Boolean>(false)];
-    this.canNavigateUp = [ new BehaviorSubject<Boolean>(false), new BehaviorSubject<Boolean>(false)];
-    this.pathSubject = [ new BehaviorSubject(""),new BehaviorSubject("")];
-    this.id = [null,null];
-    this.disableSend = true;
-    this.transferlist = [];
-  }
-
-  ngOnInit() {
-    var fel: FileElement[] = []
-    // this.fileElements = [new BehaviorSubject([]), new BehaviorSubject([])];
-    // this.working = [ new BehaviorSubject<Boolean>(false), new BehaviorSubject<Boolean>(false)];
-    // this.canNavigateUp = [ new BehaviorSubject<Boolean>(false), new BehaviorSubject<Boolean>(false)];
-    // this.pathSubject = [ new BehaviorSubject(""),new BehaviorSubject("")];
-    // this.id = [null,null];
-    // this.disableSend = true;
-    setTimeout( () => this.authService.updateAgentContents() )
-  }
-
-compareObjects(o1: any, o2: any) {
-  if(o1.name == o2.name) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-processError(idx,error) {
-  this.working[idx].next(false);
-  this.notifications.notify(error.error.message);
-
-}
-
-newDirectory(idx: number, name: string) {
-  this.working[idx].next(true);
-  this.tesService.postMkDir(this.id[idx],this.path[idx],name).subscribe(resp => this.getSftpls(idx,'.'), error => this.processError(idx,error));
-}
-
-getSftpls(idx,cd) {
-  this.working[idx].next(true);
-  this.tesService.getSftpData(this.id[idx],this.path[idx],cd).subscribe(resp => this.updateSftpls(idx,resp), error => this.processError(idx,error));
-}
-
-makeFileElements(data) {
-  var rv: FileElement[] = [];
-  var fe: FileElement;
-  for (let f of data) {
-    fe = new FileElement();
-    if (f.isdir !== undefined) {
-      fe.isFolder = f.isdir;
-    } else {
-      if (f.mode.indexOf('d')== 0) {
-        fe.isFolder=true;
-      }
-    }
-    fe.name = f.name;
-    fe.size = f.size;
-    fe.online = f.online;
-    rv.push(fe);
-  }
-  return rv;
-}
-
- updateSftpls(idx,resp) {
-   let files = this.makeFileElements(resp.files);
-   if (resp.pwd.length > 1) {
-     this.canNavigateUp[idx].next(true);
-   } else {
-     this.canNavigateUp[idx].next(false);
-
-   }
-   this.path[idx] = resp.pwd;
-   this.pathSubject[idx].next(this.path[idx]);
-   this.fileElements[idx].next(files);
-   this.working[idx].next(false);
-
- }
-
-
-  setId(idx,event) {
-    this.id[idx] = event.value;
-    if ((this.id[0] != null) && (this.id[1] != null)) {
-      this.disableSend = false;
-    }
-    this.path[idx]=".";
-    this.pathSubject[idx].next(this.id[idx].username+"@"+this.id[idx].site.name+":"+this.path[idx]);
-    this.getSftpls(idx,'.');
-
-  }
-
-  navLaunch() {
-    this.router.navigate(['/launch']);
-  }
-
-  navigateToFolder(idx,element: FileElement) {
-    this.getSftpls(idx,element.name);
-  }
-
-  navigateUp(idx: number, event: any) {
-    this.getSftpls(idx,'..');
-  }
-
-
-  queueFile(idx: number, element: FileElement) {
-    let src = idx;
-    let dest = (idx+1) % 2;
-    this.transferlist.push(new Transfer(this.path[0],this.path[1],element.name,idx));
-  }
-
-  postParams() {
-    let appparams = JSON.stringify(
-      {'sites':[this.id[0],this.id[1]],
-        'files': this.transferlist })
-    window.parent.postMessage({'appData':appparams},'*');
-  }
-
-}
diff --git a/src/assets/config/apiservers.json b/src/assets/config/apiservers.json
index 0392248fcb6e6eba3af108ee9997ee0b28eea1b1..4d694cdaad4b812ec6c76982d7c5fa5c5ca7834e 100644
--- a/src/assets/config/apiservers.json
+++ b/src/assets/config/apiservers.json
@@ -16,8 +16,8 @@
     },
     {
         "name": "localhost",
-        "tes": "http://localhost:8080",
-        "tws": "http://localhost:8090"
+        "tes": "http://localhost:8000",
+        "tws": "http://localhost:9000"
     }
 
     ]
diff --git a/src/assets/images/mlerp-dragon.png b/src/assets/images/mlerp-dragon.png
new file mode 100644
index 0000000000000000000000000000000000000000..44255f075f01b1f5cc2313d64c31717ca9778a6f
Binary files /dev/null and b/src/assets/images/mlerp-dragon.png differ
diff --git a/src/assets/mlerp-dragon.png b/src/assets/mlerp-dragon.png
new file mode 100644
index 0000000000000000000000000000000000000000..44255f075f01b1f5cc2313d64c31717ca9778a6f
Binary files /dev/null and b/src/assets/mlerp-dragon.png differ
diff --git a/src/deployments/mlerp/assets/images/mlerp-dragon.png b/src/deployments/mlerp/assets/images/mlerp-dragon.png
new file mode 100644
index 0000000000000000000000000000000000000000..44255f075f01b1f5cc2313d64c31717ca9778a6f
Binary files /dev/null and b/src/deployments/mlerp/assets/images/mlerp-dragon.png differ