diff --git a/src/frontend/app/app-routing.module.ts b/src/frontend/app/app-routing.module.ts
index 1ec529e1c917e75c15d004e9201c8f1ef96a710e..0794240505ef3234ef7d2f5ddeb133aba38480c6 100755
--- a/src/frontend/app/app-routing.module.ts
+++ b/src/frontend/app/app-routing.module.ts
@@ -21,12 +21,14 @@ import { AcknowledgementReceptionComponent } from './registeredMail/acknowledgem
 import { SearchComponent } from './search/search.component';
 import { ProcessComponent } from './process/process.component';
 import { IndexationComponent } from './indexation/indexation.component';
+import { AppLightGuard } from '@service/app-light.guard';
 
 
 const routes: Routes = [
     { path: 'resources/:resId/content', canActivate: [AppGuard], component: DocumentViewerPageComponent },
     {
         path: 'install',
+        canActivate: [AppLightGuard],
         loadChildren: () => import('./installer/installer.module').then(m => m.InstallerModule)
     },
     { path: 'signatureBook/users/:userId/groups/:groupId/baskets/:basketId/resources/:resId', canActivate: [AppGuard], component: SignatureBookComponent },
@@ -42,7 +44,7 @@ const routes: Routes = [
     { path: 'about-us', canActivate: [AppGuard], component: AboutUsComponent },
     { path: 'home', canActivate: [AppGuard], component: HomeComponent },
     { path: 'basketList/users/:userSerialId/groups/:groupSerialId/baskets/:basketId', canActivate: [AppGuard], component: BasketListComponent },
-    { path: 'login', component: LoginComponent },
+    { path: 'login', canActivate: [AppLightGuard], component: LoginComponent },
     { path: 'registeredMail/acknowledgement', canActivate: [AppGuard], component: AcknowledgementReceptionComponent },
     { path: 'search', canActivate: [AppGuard], component: SearchComponent },
     {
diff --git a/src/frontend/app/app.component.ts b/src/frontend/app/app.component.ts
index 0c8e86e26fee4ea7468845e70155d7f0650e6d41..a2eb64caac9cc8c8190189c7e60601ee68111f2f 100755
--- a/src/frontend/app/app.component.ts
+++ b/src/frontend/app/app.component.ts
@@ -10,6 +10,7 @@ import { AuthService } from '@service/auth.service';
 import { environment } from '../environments/environment';
 import { TranslateService } from '@ngx-translate/core';
 import { DateAdapter } from '@angular/material/core';
+import { MatDialog } from '@angular/material/dialog';
 
 /** Custom options the configure the tooltip's default show/hide delays. */
 export const myCustomTooltipDefaults: MatTooltipDefaultOptions = {
@@ -44,7 +45,8 @@ export class AppComponent implements OnInit, AfterViewInit {
         public appService: AppService,
         public headerService: HeaderService,
         public authService: AuthService,
-        private adapter: DateAdapter<any>
+        private adapter: DateAdapter<any>,
+        public dialog: MatDialog,
     ) {
 
         translate.setDefaultLang('fr');
@@ -60,8 +62,6 @@ export class AppComponent implements OnInit, AfterViewInit {
     }
 
     async ngOnInit() {
-        this.appService.checkAppSecurity();
-        await this.appService.applyMinorUpdate();
         this.loading = false;
         this.headerService.hideSideBar = true;
         setTimeout(() => {
diff --git a/src/frontend/app/installer/install-action/install-action.component.ts b/src/frontend/app/installer/install-action/install-action.component.ts
index 3236cf0b01d9e644a0311ff57ca3e46ed37578be..079db3feb9b5f084745b0b12504cf08918c3e244 100644
--- a/src/frontend/app/installer/install-action/install-action.component.ts
+++ b/src/frontend/app/installer/install-action/install-action.component.ts
@@ -6,6 +6,7 @@ import { of } from 'rxjs';
 import { InstallerService } from '../installer.service';
 import { NotificationService } from '@service/notification/notification.service';
 import { catchError, tap } from 'rxjs/operators';
+import { AuthService } from '@service/auth.service';
 
 @Component({
     selector: 'app-install-action',
@@ -25,7 +26,8 @@ export class InstallActionComponent implements OnInit, AfterViewInit {
         public dialogRef: MatDialogRef<InstallActionComponent>,
         public http: HttpClient,
         private installerService: InstallerService,
-        private notify: NotificationService
+        private notify: NotificationService,
+        private authService: AuthService,
     ) { }
 
     async ngOnInit(): Promise<void> {
@@ -108,6 +110,7 @@ export class InstallActionComponent implements OnInit, AfterViewInit {
     goToInstance() {
         this.http.request('DELETE', '../rest/installer/lock', { body: { customId: this.customId } }).pipe(
             tap((res: any) => {
+                this.authService.noInstall = false;
                 window.location.href = res.url;
                 this.dialogRef.close('ok');
             }),
diff --git a/src/frontend/app/installer/installer.component.html b/src/frontend/app/installer/installer.component.html
index d9c98310ff54920ef1af7d9eff2f25247147e0a9..a17d3a397c2076f3d58257191ad2fcf476748fda 100644
--- a/src/frontend/app/installer/installer.component.html
+++ b/src/frontend/app/installer/installer.component.html
@@ -6,13 +6,16 @@
         </div>
         <div class="container" [class.fullContainer]="appService.getViewMode()">
             <div class="container-content" style="overflow: hidden;">
-                <mat-horizontal-stepper [@.disabled]="true" linear #stepper style="height: 100vh;overflow: auto;" (selectionChange)="initStep($event)">
+                <mat-horizontal-stepper [@.disabled]="true" *ngIf="!loading" linear #stepper style="height: 100vh;overflow: auto;" (selectionChange)="initStep($event)">
                     <mat-step label="install">
                         <ng-template matStepLabel>Installation</ng-template>
                         <div class="stepContainer">
                             <div class="stepContent">
                                 <app-welcome #stepContent></app-welcome>
                             </div>
+                            <button *ngIf="!authService.noInstall" mat-fab [title]="'lang.home' | translate" class="previousStepButton" color="primary" (click)="gotToLogin()">
+                                <mat-icon class="fas fa-home"></mat-icon>
+                            </button>
                             <button mat-fab matStepperNext [title]="this.translate.instant('lang.next')" class="nextStepButton" color="primary">
                                 <mat-icon class="fa fa-arrow-right"></mat-icon>
                             </button>
diff --git a/src/frontend/app/installer/installer.component.ts b/src/frontend/app/installer/installer.component.ts
index f67b043f85d601c7f6dbe0a77e0f2439c41f5ec3..e07472edf5d0e478eda26cf8f13c33b3b19ea89a 100644
--- a/src/frontend/app/installer/installer.component.ts
+++ b/src/frontend/app/installer/installer.component.ts
@@ -1,5 +1,4 @@
 import { Component, OnInit, ViewChild, AfterViewInit, ViewChildren } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
 import { Router } from '@angular/router';
 import { HeaderService } from '@service/header.service';
 import { NotificationService } from '@service/notification/notification.service';
@@ -13,8 +12,9 @@ import { MatDialog } from '@angular/material/dialog';
 import { InstallActionComponent } from './install-action/install-action.component';
 import { of } from 'rxjs';
 import { FunctionsService } from '@service/functions.service';
-import { InstallerService } from './installer.service';
 import { catchError, filter, tap } from 'rxjs/operators';
+import { AuthService } from '@service/auth.service';
+import { PrivilegeService } from '@service/privileges.service';
 
 @Component({
     templateUrl: './installer.component.html',
@@ -28,12 +28,12 @@ import { catchError, filter, tap } from 'rxjs/operators';
 })
 export class InstallerComponent implements OnInit, AfterViewInit {
 
+    loading: boolean = true;
     @ViewChildren('stepContent') stepContent: any;
     @ViewChild('stepper', { static: true }) stepper: MatStepper;
 
     constructor(
         public translate: TranslateService,
-        private http: HttpClient,
         private router: Router,
         private headerService: HeaderService,
         private notify: NotificationService,
@@ -41,13 +41,25 @@ export class InstallerComponent implements OnInit, AfterViewInit {
         private sortPipe: SortPipe,
         public dialog: MatDialog,
         private functionService: FunctionsService,
-        private installerService: InstallerService
+        public privilegeService: PrivilegeService,
+        public authService: AuthService,
     ) { }
 
     ngOnInit(): void {
         this.headerService.hideSideBar = true;
+
+        if (!this.authService.isAuth() && !this.authService.noInstall) {
+            this.router.navigate(['/login']);
+            this.notify.error(this.translate.instant('lang.mustConnectToInstall'));
+        } else if (this.authService.getToken() !== null && !this.privilegeService.hasCurrentUserPrivilege('create_custom')) {
+            this.router.navigate(['/login']);
+            this.notify.error(this.translate.instant('lang.mustPrivilegeToInstall'));
+        } else {
+            this.loading = false;
+        }
     }
 
+
     ngAfterViewInit(): void {
         $('.mat-horizontal-stepper-header-container').insertBefore('.bg-head-content');
         $('.mat-step-icon').css('background-color', 'white');
@@ -72,6 +84,10 @@ export class InstallerComponent implements OnInit, AfterViewInit {
         this.stepper.next();
     }
 
+    gotToLogin() {
+        this.router.navigate(['/login']);
+    }
+
     endInstall() {
         let installContent: StepAction[] = [];
         this.stepContent.toArray().forEach((component: any) => {
@@ -80,10 +96,6 @@ export class InstallerComponent implements OnInit, AfterViewInit {
 
         installContent = this.sortPipe.transform(installContent, 'installPriority');
 
-        console.log(installContent);
-
-        // this.stepper.next();
-
         const dialogRef = this.dialog.open(InstallActionComponent, {
             panelClass: 'maarch-modal',
             disableClose: true,
diff --git a/src/frontend/app/installer/welcome/welcome.component.html b/src/frontend/app/installer/welcome/welcome.component.html
index 26f0c9ffb1b34ef9636ff7f4cf6b21629c464393..8405ca2f9890e6fdba1777a11681447758fa73cd 100644
--- a/src/frontend/app/installer/welcome/welcome.component.html
+++ b/src/frontend/app/installer/welcome/welcome.component.html
@@ -14,6 +14,17 @@
         </mat-form-field>
     </form>
     <mat-divider></mat-divider>
+    <ng-container *ngIf="customs.length > 0">
+        <mat-list>
+            <div mat-subheader>{{'lang.instancesList' | translate}} :
+            </div>
+            <mat-list-item *ngFor="let custom of customs">
+                <mat-icon mat-list-icon color="primary" class="fas fa-box-open"></mat-icon>
+                <div mat-line>{{custom.label}} <small style="color: #666">{{custom.id}}</small></div>
+            </mat-list-item>
+        </mat-list>
+        <mat-divider></mat-divider>
+    </ng-container>
     <mat-list>
         <div mat-subheader>{{'lang.installDescription' | translate}} :
         </div>
diff --git a/src/frontend/app/installer/welcome/welcome.component.ts b/src/frontend/app/installer/welcome/welcome.component.ts
index 596accbe753303a59c5a7520803e49de8667507a..69e822fcf992bd50602dc2513dd47e77559e06d6 100644
--- a/src/frontend/app/installer/welcome/welcome.component.ts
+++ b/src/frontend/app/installer/welcome/welcome.component.ts
@@ -4,6 +4,9 @@ import { NotificationService } from '@service/notification/notification.service'
 import { TranslateService } from '@ngx-translate/core';
 import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 import { environment } from '../../../environments/environment';
+import { catchError, tap } from 'rxjs/operators';
+import { of } from 'rxjs';
+import { AuthService } from '@service/auth.service';
 
 
 @Component({
@@ -21,36 +24,39 @@ export class WelcomeComponent implements OnInit {
 
     steps: any[] = [
         {
-            icon : 'fas fa-check-square',
+            icon: 'fas fa-check-square',
             desc: this.translate.instant('lang.prerequisiteCheck')
         },
         {
-            icon : 'fa fa-database',
+            icon: 'fa fa-database',
             desc: this.translate.instant('lang.databaseCreation')
         },
         {
-            icon : 'fa fa-database',
+            icon: 'fa fa-database',
             desc: this.translate.instant('lang.dataSampleCreation')
         },
         {
-            icon : 'fa fa-hdd',
+            icon: 'fa fa-hdd',
             desc: this.translate.instant('lang.docserverCreation')
         },
         {
-            icon : 'fas fa-tools',
+            icon: 'fas fa-tools',
             desc: this.translate.instant('lang.stepCustomizationActionDesc')
         },
         {
-            icon : 'fa fa-user',
+            icon: 'fa fa-user',
             desc: this.translate.instant('lang.adminUserCreation')
         },
     ];
 
+    customs: any = [];
+
     constructor(
         public translate: TranslateService,
         public http: HttpClient,
         private notify: NotificationService,
-        private _formBuilder: FormBuilder
+        private _formBuilder: FormBuilder,
+        private authService: AuthService
     ) { }
 
     ngOnInit(): void {
@@ -59,6 +65,9 @@ export class WelcomeComponent implements OnInit {
         });
 
         this.getLang();
+        if (!this.authService.noInstall) {
+            this.getCustoms();
+        }
     }
 
     getLang() {
@@ -76,6 +85,18 @@ export class WelcomeComponent implements OnInit {
         ).subscribe();*/
     }
 
+    getCustoms() {
+        this.http.get('../rest/installer/customs').pipe(
+            tap((data: any) => {
+                this.customs = data.customs;
+            }),
+            catchError((err: any) => {
+                this.notify.handleSoftErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+
     initStep() {
         return false;
     }
diff --git a/src/frontend/app/login/login.component.html b/src/frontend/app/login/login.component.html
index 7b35d8fe65483647110e0d2e868625a28f5920f1..f59708c6b501524e7dc9df3022a632ea91e082bc 100644
--- a/src/frontend/app/login/login.component.html
+++ b/src/frontend/app/login/login.component.html
@@ -3,8 +3,8 @@
         <div class="login-form">
             <form (ngSubmit)="onSubmit()" [formGroup]="loginForm">
                 <mat-icon svgIcon="maarchLogoFull" class="maarchLogo"></mat-icon>
-                <div style="color: white;font-size: 14px;" [innerHTML]="loginMessage | safeHtml"></div>
-                <p style="color: white;font-size: 14px;font-weight: bold;">{{applicationName}}</p>
+                <div style="color: white;font-size: 14px;" [innerHTML]="authService.loginMessage | safeHtml"></div>
+                <p style="color: white;font-size: 14px;font-weight: bold;">{{authService.applicationName}}</p>
                 <div style="padding-left: 30px;padding-right: 30px;">
                     <mat-form-field *ngIf="['cas', 'keycloak'].indexOf(authService.authMode) === -1" class="input-row login" appearance="outline" style="padding-bottom: 0px;">
                         <input id="login" name="login" matInput [placeholder]="this.translate.instant('lang.id')" formControlName="login"
diff --git a/src/frontend/app/login/login.component.ts b/src/frontend/app/login/login.component.ts
index a2883d2da0b060a40ce71f4110e5a136c230cb2d..25cdd0a465ac19ad173a61f07ee9c11c658cc786 100644
--- a/src/frontend/app/login/login.component.ts
+++ b/src/frontend/app/login/login.component.ts
@@ -3,7 +3,7 @@ import { MatDialog } from '@angular/material/dialog';
 import { HttpClient } from '@angular/common/http';
 import { Router } from '@angular/router';
 import { Validators, FormGroup, FormBuilder } from '@angular/forms';
-import { tap, catchError, finalize } from 'rxjs/operators';
+import { tap, catchError } from 'rxjs/operators';
 import { AuthService } from '@service/auth.service';
 import { NotificationService } from '@service/notification/notification.service';
 import { environment } from '../../environments/environment';
@@ -11,7 +11,6 @@ import { of } from 'rxjs';
 import { HeaderService } from '@service/header.service';
 import { FunctionsService } from '@service/functions.service';
 import { TimeLimitPipe } from '../../plugins/timeLimit.pipe';
-import { AlertComponent } from '../../plugins/modal/alert.component';
 import { TranslateService } from '@ngx-translate/core';
 import { LocalStorageService } from '@service/local-storage.service';
 
@@ -24,7 +23,7 @@ export class LoginComponent implements OnInit {
     loginForm: FormGroup;
 
     loading: boolean = false;
-    showForm: boolean = false;
+    showForm: boolean = true;
     environment: any;
     applicationName: string = '';
     loginMessage: string = '';
@@ -59,7 +58,7 @@ export class LoginComponent implements OnInit {
                 this.router.navigate(['/home']);
             }
         } else {
-            this.getLoginInformations();
+            this.initConnection();
         }
     }
 
@@ -109,46 +108,6 @@ export class LoginComponent implements OnInit {
         ).subscribe();
     }
 
-    getLoginInformations() {
-        this.http.get('../rest/authenticationInformations').pipe(
-            tap((data: any) => {
-                this.authService.setAppSession(data.instanceId);
-                this.authService.changeKey = data.changeKey;
-                this.applicationName = data.applicationName;
-                this.loginMessage = data.loginMessage;
-                this.authService.setEvent('authenticationInformations');
-                this.authService.authMode = data.authMode;
-                this.authService.authUri = data.authUri;
-
-                if (this.authService.authMode === 'keycloak') {
-                    const keycloakState = this.localStorage.get('keycloakState');
-                    if (keycloakState === null || keycloakState === 'null') {
-                        this.localStorage.save('keycloakState', data.keycloakState);
-                    }
-                }
-
-                this.initConnection();
-            }),
-            finalize(() => this.showForm = true),
-            catchError((err: any) => {
-                this.http.get('../rest/validUrl').pipe(
-                    tap((data: any) => {
-                        if (!this.functionsService.empty(data.url)) {
-                            window.location.href = data.url;
-                        } else if (data.lang === 'moreOneCustom') {
-                            this.dialog.open(AlertComponent, { panelClass: 'maarch-modal', autoFocus: false, disableClose: true, data: { title: this.translate.instant('lang.accessNotFound'), msg: this.translate.instant('lang.moreOneCustom'), hideButton: true } });
-                        } else if (data.lang === 'noConfiguration') {
-                            this.router.navigate(['/install']);
-                        } else {
-                            this.notify.handleSoftErrors(err);
-                        }
-                    })
-                ).subscribe();
-                return of(false);
-            })
-        ).subscribe();
-    }
-
     initConnection() {
         if (['cas', 'keycloak'].indexOf(this.authService.authMode) > -1) {
             this.loginForm.disable();
diff --git a/src/frontend/plugins/modal/alert.component.html b/src/frontend/plugins/modal/alert.component.html
index 99f9a936632c46e8a21867891c3cd0aca2797c63..339f3327c54e8458c1cfc4bc9d09cde3b364caf7 100644
--- a/src/frontend/plugins/modal/alert.component.html
+++ b/src/frontend/plugins/modal/alert.component.html
@@ -4,7 +4,7 @@
         <div class="alert-message {{data.mode}}" [innerHTML]="data.msg"></div>
     </div>
     <span class="divider-modal"></span>
-    <div mat-dialog-actions *ngIf="!data.hidebutton">
+    <div mat-dialog-actions *ngIf="!data.hideButton">
         <button id="alertComponentClose" class="actions" color="primary" mat-raised-button (click)="this.dialogRef.close();">{{'lang.ok' | translate}}</button>
     </div>
 </div>
diff --git a/src/frontend/service/app-light.guard.ts b/src/frontend/service/app-light.guard.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5959a1238a9f7907f7c7d1045737023d35563fe3
--- /dev/null
+++ b/src/frontend/service/app-light.guard.ts
@@ -0,0 +1,51 @@
+
+import { Injectable } from '@angular/core';
+import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, CanDeactivate, UrlTree } from '@angular/router';
+import { HttpClient } from '@angular/common/http';
+import { Observable, of } from 'rxjs';
+import { map, tap, catchError, exhaustMap, filter, finalize } from 'rxjs/operators';
+import { HeaderService } from './header.service';
+import { ProcessComponent } from '../app/process/process.component';
+import { PrivilegeService } from './privileges.service';
+import { AuthService } from './auth.service';
+import { LocalStorageService } from './local-storage.service';
+import { FunctionsService } from './functions.service';
+import { AlertComponent } from '../plugins/modal/alert.component';
+import { MatDialog } from '@angular/material/dialog';
+import { TranslateService } from '@ngx-translate/core';
+
+@Injectable({
+    providedIn: 'root'
+})
+export class AppLightGuard implements CanActivate {
+
+    constructor(
+        public translate: TranslateService,
+        public http: HttpClient,
+        private router: Router,
+        private authService: AuthService,
+        private localStorage: LocalStorageService,
+        private functionService: FunctionsService,
+        public headerService: HeaderService,
+        private privilegeService: PrivilegeService,
+        private dialog: MatDialog,
+        private functionsService: FunctionsService,
+    ) { }
+
+    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
+        const urlArr = state.url.replace(/^\/+|\/+$/g, '').split('/');
+
+        console.log('== ROUTE LIGHT GUARD ==');
+        console.log(state.url);
+
+        this.headerService.resetSideNavSelection();
+
+        return this.authService.getLoginInformations(state.url).pipe(
+            exhaustMap(() => this.authService.getToken() !== null ? this.authService.getCurrentUserInfo() : of(false)),
+            map(() => true),
+            catchError((err: any) => {
+                return of(true);
+            })
+        );
+    }
+}
diff --git a/src/frontend/service/app.guard.ts b/src/frontend/service/app.guard.ts
index 6878488bfcb840af34ce8cba3488df8a8f37f66c..891e4f7d68f923449ba59686b7cb4dc937cef323 100644
--- a/src/frontend/service/app.guard.ts
+++ b/src/frontend/service/app.guard.ts
@@ -1,17 +1,12 @@
 
 import { Injectable } from '@angular/core';
-import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, CanDeactivate, UrlTree } from '@angular/router';
+import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, CanDeactivate } from '@angular/router';
 import { HttpClient } from '@angular/common/http';
 import { Observable, of } from 'rxjs';
-import { map, tap, catchError, exhaustMap, filter } from 'rxjs/operators';
+import { map, catchError, exhaustMap, filter } from 'rxjs/operators';
 import { HeaderService } from './header.service';
 import { ProcessComponent } from '../app/process/process.component';
-import { PrivilegeService } from './privileges.service';
 import { AuthService } from './auth.service';
-import { LocalStorageService } from './local-storage.service';
-import { FunctionsService } from './functions.service';
-import {AlertComponent} from '../plugins/modal/alert.component';
-import {MatDialog} from '@angular/material/dialog';
 import { TranslateService } from '@ngx-translate/core';
 
 @Injectable({
@@ -24,168 +19,59 @@ export class AppGuard implements CanActivate {
         public http: HttpClient,
         private router: Router,
         private authService: AuthService,
-        private localStorage: LocalStorageService,
-        private functionService: FunctionsService,
         public headerService: HeaderService,
-        private privilegeService: PrivilegeService,
-        private dialog: MatDialog,
     ) { }
 
     canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
         const urlArr = state.url.replace(/^\/+|\/+$/g, '').split('/');
 
-        console.log('== ROUTE GUARD ==');
-        this.headerService.resetSideNavSelection();
-
-        let tokenInfo = this.authService.getToken();
-
-        if (tokenInfo !== null) {
-            this.functionService.debug('Token trouvé !', route.url.join('/'));
-
-            this.authService.setUrl(route.url.join('/'));
-            if (this.headerService.user.id === undefined) {
-                console.log('Récupération données user...');
-                return this.http.get('../rest/currentUser/profile')
-                    .pipe(
-                        map((data: any) => {
-                            this.headerService.user = {
-                                mode: data.mode,
-                                id: data.id,
-                                status: data.status,
-                                userId: data.user_id,
-                                firstname: data.firstname,
-                                lastname: data.lastname,
-                                entities: data.entities,
-                                groups: data.groups,
-                                preferences: data.preferences,
-                                privileges: data.privileges[0] === 'ALL_PRIVILEGES' ? this.privilegeService.getAllPrivileges() : data.privileges
-                            };
-                            this.functionService.debug('', route.url.join('/'));
-                            this.headerService.nbResourcesFollowed = data.nbFollowedResources;
-                            this.privilegeService.resfreshUserShortcuts();
-
-                            if (this.headerService.user.status === 'ABS') {
-                                return this.router.navigate(['/activate-user']);
-                            } else {
-                                if (urlArr.filter((url: any) => ['signatureBook', 'content'].indexOf(url) > -1).length > 0) {
-
-                                    this.headerService.hideSideBar = true;
-                                } else {
-                                    this.headerService.hideSideBar = false;
-                                }
-                                if (urlArr.filter((url: any) => url === 'administration').length > 0 || urlArr.filter((url: any) => url === 'profile').length > 0) {
-                                    this.headerService.sideBarAdmin = true;
-                                } else {
-                                    this.headerService.sideBarAdmin = false;
-                                }
-                                return true;
-                            }
+        console.debug('== ROUTE GUARD ==');
+        console.debug(state.url);
 
-                        }),
-                        catchError((err: any) => {
-                            console.log(err);
-                            if (err.error.errors === 'User must change his password') {
-                                return this.router.navigate(['/password-modification']);
-                            } else {
-                                return of(false);
-                            }
-                        })
-                    );
-            } else {
-                console.log('Données user trouvées !');
+        this.headerService.resetSideNavSelection();
 
-                if (this.headerService.user.status === 'ABS') {
-                    this.router.navigate(['/activate-user']);
-                    return of(false);
-                } else {
-                    if (urlArr.filter((url: any) => ['signatureBook', 'content'].indexOf(url) > -1).length > 0) {
-                        this.headerService.hideSideBar = true;
-                    } else {
-                        this.headerService.hideSideBar = false;
+        return this.authService.getLoginInformations(state.url)
+            .pipe(
+                map((data: any) => {
+                    if (!data) {
+                        return false;
+                    } else if (this.authService.getToken() === null) {
+                        this.authService.setCachedUrl(state.url.replace(/^\//g, ''));
+                        console.debug('Aucun token trouvé ! Redirection sur login ...');
+                        this.authService.logout(false);
+                        return false;
                     }
-                    if (urlArr.filter((url: any) => url === 'administration').length > 0 || urlArr.filter((url: any) => url === 'profile').length > 0) {
-                        this.headerService.sideBarAdmin = true;
+                }),
+                filter(() => this.authService.getToken() !== null),
+                exhaustMap(() => this.authService.getCurrentUserInfo()),
+                map((data: any) => {
+                    if (this.headerService.user.status === 'ABS') {
+                        this.router.navigate(['/activate-user']);
+                        return false;
                     } else {
-                        this.headerService.sideBarAdmin = false;
-                    }
-                    return of(true);
-                }
-            }
-        } else {
-            console.log('Aucun token trouvé ! Recupération du token ...');
-
-            return this.http.get('../rest/authenticationInformations')
-                .pipe(
-                    map((data: any) => {
-                        this.authService.setAppSession(data.instanceId);
-                        // this.authService.authMode = data.connection;
-                        this.authService.changeKey = data.changeKey;
-                        this.localStorage.setAppSession(data.instanceId);
-                        tokenInfo = this.authService.getToken();
-
-                        if (tokenInfo !== null) {
-                            // this.authService.setUrl(route.url.join('/'));
-                            this.functionService.debug('', route.url.join('/'));
-
-                            this.authService.setEvent('authenticationInformations');
-
-                            return tokenInfo;
-                        } else {
-                            this.authService.setCachedUrl(state.url.replace(/^\//g, ''));
-                            console.log('Aucun token trouvé ! Redirection sur login ...');
-                            this.authService.logout(false);
-                            return false;
-                        }
-                    }),
-                    filter((info: any) => info !== null),
-                    tap(() => console.log('Récupération données user...')),
-                    exhaustMap(() => this.http.get('../rest/currentUser/profile')),
-                    map((dataUser: any) => {
-                        this.headerService.user = {
-                            mode: dataUser.mode,
-                            id: dataUser.id,
-                            status: dataUser.status,
-                            userId: dataUser.user_id,
-                            firstname: dataUser.firstname,
-                            lastname: dataUser.lastname,
-                            entities: dataUser.entities,
-                            groups: dataUser.groups,
-                            preferences: dataUser.preferences,
-                            privileges: dataUser.privileges[0] === 'ALL_PRIVILEGES' ? this.privilegeService.getAllPrivileges() : dataUser.privileges
-                        };
-                        this.functionService.debug('', route.url.join('/'));
-                        this.headerService.nbResourcesFollowed = dataUser.nbFollowedResources;
-                        this.privilegeService.resfreshUserShortcuts();
-                        if (this.headerService.user.status === 'ABS') {
-                            return this.router.navigate(['/activate-user']);
-                        } else if (this.localStorage.get('MaarchCourrierUrl_' + JSON.parse(atob(tokenInfo.split('.')[1])).user.id) !== route.url.join('/')) {
-                            return this.router.navigate(['/' + this.localStorage.get('MaarchCourrierUrl_' + JSON.parse(atob(tokenInfo.split('.')[1])).user.id)]);
+                        if (urlArr.filter((url: any) => ['signatureBook', 'content'].indexOf(url) > -1).length > 0) {
+                            this.headerService.hideSideBar = true;
                         } else {
-                            if (urlArr.filter((url: any) => ['signatureBook', 'content'].indexOf(url) > -1).length > 0) {
-                                this.headerService.hideSideBar = true;
-                            } else {
-                                this.headerService.hideSideBar = false;
-                            }
-                            if (urlArr.filter((url: any) => url === 'administration').length > 0 || urlArr.filter((url: any) => url === 'profile').length > 0) {
-                                this.headerService.sideBarAdmin = true;
-                            } else {
-                                this.headerService.sideBarAdmin = false;
-                            }
-                            return true;
+                            this.headerService.hideSideBar = false;
                         }
-                    }),
-                    catchError((err: any) => {
-                        console.log(err);
-                        if (err.error.errors === 'User must change his password') {
-                            return this.router.navigate(['/password-modification']);
+                        if (urlArr.filter((url: any) => url === 'administration').length > 0 || urlArr.filter((url: any) => url === 'profile').length > 0) {
+                            this.headerService.sideBarAdmin = true;
                         } else {
-                            this.authService.logout();
-                            return of(false);
+                            this.headerService.sideBarAdmin = false;
                         }
-                    })
-                );
+                        return true;
+                    }
 
-        }
+                }),
+                catchError((err: any) => {
+                    console.log(err);
+                    if (err.error.errors === 'User must change his password') {
+                        return this.router.navigate(['/password-modification']);
+                    } else {
+                        return of(false);
+                    }
+                })
+            );
     }
 }
 
diff --git a/src/frontend/service/app.service.ts b/src/frontend/service/app.service.ts
index b8cafdc40e0035e7501d2a4e712510692dd27f87..abdcfbc5d87fc68ac63142254142cda88fbaf690 100644
--- a/src/frontend/service/app.service.ts
+++ b/src/frontend/service/app.service.ts
@@ -36,44 +36,4 @@ export class AppService {
     setScreenWidth(width: number) {
         this.screenWidth = width;
     }
-
-    applyMinorUpdate() {
-        const loader = '<div id="updateLoading" style="position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width: 200px;text-align: center;"><img src="assets/spinner.gif"></div>';
-        $('body').append(loader);
-        return new Promise((resolve) => {
-            this.http.put('../rest/versionsUpdateSQL', {}).pipe(
-                tap((data: any) => {
-                    resolve(true);
-                    $('#updateLoading').remove();
-                }),
-                finalize(() => $('#updateLoading').remove()),
-                catchError((err: any) => {
-                    this.notify.handleSoftErrors(err);
-                    resolve(true);
-                    return of(false);
-                })
-            ).subscribe();
-        });
-    }
-
-    checkAppSecurity() {
-        this.authService.catchEvent().subscribe((result: any) => {
-            if (result === 'authenticationInformations') {
-                if (this.authService.changeKey) {
-                    setTimeout(() => {
-                        this.dialog.open(AlertComponent, {
-                            panelClass: 'maarch-modal',
-                            autoFocus: false,
-                            disableClose: true,
-                            data: {
-                                mode: 'danger',
-                                title: this.translate.instant('lang.warnPrivateKeyTitle'),
-                                msg: this.translate.instant('lang.warnPrivateKey')
-                            }
-                        });
-                    }, 1000);
-                }
-            }
-        });
-    }
 }
diff --git a/src/frontend/service/auth-interceptor.service.ts b/src/frontend/service/auth-interceptor.service.ts
index 2da88ea702668ce987cb6505696b61e70c175c8a..b172fe2762d11f369035cb2589075493d3f1311d 100644
--- a/src/frontend/service/auth-interceptor.service.ts
+++ b/src/frontend/service/auth-interceptor.service.ts
@@ -5,7 +5,6 @@ import { catchError, switchMap } from 'rxjs/operators';
 import { NotificationService } from './notification/notification.service';
 import { AuthService } from './auth.service';
 import { Router } from '@angular/router';
-import { FunctionsService } from './functions.service';
 import { Observable, of } from 'rxjs';
 
 @Injectable()
@@ -48,7 +47,6 @@ export class AuthInterceptor implements HttpInterceptor {
         private router: Router,
         public notificationService: NotificationService,
         public authService: AuthService,
-        private functionsService: FunctionsService
     ) { }
 
     addAuthHeader(request: HttpRequest<any>) {
@@ -68,7 +66,6 @@ export class AuthInterceptor implements HttpInterceptor {
     }
 
     intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
-
         if (this.byPassToken.filter(url => request.url.indexOf(url.route) > -1 && url.method.indexOf(request.method) > -1).length > 0) {
             return next.handle(request);
         } else {
@@ -87,14 +84,14 @@ export class AuthInterceptor implements HttpInterceptor {
                     if (this.byPassHandleErrors.filter(url => request.url.indexOf(url.route) > -1 && url.method.indexOf(request.method) > -1).length > 0) {
                         return next.handle(request);
                     } else if (error.status === 401) {
-                        this.functionsService.debug('Auth error', request.url);
+                        console.debug('Auth error', request.url);
                         return this.http.get('../rest/authenticate/token', {
                             params: {
                                 refreshToken: this.authService.getRefreshToken()
                             }
                         }).pipe(
                             switchMap((data: any) => {
-                                this.functionsService.debug('Attempt get token ... !', request.url);
+                                console.debug('Attempt get token ... !', request.url);
                                 // Update stored token
                                 this.authService.setToken(data.token);
 
@@ -108,7 +105,12 @@ export class AuthInterceptor implements HttpInterceptor {
                                     catchError(err => {
                                         // Disconnect user if bad token process
                                         if (err.status === 401) {
-                                            this.logout();
+                                            if (this.router.url !== '/login' && this.router.url !== '/') {
+                                                this.logout();
+                                            } else {
+                                                return next.handle(request);
+                                            }
+
                                             return of(false);
                                         }
                                     })
@@ -118,8 +120,12 @@ export class AuthInterceptor implements HttpInterceptor {
                             catchError(err => {
                                 // Disconnect user if bad token process
                                 if (err.status === 401) {
-                                    this.functionsService.debug('Refresh token failed !', request.url);
-                                    this.logout();
+                                    console.debug('Refresh token failed !', request.url);
+                                    if (this.router.url !== '/login' && this.router.url !== '/') {
+                                        this.logout();
+                                    } else {
+                                        return next.handle(request);
+                                    }
                                 }
                                 return of(false);
                             })
diff --git a/src/frontend/service/auth.service.ts b/src/frontend/service/auth.service.ts
index d980b410e40914e7ecb2926b077b5da6dc4860b6..6f4344e46f15683e9ee239c3bf68db98c91bcff1 100644
--- a/src/frontend/service/auth.service.ts
+++ b/src/frontend/service/auth.service.ts
@@ -4,25 +4,38 @@ import { Router } from '@angular/router';
 import { LocalStorageService } from './local-storage.service';
 import { NotificationService } from './notification/notification.service';
 import { HeaderService } from './header.service';
-import { Observable, Subject } from 'rxjs';
-import { tap } from 'rxjs/operators';
+import { Observable, of, Subject } from 'rxjs';
+import { catchError, finalize, map, tap } from 'rxjs/operators';
+import { PrivilegeService } from './privileges.service';
+import { AlertComponent } from '@plugins/modal/alert.component';
+import { FunctionsService } from './functions.service';
+import { MatDialog } from '@angular/material/dialog';
+import { TranslateService } from '@ngx-translate/core';
 
 @Injectable({
     providedIn: 'root'
 })
 export class AuthService {
 
+    applicationName: string = '';
+    loginMessage: string = '';
     authMode: string = 'default';
     authUri: string = '';
     changeKey: boolean = null;
     user: any = {};
+    noInstall: boolean = false;
     private eventAction = new Subject<any>();
 
     constructor(public http: HttpClient,
         private router: Router,
         private headerService: HeaderService,
         private notify: NotificationService,
-        private localStorage: LocalStorageService) { }
+        private localStorage: LocalStorageService,
+        private privilegeService: PrivilegeService,
+        private functionsService: FunctionsService,
+        public dialog: MatDialog,
+        public translate: TranslateService,
+    ) { }
 
     catchEvent(): Observable<any> {
         return this.eventAction.asObservable();
@@ -121,7 +134,7 @@ export class AuthService {
     }
 
     isAuth(): boolean {
-        return this.getToken() !== null;
+        return this.headerService.user.id !== undefined;
     }
 
     updateUserInfo(token: string) {
@@ -152,4 +165,125 @@ export class AuthService {
     setUser(value: any) {
         this.user = value;
     }
+
+    applyMinorUpdate() {
+        console.debug('applyMinorUpdate');
+        const loader = '<div id="updateLoading" style="position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width: 200px;text-align: center;"><img src="assets/spinner.gif"></div>';
+        $('body').append(loader);
+        this.http.put('../rest/versionsUpdateSQL', {}).pipe(
+            finalize(() => $('#updateLoading').remove()),
+            catchError((err: any) => {
+                this.notify.handleSoftErrors(err);
+                return of(false);
+            })
+        ).subscribe();
+    }
+
+    checkAppSecurity() {
+        console.debug('checkAppSecurity');
+        if (this.changeKey) {
+            setTimeout(() => {
+                this.dialog.open(AlertComponent, {
+                    panelClass: 'maarch-modal',
+                    autoFocus: false,
+                    disableClose: true,
+                    data: {
+                        mode: 'danger',
+                        title: this.translate.instant('lang.warnPrivateKeyTitle'),
+                        msg: this.translate.instant('lang.warnPrivateKey')
+                    }
+                });
+            }, 1000);
+        }
+    }
+
+    getLoginInformations(currentRoute: string): Observable<any> {
+        if (this.noInstall) {
+            if (currentRoute === '/install') {
+                return of(true);
+            } else {
+                this.router.navigate(['/install']);
+                return of(false);
+            }
+        } else if (this.getAppSession() !== null) {
+            return of(true);
+        } else {
+            return this.http
+                .get('../rest/authenticationInformations')
+                .pipe(
+                    tap((data: any) => {
+                        console.debug('getLoginInformations');
+                        this.setAppSession(data.instanceId);
+                        this.changeKey = data.changeKey;
+                        this.applicationName = data.applicationName;
+                        this.loginMessage = data.loginMessage;
+                        this.setEvent('authenticationInformations');
+                        this.authMode = data.authMode;
+                        this.authUri = data.authUri;
+
+                        if (this.authMode === 'keycloak') {
+                            const keycloakState = this.localStorage.get('keycloakState');
+                            if (keycloakState === null || keycloakState === 'null') {
+                                this.localStorage.save('keycloakState', data.keycloakState);
+                            }
+                        }
+                        this.applyMinorUpdate();
+                        this.checkAppSecurity();
+                    }),
+                    catchError((err: any) => {
+                        console.log(err);
+                        return this.http.get('../rest/validUrl').pipe(
+                            map((data: any) => {
+                                if (!this.functionsService.empty(data.url)) {
+                                    window.location.href = data.url;
+                                    return false;
+                                } else if (data.lang === 'moreOneCustom') {
+                                    this.dialog.open(AlertComponent, { panelClass: 'maarch-modal', autoFocus: false, disableClose: true, data: { title: this.translate.instant('lang.accessNotFound'), msg: this.translate.instant('lang.moreOneCustom'), hideButton: true } });
+                                    return false;
+                                } else if (data.lang === 'noConfiguration') {
+                                    this.noInstall = true;
+                                    if (currentRoute === '/install') {
+                                        return true;
+                                    } else {
+                                        console.log(this.router.url, 'navigate to install');
+                                        this.router.navigate(['/install']);
+                                        return false;
+                                    }
+                                } else {
+                                    // this.notify.handleSoftErrors(err);
+                                }
+                            })
+                        );
+                    })
+                );
+        }
+    }
+
+    getCurrentUserInfo(): Observable<any> {
+        if (this.isAuth()) {
+            return of(true);
+        } else {
+            return this.http
+                .get('../rest/currentUser/profile')
+                .pipe(
+                    tap((data: any) => {
+                        console.debug('getCurrentUserInfo');
+                        this.headerService.user = {
+                            mode: data.mode,
+                            id: data.id,
+                            status: data.status,
+                            userId: data.user_id,
+                            firstname: data.firstname,
+                            lastname: data.lastname,
+                            entities: data.entities,
+                            groups: data.groups,
+                            preferences: data.preferences,
+                            privileges: data.privileges[0] === 'ALL_PRIVILEGES' ? this.privilegeService.getAllPrivileges() : data.privileges
+                        };
+                        this.headerService.nbResourcesFollowed = data.nbFollowedResources;
+                        this.privilegeService.resfreshUserShortcuts();
+                    })
+                );
+        }
+    }
 }
diff --git a/src/frontend/service/functions.service.ts b/src/frontend/service/functions.service.ts
index a0aeeead9c068f2b62f6c453110d32efafceb371..a37c40cd32968a188f6462bff7c1dfcd244e7420 100644
--- a/src/frontend/service/functions.service.ts
+++ b/src/frontend/service/functions.service.ts
@@ -1,7 +1,6 @@
 import { Injectable } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 import { LatinisePipe } from 'ngx-pipes';
-import { AuthService } from './auth.service';
 import { HeaderService } from './header.service';
 import { TimeLimitPipe } from '../plugins/timeLimit.pipe';
 
@@ -12,7 +11,6 @@ export class FunctionsService {
 
     constructor(
         public translate: TranslateService,
-        private authService: AuthService,
         private headerService: HeaderService,
         private latinisePipe: LatinisePipe,
     ) { }
@@ -126,35 +124,6 @@ export class FunctionsService {
         return filterReturn;
     }
 
-    debug(msg: string, route: string) {
-        let info: any = {
-            route : route,
-            session : 'No user logged !',
-            refreshSession : 'No user logged !',
-            user : 'No user logged !'
-        };
-        if (this.authService.getToken() != null) {
-            info = {
-                route : route,
-                session : {
-                    id : this.authService.getAppSession(),
-                    expireIn : new Date((JSON.parse(atob(this.authService.getToken().split('.')[1])).exp) * 1000)
-                },
-                refreshSession : {
-                    id : this.authService.getAppSession(),
-                    expireIn : new Date((JSON.parse(atob(this.authService.getRefreshToken().split('.')[1])).exp) * 1000)
-                },
-                user : this.headerService.user,
-            };
-        }
-
-        if (msg !== '') {
-            console.log(msg, info);
-        } else {
-            console.log(info);
-        }
-    }
-
     formatBytes(bytes: number, decimals = 2) {
         if (typeof bytes === 'number') {
             if (bytes === 0) { return '0 Octet'; }
diff --git a/src/frontend/service/local-storage.service.ts b/src/frontend/service/local-storage.service.ts
index 30b095de667315ad26bb08712340ae3bfde860d3..dc49bfa38fb0a392a1c6c718c04e4a0984b475e8 100644
--- a/src/frontend/service/local-storage.service.ts
+++ b/src/frontend/service/local-storage.service.ts
@@ -4,7 +4,7 @@ import { Injectable } from '@angular/core';
     providedIn: 'root'
 })
 export class LocalStorageService {
-    appSession: any;
+    appSession: any = null;
 
     constructor() { }
 
diff --git a/src/frontend/service/privileges.service.ts b/src/frontend/service/privileges.service.ts
index 9f56d95eedc9a1613b6f578c37ee41be4a4705f5..ee3f3066405f8c65ff31edbe6a11654926dabc62 100755
--- a/src/frontend/service/privileges.service.ts
+++ b/src/frontend/service/privileges.service.ts
@@ -572,6 +572,16 @@ export class PrivilegeService {
             'unit': 'registeredMails',
             'angular': true,
             'shortcut': false
+        },
+        {
+            'id': 'create_custom',
+            'label': 'lang.installNewCustom',
+            'comment': 'lang.installNewCustom',
+            'route': '/install',
+            'style': 'far fa-window-restore',
+            'unit': 'application',
+            'angular': true,
+            'shortcut': false
         }
     ];
 
diff --git a/src/frontend/tslint.json b/src/frontend/tslint.json
index f6dab386bff89bef5a21127389dfaee084aed807..bca6bbf21de88cc6cfb8677d43f1745a519d3b8a 100644
--- a/src/frontend/tslint.json
+++ b/src/frontend/tslint.json
@@ -49,7 +49,6 @@
     "no-bitwise": true,
     "no-console": [
       true,
-      "debug",
       "info",
       "time",
       "timeEnd",
diff --git a/src/lang/lang-fr.json b/src/lang/lang-fr.json
index 1627e5b7730470a0dd4c022e4aefe4aec943ed2b..4a5eb3fed9362e65fb1512b63f4923e507776c7e 100644
--- a/src/lang/lang-fr.json
+++ b/src/lang/lang-fr.json
@@ -2125,5 +2125,9 @@
     "restrictAccess": "Accès retreint",
     "transfer": "Transfert SAE + destruction",
     "copy": "Transfert SAE + accès restreint",
-    "deleteAction": "Suppression"
+    "deleteAction": "Suppression",
+    "installNewCustom": "Créer une nouvelle instance",
+    "mustConnectToInstall" : "Veuillez vous connecter pour accéder à l'installeur",
+    "mustPrivilegeToInstall" : "Vous n'avez pas le droit de créer une nouvelle instance",
+    "instancesList" : "Instances présentes"
 }