diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 59111b6c8602d03d4c0d954364413f6f6dfd2b3c..ca9b96403403231ff452d8fd94b9fe9207c104be 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,6 +20,7 @@ sonar:
   image: trion/ng-cli:17.3.7
   only:
     - develop
+    - /^release/
   script:
     - npm ci --force
     - npm run sonar -- -Dsonar.host.url=${SONAR_HOST} -Dsonar.projectKey=${SONAR_PROJECT_KEY} -Dsonar.projectName=${SONAR_PROJECT_NAME} -Dsonar.branch.name=develop -Dsonar.login=${SONAR_LOGIN_TOKEN}
diff --git a/build.gradle b/build.gradle
index b0f93a8b25f6963e6821448de89bd40a1cb6ccc0..a443e5382e46befdc5870955a7650591f7e79e96 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ plugins {
 	id "org.sonarqube" version "3.2.0"
 }
 
-version = '1.6.5'
+version = '1.7.0-SNAPSHOT'
 
 task buildGUI(type: Exec) {
 	println 'Building using Angular CLI'
diff --git a/package-lock.json b/package-lock.json
index 2158b8b4014ac3f0dbe34ebdc01a4c2d4d563d8d..9587e3edb93829b96b09f645a89e4907917c705d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "nmaas-portal",
-  "version": "1.6.5",
+  "version": "1.7.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "nmaas-portal",
-      "version": "1.6.5",
+      "version": "1.7.0",
       "license": "Apache 2.0",
       "dependencies": {
         "@angular/animations": "17.3.12",
diff --git a/package.json b/package.json
index 09a8e774d77de12a925911a29ee16690f7e7194c..6c76618594cd9546a117d73864d93c6fccfd124d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nmaas-portal",
-  "version": "1.6.5",
+  "version": "1.7.0",
   "license": "Apache 2.0",
   "angular-cli": {},
   "scripts": {
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index c16ff45ea28e9f74a889c241a77b0d005624c223..610c10ccf5c6a61d2610e4be2b3fdefe9e51fcde 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -5,13 +5,16 @@ import { AppMarketRoutes } from './appmarket';
 import { WelcomeRoutes } from './welcome/welcome.routes';
 import {ServiceUnavailableRoutes} from './service-unavailable/service-unavailable.routes';
 import {PageNotFoundComponent} from './shared/page-not-found/page-not-found.component';
+import {LoginSuccessComponent} from './auth/login-success/login-success.component';
 
 const appRoutes: Routes = [
     ...WelcomeRoutes,
     ...AppMarketRoutes,
     ...ServiceUnavailableRoutes,
     { path: 'notfound', component: PageNotFoundComponent },
-    { path: '**', redirectTo: '/welcome' }
+    { path: 'login-success', component: LoginSuccessComponent },
+    { path: '**', redirectTo: '/welcome' },
+
 ];
 
 export const routing = RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' });
diff --git a/src/app/appmarket/admin/configuration/details/configurationdetails.component.html b/src/app/appmarket/admin/configuration/details/configurationdetails.component.html
index 92aafcd35ac0b0fe8ffbd4b30836afee1c5b256e..de8a5d141eabd06407384500438ac27cf15ed1a3 100644
--- a/src/app/appmarket/admin/configuration/details/configurationdetails.component.html
+++ b/src/app/appmarket/admin/configuration/details/configurationdetails.component.html
@@ -131,6 +131,17 @@
                     
                     </div>
                 </div>
+                <div class="form-group">
+                    <label for="bulkDeploymentQueueRefresh"
+                           class="col-sm-3 control-label">{{'PORTAL_CONFIGURATION.BULK_DEPLOYMENT_QUEUE_REFRESH' | translate}}</label>
+                    <div class="col-sm-9 pd-top-7">
+                        <div class="input-width">
+                            <input class="form-control" type="number" id="bulkDeploymentQueueRefresh" name="bulkDeploymentQueueRefresh"
+                            [(ngModel)]="this.configuration.bulkDeploymentQueueRefresh">
+                        </div>
+                    
+                    </div>
+                </div>
                 <div class="flex justify-content-end">
                     <button class="btn btn-primary"
                             type="submit">{{ 'PORTAL_CONFIGURATION.SUBMIT_BUTTON' | translate }}</button>
diff --git a/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts b/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts
index 742069adfd21e9f305a3b14ceb8ccbbdcdf4c0ae..449459e4f4b881d437f763ae6433b6b45ad4b7b7 100644
--- a/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts
+++ b/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts
@@ -13,7 +13,6 @@ import {NgxPaginationModule} from 'ngx-pagination';
 import {AppRestartModalComponent} from '../modals/app-restart-modal';
 import {AppAbortModalComponent} from '../modals/app-abort-modal';
 import {RouterTestingModule} from '@angular/router/testing';
-import {StorageServiceModule} from 'ngx-webstorage-service';
 import {AppInstanceState, User} from '../../../model';
 import {Role} from '../../../model/userrole';
 import {ServiceAccessMethodType} from '../../../model/service-access-method';
@@ -272,7 +271,6 @@ describe('Component: AppInstance', () => {
                 PipesModule,
                 FormioModule,
                 RouterTestingModule,
-                StorageServiceModule,
                 JwtModule.forRoot({}),
                 TranslateModule.forRoot({
                     loader: {
diff --git a/src/app/appmarket/appmarket.module.ts b/src/app/appmarket/appmarket.module.ts
index 8bd9ce86288da65d981ac9fe9af4363df7b433b3..1539264532ea45f31fb58cb059887338c5cecf57 100644
--- a/src/app/appmarket/appmarket.module.ts
+++ b/src/app/appmarket/appmarket.module.ts
@@ -21,7 +21,6 @@ import {ClustersModule} from './admin/clusters/clusters.module';
 import {ClusterService} from '../service/cluster.service';
 import {ConfigurationModule} from './admin/configuration/configuration.module';
 import {MonitorModule} from './admin/monitor/monitor.module';
-import {StorageServiceModule} from 'ngx-webstorage-service';
 import {TranslateModule} from '@ngx-translate/core';
 import {HttpClientModule} from '@angular/common/http';
 import {BrowserModule} from '@angular/platform-browser';
@@ -48,6 +47,12 @@ import {NgxPaginationModule} from 'ngx-pagination';
 import {InputTextModule} from 'primeng/inputtext';
 import {BulkSearchPipe} from './bulkDeployment/bulk-list/bulk-search.pipe';
 import {CheckboxModule} from 'primeng/checkbox';
+import { InputSwitchModule } from 'primeng/inputswitch';
+import { OverlayPanelModule } from 'primeng/overlaypanel';
+import { SidebarModule } from 'primeng/sidebar';
+import { ProgressBarModule } from 'primeng/progressbar';
+
+
 
 @NgModule({
     declarations: [
@@ -66,7 +71,6 @@ import {CheckboxModule} from 'primeng/checkbox';
     ],
     imports: [
         FormsModule,
-        StorageServiceModule,
         CommonModule,
         RouterModule,
         SharedModule,
@@ -94,6 +98,10 @@ import {CheckboxModule} from 'primeng/checkbox';
         InputTextModule,
         TooltipModule,
         CheckboxModule,
+        InputSwitchModule,
+        OverlayPanelModule,
+        SidebarModule,
+        ProgressBarModule
     ],
     exports: [
         AppMarketComponent,
diff --git a/src/app/appmarket/bulkDeployment/appdeployment.service.ts b/src/app/appmarket/bulkDeployment/appdeployment.service.ts
index e754e949023a94f7ceb1fcb65c90f7f0f8a7ab62..a44c0f9cc361bc8f12b247c5f9a1534fdbfe11f0 100644
--- a/src/app/appmarket/bulkDeployment/appdeployment.service.ts
+++ b/src/app/appmarket/bulkDeployment/appdeployment.service.ts
@@ -1,10 +1,11 @@
 import {Injectable} from '@angular/core';
 import {ApplicationBase} from '../../model/application-base';
-import {HttpClient} from '@angular/common/http';
+import {HttpClient, HttpParams} from '@angular/common/http';
 import {AppConfigService} from '../../service';
 import {BulkResponse} from '../../model/bulk-response';
 import {Observable} from 'rxjs';
 import {BulkDeployment} from '../../model/bulk-deployment';
+import { BulkQueueDetails } from '../../model/bulk-queue-details';
 
 @Injectable({
     providedIn: 'root'
@@ -71,16 +72,20 @@ export class AppdeploymentService {
         return this.http.post<BulkDeployment>(this.getUrl() + 'domains', formParams);
     }
 
-    public getBulksDomainDeployments(): Observable<BulkDeployment[]> {
-        return this.http.get<BulkDeployment[]>(this.getUrl() + 'domains');
+    public getBulksDomainDeployments(showDeleted: boolean = false): Observable<BulkDeployment[]> {
+        const formParams = new HttpParams().append('deleted', showDeleted);
+    
+        return this.http.get<BulkDeployment[]>(this.getUrl() + 'domains', {params:formParams});
     }
 
     public getBulksDomainDeploymentsOwner(): Observable<BulkDeployment[]> {
         return this.http.get<BulkDeployment[]>(this.getUrl() + 'domains/vl');
     }
 
-    public getBulksAppDeployments(): Observable<BulkDeployment[]> {
-        return this.http.get<BulkDeployment[]>(this.getUrl() + 'apps');
+    public getBulksAppDeployments(showDeleted: boolean = false): Observable<BulkDeployment[]> {
+        const formParams = new HttpParams().append('deleted', showDeleted);
+
+        return this.http.get<BulkDeployment[]>(this.getUrl() + 'apps', {params:formParams});
     }
 
     public getBulksAppDeploymentsOwner(): Observable<BulkDeployment[]> {
@@ -99,5 +104,14 @@ export class AppdeploymentService {
         return this.http.get<BulkDeployment>(this.getUrl() + `refresh/${id}`)
     }
 
+    public removeBulkDeployment(id: number, removeAll: boolean)  {
+        const params = new HttpParams().set('removeAll', removeAll);
+        return this.http.delete(this.getUrl() +`${id}`, { params });
+    }
+
+    public getQueueDetails(id: number) : Observable<BulkQueueDetails> {
+        return this.http.get<BulkQueueDetails>(this.getUrl() + `queue/${id}`)
+    }
+
 
 }
diff --git a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html
index e34eee5938d37ec4330b3cd1f1ebdc2d9659707f..340557d5220556e32498ffcac2549231bde94c23 100644
--- a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html
+++ b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.html
@@ -1,2 +1,2 @@
-<app-bulk-list [header]="'BULK.APP.HEADER'" [bulks]="bulks" [mode]="mode"></app-bulk-list>
+<app-bulk-list [header]="'BULK.APP.HEADER'" [bulks]="bulks" [mode]="mode" (refresh)="onRefresh($event)"></app-bulk-list>
 
diff --git a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts
index 9256cfa4ea2a99172b68b96471a1312b92bb206d..4a773179c64068601af012a9fe6506a818eecfbe 100644
--- a/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts
+++ b/src/app/appmarket/bulkDeployment/bulk-app-list/bulk-app-list.component.ts
@@ -20,16 +20,20 @@ export class BulkAppListComponent implements OnInit {
     }
 
     ngOnInit(): void {
+     this.onRefresh();
+    }
+
+    onRefresh(showDeleted = false) : void {
         if (this.authService.getRoles().find(value => value === 'ROLE_VL_MANAGER') !== undefined) {
             this.deployService.getBulksAppDeploymentsOwner().subscribe(data => {
                 data = data.sort((a, b) => new Date(b.creationDate).getTime() - new Date(a.creationDate).getTime())
                 this.bulks = data
             });
         } else {
-            this.deployService.getBulksAppDeployments().subscribe(data => {
+            this.deployService.getBulksAppDeployments(showDeleted).subscribe(data => {
                 data = data.sort((a, b) => new Date(b.creationDate).getTime() - new Date(a.creationDate).getTime())
                 this.bulks = data
             });
         }
     }
-}
+ }
diff --git a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html
index 7a9fc5815787d93905e271793dc971856f8a1bcc..06d42a13307598d26cd863a2d5d086d6b4284510 100644
--- a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html
+++ b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.html
@@ -7,7 +7,40 @@
         <div *ngIf="mode=== bulkTypeApp">
             <button class="btn btn-primary" [routerLink]="['/admin/apps/bulks/new']">New deployment</button>
         </div>
+        
         <div class="flex">
+            <div  *roles="['ROLE_SYSTEM_ADMIN', 'ROLE_VL_MANAGER']"  class="flex align-items-center mr-6">
+        
+                <p-button 
+                    type="button" 
+                    class="mr-2" 
+                    (onClick)="sidebarVisible4 = true" 
+                    label="Deployments Queue"
+                    severity="secondary"
+                     ></p-button>
+                <p-sidebar [(visible)]="sidebarVisible4" position="left" styleClass="w-30rem">
+                    <h3>Deployments Queue</h3>
+                    <div class="flex flex-column">
+                        <div class="flex grid">
+                            <label class="col-10" for="jobInQueue">Jobs in queue</label>
+                            <span class="col-2 " id="jobInQueue">{{queueDetails?.jobInQueue}}</span>
+                        </div>
+                        <div class="flex grid">
+                            <label class="col-10" for="jobInProcess">In progress</label>
+                            <span class="col-2 " id="jobInProcess">{{queueDetails?.jobInProcess}}</span>
+                        </div>
+                        <div class="flex grid">
+                            <label class="col-10" for="jobInProcessId">Current proccessing bulk id</label>
+                            <span class="col-2" id="jobInProcessId">{{queueDetails?.jobInProcessId}}</span>
+                        </div>
+                    </div>
+                </p-sidebar>
+                
+            </div>
+            <div  *roles="['ROLE_SYSTEM_ADMIN']"  class="flex align-items-center mr-6 pt-2">
+                <label  *ngIf="mode=== bulkTypeApp" class="mr-2" for="showDeleted">Show all</label>
+                <p-inputSwitch  *ngIf="mode=== bulkTypeApp"  id="showDeleted" (onChange)="refreshBulks()" [(ngModel)]="showDeleted" ngDefaultControl/>
+            </div>
             <div class="flex align-items-center mr-1">{{ 'BULK.LIST.PER_PAGE' | translate }}:</div>
             <span id="selectionItems" class="dropdown"
                   style="vertical-align: middle; display: inline-block; margin-right: 1rem;">
@@ -102,8 +135,8 @@
                 <li *ngIf="mode === bulkTypeApp && bulk?.state !== 'REMOVED'">
                     <a (click)="getAppBulkDetails(bulk?.id)"> {{"BULK.APP.DOWNLOAD_CSV" | translate}}</a>
                 </li>
-                <li *ngIf="mode === bulkTypeApp && bulk?.state !== 'REMOVED' ">
-                    <a (click)="modal.show()">{{ 'BULK.LIST.REMOVE' | translate }}</a>
+                <li *ngIf="mode === bulkTypeApp && !(bulk?.state === 'REMOVED' || bulk?.deleted )">
+                    <a (click)="modal.show(); removeBulkId=bulk?.id">{{ 'BULK.LIST.REMOVE' | translate }}</a>
                 </li>
             </ul>
           </span>
@@ -133,6 +166,6 @@
     </div>
     <div class="nmaas-modal-footer">
         <button type="button" class="btn btn-secondary" (click)="modal.hide()">{{'APP_CHANGE_STATE_MODAL.CANCEL_BUTTON' | translate}}</button>
-        <button type="button" class="btn btn-primary"   [disabled]="false">{{'BULK.REMOVE.REMOVE' | translate}}</button>
+        <button type="button" class="btn btn-primary"   (click)="this.removeBulk()">{{'BULK.REMOVE.REMOVE' | translate}}</button>
     </div>
 </nmaas-modal>
diff --git a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts
index 8288379d544ee7f88744f62d8ee497a98c9d199c..4883a6bb95b8301576a8479a0d1aac8524bd0cb3 100644
--- a/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts
+++ b/src/app/appmarket/bulkDeployment/bulk-list/bulk-list.component.ts
@@ -1,17 +1,20 @@
-import {Component, Input, QueryList, ViewChild, ViewChildren} from '@angular/core';
+import {Component, EventEmitter, Input, OnDestroy, OnInit, Output, QueryList, ViewChild, ViewChildren} from '@angular/core';
 import {BulkDeployment} from '../../../model/bulk-deployment';
 import {BulkType} from '../../../model/bulk-response';
 import {SortableHeaderDirective} from '../../../service/sort-domain.directive';
 import {ModalComponent} from '../../../shared';
 import {AppdeploymentService} from '../appdeployment.service';
 import {DomSanitizer} from '@angular/platform-browser';
+import { BulkQueueDetails } from '../../../model/bulk-queue-details';
+import { map, timer } from 'rxjs';
+import { ConfigurationService } from '../../../service';
 
 @Component({
     selector: 'app-bulk-list',
     templateUrl: './bulk-list.component.html',
     styleUrls: ['./bulk-list.component.css']
 })
-export class BulkListComponent {
+export class BulkListComponent implements OnDestroy, OnInit {
 
     public static BULK_ENTRY_DETAIL_KEY_APP_INSTANCE_NO = 'appInstanceNo';
     public static BULK_ENTRY_DETAIL_KEY_APP_INSTANCE_NAME = 'appName';
@@ -32,6 +35,10 @@ export class BulkListComponent {
     @ViewChild(ModalComponent, {static: true})
     public readonly modal: ModalComponent;
 
+    @Output()
+    public refresh: EventEmitter<boolean> = new EventEmitter<boolean>();
+
+    public showDeleted = false;
 
     public readonly bulkTypeDomain = BulkType.DOMAIN;
     public readonly bulkTypeApp = BulkType.APPLICATION;
@@ -42,9 +49,26 @@ export class BulkListComponent {
     public searchValue = '';
 
     public removeAll = false;
+    public removeBulkId = 0;
+
+    public queueDetails : BulkQueueDetails;
+
+    public refreshQueue = undefined;
+    public sidebarVisible4 = false;
+
+    public configRefresh = 60;
+
 
     constructor(private appDeploy: AppdeploymentService,
-                private sanitizer: DomSanitizer) {
+                private sanitizer: DomSanitizer,
+                private configService: ConfigurationService) {   
+    }
+
+    public ngOnInit(): void {
+        this.configService.getConfiguration().subscribe(conf => {
+            this.configRefresh = conf.bulkDeploymentQueueRefresh;
+            this.update();
+        })
     }
 
     public getApplicationName(details: Map<string, string>) {
@@ -147,4 +171,44 @@ export class BulkListComponent {
         }
         return null
     }
+
+    public removeBulk(): void {
+        this.appDeploy.removeBulkDeployment(this.removeBulkId, this.removeAll).subscribe(_ => {
+            this.refreshBulks();
+            this.modal.hide();
+        })
+        this.removeAll = false;
+    }
+
+    public refreshBulks(): void {
+        this.refresh.emit(this.showDeleted);
+    }
+
+    public getQueueDetails(): void {
+        this.appDeploy.getQueueDetails(0).subscribe(queue => {
+           console.log(queue);
+           this.queueDetails = queue;
+        })   
+    }
+
+     public update() {
+            this.refreshQueue = timer(0, this.refreshQueue * 1000).pipe(map(() => {
+              this.getQueueDetails();
+            })).subscribe()
+        }
+
+    public getQueryNumber() {
+        return this.queueDetails?.jobInQueue + this.queueDetails?.jobInProcess;
+    }
+
+        
+    public ngOnDestroy() {
+        if (this.refreshQueue !== undefined) {
+            this.refreshQueue.unsubscribe();
+        }
+    }
+
+    public open() {
+
+    }
 }
diff --git a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.css b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.css
index 415a4d52c3f56b52ae0540dc65b55bf5b1c3d599..66d99ef9dc8e1b044db0c92653980615c5db3ea5 100644
--- a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.css
+++ b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.css
@@ -34,4 +34,13 @@
     white-space: nowrap !important;
 }
 
+:host ::ng-deep .job-done-bar {
+    .p-progressbar-value {
+        border: 0 none;
+        margin: 0;
+        background:green;
+    }
+}
+    
+
 
diff --git a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html
index c40a1ff6969dfe5322906d7e116981f228ef913a..9c870590051db4025f7b3d0dffbaeee499a71785 100644
--- a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html
+++ b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.html
@@ -62,7 +62,7 @@
                             <td>{{getDomainId(response)}}</td>
                             <td>{{getDomainName(response)}}</td>
                             <td>{{getDomainCodeName(response)}}</td>
-                            <td style="width: 5%" class="text-right">
+                            <td style="width: 5%" class="text-right" *ngIf="bulk.state !== 'REMOVED'">
                                 <i *ngIf="response.type === 'DOMAIN'" class="pi pi-search" style="font-size: 1.8rem; cursor: pointer" [routerLink]="['/admin/domains/view/', response?.details['domainId']]"></i>
                                 <i *ngIf="response.type === 'USER'" class="pi pi-search" style="font-size: 1.8rem; cursor: pointer" [routerLink]="['/admin/users/view', response?.details['userId']]"></i>
                     <!-- <span class="dropdown">
@@ -160,6 +160,15 @@
             </div>
         </div>
 
+        <div class="" style="padding-bottom: 5rem;">
+            <label for="id" class="col-sm-2 control-label text-right mt-2">{{ 'BULK.LIST.APP_NAME' | translate }}</label>
+            <div class="col-sm-10">
+                <input type="text" class="form-control" id="id" name="id" [disabled]="true"
+                       [(ngModel)]="bulk.details['appName']" #name="ngModel">
+            </div>
+            
+        </div>
+
         <div class="" style="padding-bottom: 5rem">
             <label for="creator"
                    class="col-sm-2 control-label text-right mt-2">{{ 'BULK.LIST.CREATOR' | translate }}</label>
@@ -187,21 +196,31 @@
             </div>
         </div>
 
-        <div class="" style="padding-bottom: 5rem;">
-            <label for="id" class="col-sm-2 control-label text-right mt-2">{{ 'BULK.LIST.APP_NAME' | translate }}</label>
+        <div class="" style="padding-bottom: 5rem">
+            <label for="completionDate"
+                   class="col-sm-2 control-label text-right mt-2">{{ 'BULK.LIST.COMPLETION_DATE' | translate }}</label>
             <div class="col-sm-10">
-                <input type="text" class="form-control" id="id" name="id" [disabled]="true"
-                       [(ngModel)]="bulk.details['appName']" #name="ngModel">
+                <input type="text" class="form-control" id="completionDate" name="completionDate" [disabled]="true"
+                       placeholder="{{completionDate}}">
             </div>
-            
         </div>
 
-        <div class="flex justify-content-end" style="padding-right: 1.5rem">
+      
+
+        <div *ngIf="bulk.state !== 'REMOVED'" class="flex justify-content-end" style="padding-right: 1.5rem">
             <button class="btn btn-primary mr-2" (click)="refreshStates()">{{'BULK.APP.REFRESH' | translate}}</button>
 
-            <button class="btn btn-primary" (click)="getAppBulkDetails(this.bulkId)">{{'BULK.APP.DOWNLOAD_CSV' | translate}}</button>
+            <button *ngIf="bulk.state !== 'FAILED'" class="btn btn-primary" (click)="getAppBulkDetails(this.bulkId)">{{'BULK.APP.DOWNLOAD_CSV' | translate}}</button>
         </div>
-        <div class="panel panel-default" style="margin-top: 3rem">
+        <div class="mt-4">
+            <p-progressBar [mode]="progressBarMode"[value]="progressBarValue" id="progressBarr" [style]="{ height: '18px' }" [styleClass]="jobDone ? 'job-done-bar' : 'normal-bar'">
+                <ng-template pTemplate="content" let-value> 
+                    <span>{{queueDetails?.jobDone}} <span *ngIf="queueDetails?.jobDone !== bulk.entries.length">(+{{queueDetails?.jobInProcess}})</span> / {{bulk.entries.length}}</span>    
+                    </ng-template>
+            </p-progressBar>
+
+        </div>
+        <div class="panel panel-default" style="margin-top: 1rem">
             <div class="panel-heading">
 
                 <div style="display: flex; justify-content: start; align-items: center">
@@ -235,8 +254,8 @@
                             <td>{{getAppInstanceId(response)}}</td>
                             <td>{{getAppInstanceName(response)}}</td>
                             <td>{{getDomainCodeName(response)}}</td>
-                            <td style="width: 5%" class="text-right">
-                                <i class="pi pi-search" style="font-size: 1.8rem; cursor: pointer" [routerLink]="['/instances/', response?.details['appInstanceId']]"></i>
+                            <td style="width: 5%" class="text-right"  >
+                                <i *ngIf="response?.details['appInstanceId'] !== undefined" class="pi pi-search" style="font-size: 1.8rem; cursor: pointer" [routerLink]="['/instances/', response?.details['appInstanceId']]"></i>
                     <!-- <span *ngIf="response?.details['appInstanceId'] !== undefined" class="dropdown">
             <a  style="display: inline-block" class="dropdown-toggle " aria-expanded="false" aria-haspopup="true"
                data-toggle="dropdown" href="#" role="button">
diff --git a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.spec.ts b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.spec.ts
index 33287d7e82506504fe8fc2bf9a4100084a49ff39..2c9c55fa673bd9e1bafe4db2fc2e97d50359fd76 100644
--- a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.spec.ts
+++ b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.spec.ts
@@ -3,6 +3,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { BulkViewComponent } from './bulk-view.component';
 import {HttpClientTestingModule} from '@angular/common/http/testing';
 import {RouterModule} from '@angular/router';
+import { DatePipe } from '@angular/common';
 
 describe('BulkViewComponent', () => {
   let component: BulkViewComponent;
@@ -14,6 +15,9 @@ describe('BulkViewComponent', () => {
       imports: [
           HttpClientTestingModule,
         RouterModule.forRoot([]),
+      ],
+      providers: [
+        DatePipe
       ]
     })
     .compileComponents();
diff --git a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts
index 5895c0b6ba5531de6c627b1026c321333073a0df..4b0c59f9115bcae87a18f76b5ea7c109e3c5f9c9 100644
--- a/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts
+++ b/src/app/appmarket/bulkDeployment/bulk-view/bulk-view.component.ts
@@ -5,7 +5,9 @@ import {ActivatedRoute, Router} from '@angular/router';
 import {BulkResponse, BulkType} from '../../../model/bulk-response';
 import {timer} from 'rxjs';
 import {map} from 'rxjs/operators';
-import {AppImagesService} from '../../../service';
+import {AppImagesService, ConfigurationService} from '../../../service';
+import { BulkQueueDetails } from '../../../model/bulk-queue-details';
+import { DatePipe } from '@angular/common';
 
 @Component({
     selector: 'app-bulk-view',
@@ -20,21 +22,40 @@ export class BulkViewComponent implements OnInit, OnDestroy {
 
     public refresh = undefined;
 
+    public progressBarMode ;
+    public progressBarValue ;
+
+    public queueDetails :BulkQueueDetails; 
+
+    public jobDone = false;
+    public completionDate = "";
+
+    public configRefresh = 60;
+
     constructor(public deployService: AppdeploymentService,
                 private route: ActivatedRoute,
                 private router: Router,
                 public appImagesService: AppImagesService,
+                private datePipe: DatePipe,
+                private configService: ConfigurationService
     ) {
     }
 
     ngOnInit(): void {
+        this.configService.getConfiguration().subscribe(conf => {
+            this.configRefresh = conf.bulkDeploymentQueueRefresh;
+        })
+
         this.route.params.subscribe(params => {
             if (params['id'] !== undefined) {
                 this.bulkId = +params['id'];
                 this.deployService.getBulkDeployment(this.bulkId).subscribe(
                     (bulk) => {
                         this.bulk = bulk;
+                        this.sortByInstanceId();
                         this.bulkType = bulk.type;
+                        this.getQueueDetails();
+                        this.setCompletionDate(bulk);
                         if (this.bulkType === BulkType.APPLICATION) {
                             this.update();
                         }
@@ -88,10 +109,24 @@ export class BulkViewComponent implements OnInit, OnDestroy {
     }
 
     public update() {
-        this.refresh = timer(0, 20000).pipe(map(() => {
+        this.refresh = timer(0, this.configRefresh * 1000).pipe(map(() => {
             this.deployService.getBulkDeployment(this.bulk.id).subscribe(bulk => {
                 this.bulk = bulk;
+                this.sortByInstanceId();
+                this.setCompletionDate(bulk);
+                if(bulk.state === 'REMOVED') this.refresh.unsubscribe();
+                if(bulk.state === 'PROCESSING' && this.queueDetails.jobInProcessId === bulk.id) {
+                    this.progressBarMode = "determinate"
+                    this.setBarValue();
+                } else if(bulk.state === 'PROCESSING') {
+                    this.setBarValue();
+                    this.progressBarMode = "indeterminate"
+                } else {
+                    this.progressBarMode = "determinate"
+                    this.setBarValue();
+                }
             })
+           
         })).subscribe()
     }
 
@@ -103,7 +138,7 @@ export class BulkViewComponent implements OnInit, OnDestroy {
 
     public getAppBulkDetails(id: number) {
         this.deployService.getAppBulkDetails(id).subscribe( (data: Blob) => {
-            console.warn(data)
+            console.log(data)
             const blob = new Blob([data], { type: 'text/csv' });
             const url = window.URL.createObjectURL(blob);
             const a = document.createElement('a');
@@ -119,7 +154,43 @@ export class BulkViewComponent implements OnInit, OnDestroy {
     public refreshStates() {
         this.deployService.refreshStatesInBulkDeployment(this.bulkId).subscribe( deply => {
             this.bulk = deply;
-            console.log("Updated states of bulks")
+            this.sortByInstanceId();
+            this.setCompletionDate(deply);
+            this.getQueueDetails();
         })
     }
+
+    public setCompletionDate( deployment: BulkDeployment) {
+        if(this.bulk.completionDate !== undefined && this.bulk.completionDate !== null && deployment.state === 'COMPLETED') {
+            this.completionDate = this.datePipe.transform(this.bulk.completionDate,'dd-MM-yyyy HH:mm' )
+        } else {
+            this.completionDate = " - "
+        }
+    }
+
+    public setBarValue() {
+        this.getQueueDetails();
+    }
+    
+    public getQueueDetails(): void {
+     this.deployService.getQueueDetails(this.bulkId).subscribe(queue => {
+        this.queueDetails = queue;
+        if(queue.jobDone === this.bulk.entries.length) {
+            this.progressBarValue = 100;
+            this.jobDone = true;
+            this.progressBarMode = "determinate"
+        } else if(queue.jobDone === 0) {
+            this.progressBarMode = "indeterminate"
+        }else {
+            this.progressBarMode = "determinate"
+            this.progressBarValue =  queue.jobDone * 100 / this.bulk.entries.length;
+            this.jobDone = false;
+        }
+        
+     })   
+    }
+
+    public sortByInstanceId() {
+        this.bulk.entries.sort((a,b) => this.getAppInstanceId(a) < this.getAppInstanceId(b) ? 1 : -1);
+    }
 }
diff --git a/src/app/appmarket/users/userdetails/userdetails.component.html b/src/app/appmarket/users/userdetails/userdetails.component.html
index 6baf5888a19174411af0589f1fcfed73cbcb78e1..f728a79ce158c48bcbe6db89c05d4452d03a47c3 100644
--- a/src/app/appmarket/users/userdetails/userdetails.component.html
+++ b/src/app/appmarket/users/userdetails/userdetails.component.html
@@ -7,5 +7,6 @@
 	<div>
 	<nmaas-userdetails [user]="user" [(userDetailsMode)]="userDetailsMode" [allowedModes]="[ComponentMode.VIEW, ComponentMode.EDIT]" [(errorMessage)]="errorMessage" (onSave)="onSave($event)" (refresh)="onRefresh()"></nmaas-userdetails>
 	<nmaas-userprivileges [allowedModes]="[ComponentMode.VIEW, ComponentMode.CREATE]" [user]="user"></nmaas-userprivileges>
+	<nmaas-ssh-keys *roles="['ROLE_SYSTEM_ADMIN']" [userMode]="true" [userId]="user?.id"></nmaas-ssh-keys>
 	</div>
 </div>
diff --git a/src/app/auth/auth.guard.ts b/src/app/auth/auth.guard.ts
index aea400e0a3ccf6885624238b496fcbd5186d9e2e..2fe88c217381e865b5ed27e7a814578d5c59aa32 100644
--- a/src/app/auth/auth.guard.ts
+++ b/src/app/auth/auth.guard.ts
@@ -2,6 +2,7 @@ import {Injectable} from '@angular/core';
 import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
 import {AuthService} from './auth.service';
 import {ConfigurationService} from '../service';
+import { debounceTime } from 'rxjs';
 
 @Injectable()
 export class AuthGuard  {
@@ -11,7 +12,7 @@ export class AuthGuard  {
 
   public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
     if (this.auth.isLogged()) {
-      this.maintenanceService.getConfiguration().subscribe(value => {
+      this.maintenanceService.getConfiguration().pipe(debounceTime(500)).subscribe(value => {
          if (!this.auth.hasRole('ROLE_SYSTEM_ADMIN') && value.maintenance) {
              this.auth.logout();
              this.router.navigate(['/welcome/login']);
diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts
index 27bb76c9fc8bfe15a5c61ce85a34c6eee4dbe0fc..cab76d65d8c483ba806570bc6daa101e29e701c3 100644
--- a/src/app/auth/auth.module.ts
+++ b/src/app/auth/auth.module.ts
@@ -5,6 +5,7 @@ import {AppConfigService} from '../service/appconfig.service';
 import {AuthService} from './auth.service'
 import {AuthGuard} from './auth.guard'
 import {RoleGuard} from './role.guard';
+import { LoginSuccessComponent } from './login-success/login-success.component';
 
 
 export const jwtOptionsFactory = (appConfig: AppConfigService) => ({
@@ -15,6 +16,9 @@ export const jwtOptionsFactory = (appConfig: AppConfigService) => ({
 });
 
 @NgModule({
+    declarations: [
+        LoginSuccessComponent
+    ],
   providers: [
     AuthGuard,
     RoleGuard,
diff --git a/src/app/auth/auth.service.ts b/src/app/auth/auth.service.ts
index 6fd5f6febafa62fc7d3843a3e9d22629b066fa79..ad7c6b8fcfa0166568751f3f9e1e3b4aa1a11938 100644
--- a/src/app/auth/auth.service.ts
+++ b/src/app/auth/auth.service.ts
@@ -34,8 +34,8 @@ export class AuthService {
                 private appConfig: AppConfigService,
                 private jwtHelper: JwtHelperService) {
     }
-
-    private storeToken(token: string): void {
+    //TODO make this static again and serive this feature in other way
+    public storeToken(token: string): void {
         localStorage.setItem(this.appConfig.config.tokenName, token);
     }
 
diff --git a/src/app/auth/login-success/login-success.component.css b/src/app/auth/login-success/login-success.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/auth/login-success/login-success.component.html b/src/app/auth/login-success/login-success.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..bf2b4b51596bcb734c40c6d46e1ec4917d9b6f71
--- /dev/null
+++ b/src/app/auth/login-success/login-success.component.html
@@ -0,0 +1 @@
+<p>login-success works!</p>
diff --git a/src/app/auth/login-success/login-success.component.spec.ts b/src/app/auth/login-success/login-success.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c2a446bbc2bc60e4ade6a4f4d3fa81c78bfdc21f
--- /dev/null
+++ b/src/app/auth/login-success/login-success.component.spec.ts
@@ -0,0 +1,36 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LoginSuccessComponent } from './login-success.component';
+import { RouterTestingModule } from '@angular/router/testing';
+import { ActivatedRoute } from '@angular/router';
+import { ActivatedRouteStub } from '../../shared/test-utils';
+import { AuthService } from '../auth.service';
+
+describe('LoginSuccessComponent', () => {
+  let component: LoginSuccessComponent;
+  let fixture: ComponentFixture<LoginSuccessComponent>;
+
+  const authUserSpy = jasmine.createSpyObj('AuthService', ['storeToken']);
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ LoginSuccessComponent ],
+      imports: [
+        RouterTestingModule
+      ],
+      providers: [
+        {provide: ActivatedRoute, useValue: new ActivatedRouteStub({token: '123'})},
+        {provide: AuthService, useValue: authUserSpy},
+      ]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(LoginSuccessComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/auth/login-success/login-success.component.ts b/src/app/auth/login-success/login-success.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..02d3386850147f1e758a80f4b435d973e5abb42f
--- /dev/null
+++ b/src/app/auth/login-success/login-success.component.ts
@@ -0,0 +1,28 @@
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute, Router} from '@angular/router';
+import {AuthService} from '../auth.service';
+
+@Component({
+    selector: 'app-login-success',
+    templateUrl: './login-success.component.html',
+    styleUrls: ['./login-success.component.css']
+})
+export class LoginSuccessComponent implements OnInit {
+    constructor(private readonly router: Router,
+                private readonly route: ActivatedRoute,
+                private readonly authService: AuthService) {
+    }
+
+
+    ngOnInit(): void {
+        this.route.queryParams.subscribe(params => {
+            const token = params['token'];
+            const refreshToken = params['refresh_token'];
+            if (token) {
+                this.authService.storeToken(token);
+            }
+            this.router.navigate(['/portal'])
+        })
+
+    }
+}
diff --git a/src/app/model/bulk-deployment.ts b/src/app/model/bulk-deployment.ts
index bf8828bb54fb0fa2dfdbfb0ad7cfc50f725979c9..1af669ecbe0bd3e05068993accf1dd17854d90e4 100644
--- a/src/app/model/bulk-deployment.ts
+++ b/src/app/model/bulk-deployment.ts
@@ -10,6 +10,8 @@ export class BulkDeployment {
     public type: BulkType;
     public details: Map<string, string>;
     public parallelDeploymentsLimit: number;
+    public deleted: boolean;
+    public completionDate: Date;
 }
 
 export enum BulkDeploymentState {
diff --git a/src/app/model/bulk-queue-details.ts b/src/app/model/bulk-queue-details.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a86da4af02b6c0151783ddbe7733b54db57d5877
--- /dev/null
+++ b/src/app/model/bulk-queue-details.ts
@@ -0,0 +1,8 @@
+export class BulkQueueDetails {
+
+    public jobInProcess: number;
+    public jobInProcessId: number;
+    public jobInQueue: number;
+    public jobDone: number;
+    public bulkJobInQueue: number;
+}
\ No newline at end of file
diff --git a/src/app/model/configuration.ts b/src/app/model/configuration.ts
index 3bffd6e8f90421fa78c8e722ece5d6de9b8aeb2d..5bdb54fdace5d822fef1526fbfe092aa13117288 100644
--- a/src/app/model/configuration.ts
+++ b/src/app/model/configuration.ts
@@ -11,4 +11,5 @@ export class Configuration {
     public appInstanceFailureEmailList: string[] = [];
     public bulkDeploymentJobCron: string;
     public parallelDeploymentsLimit: number;
+    public bulkDeploymentQueueRefresh: number;
 }
diff --git a/src/app/service/appconfig.service.ts b/src/app/service/appconfig.service.ts
index 46e77329d2aee5953b8563cf0114e2411917296e..e15d9b5c331c6cfdc8d7bf68ed9c24ec3d8bed3e 100644
--- a/src/app/service/appconfig.service.ts
+++ b/src/app/service/appconfig.service.ts
@@ -1,5 +1,5 @@
-import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
+import {Injectable} from '@angular/core';
+import {HttpClient} from '@angular/common/http';
 
 
 @Injectable({
@@ -10,7 +10,8 @@ export class AppConfigService {
 
     public jwtAllowedDomains: string[] = []
 
-    constructor(private http: HttpClient) { }
+    constructor(private http: HttpClient) {
+    }
 
     public load() {
         return new Promise<void>((resolve) => {
@@ -23,39 +24,43 @@ export class AppConfigService {
         });
     }
 
+    public getOidcUrl(): string {
+        return this.config.apiUrl + '/oauth2/authorization/my-oidc';
+    }
+
     public getApiUrl(): string {
-      if (this.config == null) {
-        return 'http://localhost/api';
-      }
-      return this.config.apiUrl;
+        if (this.config == null) {
+            return 'http://localhost/api';
+        }
+        return this.config.apiUrl;
     }
 
     public getNmaasGlobalDomainId(): number {
-      if (this.config == null) {
-         return 0;
-      }
-      return this.config.nmaas.globalDomainId || 0;
+        if (this.config == null) {
+            return 0;
+        }
+        return this.config.nmaas.globalDomainId || 0;
     }
 
     public getHttpTimeout(): number {
-      if (this.config == null) {
-         return 10000;
-      }
-      return this.config.http.timeout || 10000;
+        if (this.config == null) {
+            return 10000;
+        }
+        return this.config.http.timeout || 10000;
     }
 
     public getShowGitInfo(): boolean {
-      if (this.config == null) {
-          return false;
-      }
-      return this.config.showGitInfo || false;
+        if (this.config == null) {
+            return false;
+        }
+        return this.config.showGitInfo || false;
     }
 
     public getShowChangelog(): boolean {
-      if (this.config == null) {
-          return false;
-      }
-      return this.config.showChangelog || false;
+        if (this.config == null) {
+            return false;
+        }
+        return this.config.showChangelog || false;
     }
 
     public getSiteKey(): string {
@@ -70,6 +75,6 @@ export class AppConfigService {
     }
 
     public getLandingProfile(): string {
-      return this.config.landing || ''
+        return this.config.landing || ''
     }
 }
diff --git a/src/app/service/configuration.service.ts b/src/app/service/configuration.service.ts
index 6e03d6f911758fc5dbbe32e2c3a4a92b5789b17a..9d93b4018f6ead3cfc3eb71c3db60417323b71bd 100644
--- a/src/app/service/configuration.service.ts
+++ b/src/app/service/configuration.service.ts
@@ -14,7 +14,7 @@ export class ConfigurationService extends GenericDataService{
 
   constructor(http: HttpClient, appConfig: AppConfigService) {
     super(http, appConfig);
-    this.uri = this.appConfig.getApiUrl() + '/configuration/'
+    this.uri = this.appConfig.getApiUrl() + '/configuration'
   }
 
   public getConfiguration(): Observable<Configuration> {
@@ -22,7 +22,7 @@ export class ConfigurationService extends GenericDataService{
   }
 
   public updateConfiguration(configuration: Configuration): Observable<any>{
-    return this.put(this.uri + configuration.id, configuration);
+    return this.put(this.uri + "/"+ configuration.id, configuration);
   }
 
 }
diff --git a/src/app/service/domain.service.ts b/src/app/service/domain.service.ts
index dfff8ef6b175c94517fe78cdbb03feafe3f65202..7ed0257a4aca76390edd525a84274cb6667c150d 100644
--- a/src/app/service/domain.service.ts
+++ b/src/app/service/domain.service.ts
@@ -24,7 +24,7 @@ export class DomainService extends GenericDataService {
   constructor(http: HttpClient, appConfig: AppConfigService) {
     super(http, appConfig);
     this.updateRequiredFlag = false;
-    this.url = this.appConfig.getApiUrl() + '/domains/';
+    this.url = this.appConfig.getApiUrl() + '/domains';
   }
 
   public getGlobalDomainId(): number {
@@ -40,7 +40,7 @@ export class DomainService extends GenericDataService {
   }
 
   public getOne(domainId: number): Observable<Domain> {
-    return this.get<Domain>(this.url + domainId);
+    return this.get<Domain>(this.url + '/' + domainId);
   }
 
   public add(domain: Domain): Observable<Id> {
@@ -48,19 +48,19 @@ export class DomainService extends GenericDataService {
   }
 
   public update(domain: Domain): Observable<any> {
-    return this.put<Domain, Id>(this.url + domain.id, domain);
+    return this.put<Domain, Id>(this.url + '/' + domain.id, domain);
   }
 
   public updateTechDetails(domain: Domain): Observable<any> {
-    return this.patch<Domain, Id>(this.url + domain.id, domain)
+    return this.patch<Domain, Id>(this.url + '/' + domain.id, domain)
   }
 
   public updateDcnConfigured(domain: Domain): Observable<any> {
-    return this.patch<Domain, Id>(this.url + domain.id + '/dcn?configured=' + domain.domainDcnDetails.dcnConfigured, null);
+    return this.patch<Domain, Id>(this.url  + '/' + domain.id + '/dcn?configured=' + domain.domainDcnDetails.dcnConfigured, null);
   }
 
   public updateDomainState(domain: Domain): Observable<any> {
-    return this.patch<Domain, Id>(this.url + domain.id + '/state?active=' + !domain.active, null);
+    return this.patch<Domain, Id>(this.url + '/' + domain.id + '/state?active=' + !domain.active, null);
   }
 
   public remove(domainId: number, softRemove?: boolean): Observable<any> {
@@ -68,15 +68,15 @@ export class DomainService extends GenericDataService {
     if (softRemove !== undefined) {
       params = params.append("softRemove", softRemove.toString())
     }
-    return this.http.delete(this.url + domainId, {params})
+    return this.http.delete(this.url + '/' + domainId, {params})
   }
 
   public getMyDomains(): Observable<Domain[]> {
-    return this.get<Domain[]>(this.url + 'my');
+    return this.get<Domain[]>(this.url + '/my');
   }
 
   public getUsers(domainId: number): Observable<User[]> {
-    return this.get<User[]>(this.url + 'users');
+    return this.get<User[]>(this.url + '/users');
   }
 
   public setUpdateRequiredFlag(flag: boolean) {
@@ -89,50 +89,50 @@ export class DomainService extends GenericDataService {
 
   // GROUPS
   public getAllDomainGroups(): Observable<DomainGroup[]> {
-    return this.get<DomainGroup[]>(this.url + 'group');
+    return this.get<DomainGroup[]>(this.url + '/group');
   }
 
   public getDomainGroup(domainGroupId: number): Observable<DomainGroup> {
-    return this.get<DomainGroup>(this.url + 'group/' + domainGroupId);
+    return this.get<DomainGroup>(this.url + '/group/' + domainGroupId);
   }
 
   public deleteDomainGroup(domainGroupId: number): Observable<void> {
-    return this.delete<void>(this.url + 'group/' + domainGroupId);
+    return this.delete<void>(this.url + '/group/' + domainGroupId);
   }
 
   public addDomainsToGroup(groupCodeName: string, domainIds: number[]): Observable<DomainGroup> {
-    return this.post(this.url + 'group/' + groupCodeName, domainIds);
+    return this.post(this.url + '/group/' + groupCodeName, domainIds);
   }
 
   public deleteDomainFromGroup(groupId: number, domainId: number): Observable<DomainGroup> {
-    return this.patch(this.url + 'group/' + groupId, domainId);
+    return this.patch(this.url + '/group/' + groupId, domainId);
   }
 
   public createDomainGroup(domainGroup: DomainGroup): Observable<Id> {
-    return this.post(this.url + 'group', domainGroup);
+    return this.post(this.url + '/group', domainGroup);
   }
 
   public updateDomainGroup(domainGroup: DomainGroup, id: number): Observable<Id> {
-    return this.put(this.url + 'group/' + id, domainGroup);
+    return this.put(this.url + '/group/' + id, domainGroup);
   }
 
   public updateDomainGroupManagers(managers: User[], id: number): Observable<DomainGroup> {
-    return this.put(this.url + 'group/members/' + id, managers);
+    return this.put(this.url + '/group/members/' + id, managers);
   }
 
   public getAnnotations(): Observable<DomainAnnotation[]> {
-    return this.get<DomainAnnotation[]>(this.url + 'annotations')
+    return this.get<DomainAnnotation[]>(this.url + '/annotations')
   }
 
   public addAnnotations(annotation: KeyValue): Observable<void> {
-    return this.post(this.url + 'annotations', annotation)
+    return this.post(this.url + '/annotations', annotation)
   }
 
-  public deleteAnnotation(id: number) : Observable<void>{
-    return this.delete(`${this.url}annotations/${id}`)
+  public deleteAnnotation(id: number) : Observable<void> {
+    return this.delete(`${this.url}/annotations/${id}`)
   }
 
   public updateAnnotation(annotation: DomainAnnotation): Observable<void> {
-    return this.put(`${this.url}annotations/${annotation.id}`, annotation)
+    return this.put(`${this.url}/annotations/${annotation.id}`, annotation)
   }
 }
diff --git a/src/app/service/sshkey.service.ts b/src/app/service/sshkey.service.ts
index f6b47b7245f782a9190f9bae5b6d1347cd398bdf..32424f472417e56ad29d71c83ff42cb5959f862b 100644
--- a/src/app/service/sshkey.service.ts
+++ b/src/app/service/sshkey.service.ts
@@ -26,4 +26,17 @@ export class SSHKeyService extends GenericDataService {
   public invalidate(id: number): Observable<any> {
     return this.delete(this.appConfig.getApiUrl() + '/user/keys/' + id);
   }
+
+  public getAllByUserId(userId: number): Observable<SSHKeyView[]> {
+    return this.get<SSHKeyView[]>(this.appConfig.getApiUrl() + '/user/keys/view/' + userId);
+  }
+
+  public createKeyForUser(request: SSHKeyRequest, userId: number ): Observable<any> {
+    return this.put<SSHKeyRequest, any>(this.appConfig.getApiUrl() + '/user/keys/view/' + userId, request);
+  }
+
+  public invalidateUserKey(keyId: number, userId: number): Observable<any> {
+    return this.delete(this.appConfig.getApiUrl() + '/user/keys/view/' + userId + "/" + keyId);
+  }
+
 }
diff --git a/src/app/service/user.service.ts b/src/app/service/user.service.ts
index 66db21d2b48f72e4a20521a5d2242480f955cc58..e139180f752173a84594c97211e16e8ddb17ae96 100644
--- a/src/app/service/user.service.ts
+++ b/src/app/service/user.service.ts
@@ -20,7 +20,7 @@ export class UserService extends GenericDataService {
 
     public getAll(domainId?: number): Observable<User[]> {
         return this.get<User[]>(domainId === undefined || domainId === this.domainService.getGlobalDomainId() ?
-            this.getUsersUrl() : this.getDomainUsersUrl(domainId));
+            this.getUsersUrlWithoutDash() : this.getDomainUsersUrl(domainId));
     }
 
     public getOne(userId: number, domainId?: number): Observable<User> {
@@ -32,7 +32,7 @@ export class UserService extends GenericDataService {
     }
 
     public getRoles(userId: number, domainId?: number): Observable<UserRole[]> {
-        return this.get<UserRole[]>((domainId === undefined ? this.getUsersUrl() : this.getDomainUsersUrl(domainId)) + userId + '/roles');
+        return this.get<UserRole[]>((domainId === undefined ? this.getUsersUrl() : this.getDomainUsersUrl(domainId))  + userId + '/roles');
     }
 
     public updateUser(userId: number, user: User): Observable<any> {
@@ -87,6 +87,11 @@ export class UserService extends GenericDataService {
         return this.appConfig.getApiUrl() + '/users/';
     }
 
+    protected getUsersUrlWithoutDash(): string {
+        return this.appConfig.getApiUrl() + '/users';
+    }
+
+
     protected getDomainUsersUrl(domainId: number): string {
         return this.appConfig.getApiUrl() + '/domains/' + domainId + '/users/';
     }
diff --git a/src/app/shared/about/about.component.css b/src/app/shared/about/about.component.css
index cbf25d83e53161e2bfe9524f48abbe82c72e31e3..4a9f3de4150444470b0d301c1752aa16ef708229 100644
--- a/src/app/shared/about/about.component.css
+++ b/src/app/shared/about/about.component.css
@@ -16,3 +16,11 @@
     padding-left: 15px;
     padding-right:15px;
 }
+.position{
+    display: flex;
+}
+@media (max-width: 991px){
+    .position{
+        flex-direction: column-reverse;
+    }
+}
diff --git a/src/app/shared/about/about.component.html b/src/app/shared/about/about.component.html
index 624cbd8f01ae0b577f99c2acbb0643eb82124ec8..df6d0eb479e590e7436abc90906638ecbe4fb3d0 100644
--- a/src/app/shared/about/about.component.html
+++ b/src/app/shared/about/about.component.html
@@ -1,4 +1,4 @@
-<div class="col-md-offset-1 col-md-10 col-lg-offset-1 col-lg-10 row" style="padding-bottom: 80px; padding-top: 80px;">
+<div class="col-md-offset-1 col-md-10 col-lg-offset-1 col-lg-10 row position" style="padding-bottom: 80px; padding-top: 80px;">
     <div class="col-md-6">
         <div class="" style="padding-bottom: 15px;">
             <h2>{{ 'ABOUT.CHANGELOG_TITLE' | translate }}</h2>
@@ -41,16 +41,16 @@
     <div class="col-md-6">
         <div class="" style="padding-bottom: 15px;">
             <h2>{{ 'ABOUT.CONTACT_TITLE' | translate }}</h2>
-            <span>{{ 'ABOUT.CONTACT_DESC' | translate}}</span>
-            <p>Join the mailing list: </p>
+            <p>Join the mailing list of your interest: </p>
             <ul>
                 <li>
-                    <p><a href="https://lists.geant.org/sympa/info/nmaas-announce">low frequency nmaas news</a> - Mailing list for nmaas-related announcements sent out by the nmaas Team members</p>
+                    <p><a href="https://lists.geant.org/sympa/info/nmaas-announce">nmaas-announce</a> - for nmaas-related announcements sent out by the nmaas Team members,</p>
                 </li>
                 <li>
-                    <p><a href="https://lists.geant.org/sympa/info/nmaas-users ">users discussion about nmaas</a> -  Mailing list for message exchange between nmaas users and the nmaas Team</p>
+                    <p><a href="https://lists.geant.org/sympa/info/nmaas-users">nmaas-users</a> - for discussions and message exchange between nmaas users and the nmaas Team.</p>
                 </li>
             </ul>
+            <span>{{ 'ABOUT.CONTACT_DESC' | translate}}</span>
         </div>
         <div class="panel panel-default">
             <div class="panel-body">
diff --git a/src/app/shared/page-not-found/page-not-found.component.css b/src/app/shared/page-not-found/page-not-found.component.css
index 81255a0b4ffd0b6f3f6e72de771581796a4648da..d1bc030c6435a8816481bec18f3bc499207c5439 100644
--- a/src/app/shared/page-not-found/page-not-found.component.css
+++ b/src/app/shared/page-not-found/page-not-found.component.css
@@ -1,5 +1,5 @@
 .container-fluid {
-    min-height: 100vh;
+    min-height: 55vh;
     padding: 25px;
     background-repeat: no-repeat;
     background-color: rgb(255, 255, 255);
diff --git a/src/app/shared/page-not-found/page-not-found.component.html b/src/app/shared/page-not-found/page-not-found.component.html
index 64b11d2695c7b7e0c9db9c59d82fe8b5b026bc11..48dfe9e1d3a6916e20f9c7da4f431064c0012576 100644
--- a/src/app/shared/page-not-found/page-not-found.component.html
+++ b/src/app/shared/page-not-found/page-not-found.component.html
@@ -3,7 +3,7 @@
     <img src="assets/images/error/404.gif" width="60%">
   </div>
   <div class="row">
-    <h1>Oops! Something went wrong.</h1>
+    <h1>Oops! Something went wrong (404).</h1>
     <p>Our robot couldn't find this page. Try a different link or head back to the homepage.</p>
     <button class="btn btn-primary" type="button" (click)="redirect()">Go back</button>
   </div>
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 038dac09fc2107920049cc71f42f0e12aad504b6..b1f373c8a0f49f624fa8e4628df4e5888f290e8c 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -60,6 +60,7 @@ import {SortableHeaderDirective} from '../service/sort-domain.directive';
 import {InputTextModule} from 'primeng/inputtext';
 import { DomainNamespaceAnnotationsComponent } from './domain-namespace-annotations/domain-namespace-annotations.component';
 import { provideZxvbnServiceForPSM  } from 'angular-password-strength-meter/zxcvbn';
+import { AccessTokensComponent } from './users/access-token/access-tokens.component';
 import { LeftMenuComponent } from './left-menu/left-menu.component';
 import {TableModule} from 'primeng/table';
 
@@ -127,6 +128,7 @@ import {TableModule} from 'primeng/table';
         PreferencesComponent,
         SortableHeaderDirective,
         DomainNamespaceAnnotationsComponent,
+        AccessTokensComponent
     ],
     providers: [
         PasswordValidator,
@@ -177,7 +179,8 @@ import {TableModule} from 'primeng/table';
         ModalProvideSshKeyComponent,
         PreferencesComponent,
         SortableHeaderDirective,
-        DomainNamespaceAnnotationsComponent
+        DomainNamespaceAnnotationsComponent,
+        AccessTokensComponent
     ]
 })
 export class SharedModule {
diff --git a/src/app/shared/test-utils.ts b/src/app/shared/test-utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..41f9b1914dbfc1d24dc56337bce64bd10d1c40a6
--- /dev/null
+++ b/src/app/shared/test-utils.ts
@@ -0,0 +1,31 @@
+import { convertToParamMap, ParamMap, Params } from "@angular/router";
+import { Observable, ReplaySubject } from "rxjs";
+
+export class ActivatedRouteStub {
+    // Use a ReplaySubject to share previous values with subscribers
+    // and pump new values into the `paramMap` observable
+    private readonly subject = new ReplaySubject<ParamMap>();
+    private readonly subjectQuery = new ReplaySubject<ParamMap>();
+    snapshot = {};
+  
+    constructor(initialParams?: Params, initialQueryParams?: Params) {
+      this.setParamMap(initialParams);
+    }
+  
+    /** The mock paramMap observable */
+    readonly paramMap = this.subject.asObservable();
+    readonly queryParamMap = this.subjectQuery.asObservable();
+  
+    /** Set the paramMap observables's next value */
+    setParamMap(params?: Params) {
+      this.subject.next(convertToParamMap(params));
+    }
+  
+    setQueryParamMap(params?: Params) {
+      this.subjectQuery.next(convertToParamMap(params));
+    }
+
+    get queryParams() : Observable<ParamMap> {
+        return this.subject.asObservable();
+    }
+  }
\ No newline at end of file
diff --git a/src/app/shared/users/access-token/access-token.ts b/src/app/shared/users/access-token/access-token.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7e0eb1e41bbaf717eedf8e5b4d1982b298f960b3
--- /dev/null
+++ b/src/app/shared/users/access-token/access-token.ts
@@ -0,0 +1,7 @@
+export class AccessToken {
+    public id: number
+    public name: string
+    public userId: number
+    public tokenValue: string
+    public valid: boolean
+}
\ No newline at end of file
diff --git a/src/app/shared/users/access-token/access-tokens.component.html b/src/app/shared/users/access-token/access-tokens.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..e58fa61efbc62b07e6e9692877deb12fc3288b4c
--- /dev/null
+++ b/src/app/shared/users/access-token/access-tokens.component.html
@@ -0,0 +1,66 @@
+<div style="margin-bottom: 15px;" class="panel panel-default">
+    <div class="panel-heading">{{'TOKENS.HEADER' | translate}}</div>
+    <div class="panel-body">
+        <table class="table table-hover" aria-describedby="User access tokens table">
+            <thead>
+            <tr>
+                <th scope="col">{{'TOKENS.TABLE.ID' | translate}}</th>
+                <th scope="col">{{'TOKENS.TABLE.NAME' | translate}}</th>
+                <th scope="col">{{'TOKENS.TABLE.VALUE' | translate}}</th>
+                <th scope="col">{{'TOKENS.TABLE.VALID' | translate}}</th>
+                <th scope="col">{{'TOKENS.TABLE.ACTIONS' | translate}}</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr *ngFor="let token of tokensList">
+                <td>{{token.id}}</td>
+                <td>{{token.name}}</td>
+                <td>{{token.tokenValue}}</td>
+                <td>{{token.valid}}</td>
+                <td *ngIf="token.valid">
+                    <button type="button" class="btn btn-danger"
+                            (click)="invalidate(token.id)">{{'TOKENS.BUTTON_INVALIDATE' | translate}}</button>
+                </td>
+                <td *ngIf="!token.valid">
+                    <button type="button" class="btn btn-danger"
+                            (click)="deleteToken(token.id)">{{'TOKENS.BUTTON_DELETE' | translate}}</button>
+                </td>
+            </tr>
+            <tr *ngIf="tokensList.length === 0">
+                <td colspan="3" style="text-align: center">{{'TOKENS.NO_TOKENS' | translate}}</td>
+            </tr>
+            </tbody>
+        </table>
+        <div>
+            <button type="button" class="btn btn-success"
+                    (click)="modal.show()">{{'TOKENS.NEW_TOKEN' | translate}}</button>
+
+        </div>
+    </div>
+</div>
+
+<nmaas-modal styleModal="info">
+    <div class="nmaas-modal-header">{{'TOKENS.MODAL.HEADER' | translate}}</div>
+    <div class="nmaas-modal-body" style="height: 60%; max-height: 80vh;overflow-y: auto;">
+        <form [formGroup]="requestForm" (ngSubmit)="createNewToken()">
+            <div class="form-group">
+                <label class="control-label" for="new-token-name">
+                    {{'TOKENS.MODAL.NAME' | translate}}:
+                </label>
+                <input id="new-token-name" type="text" class="form-control" formControlName="name">
+            </div>
+            <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger">
+                <div *ngIf="name.errors.required">{{'SSH_KEYS.MODAL.ERROR.NAME_REQUIRED' | translate}}</div>
+                <div *ngIf="name.errors.minlength">{{'SSH_KEYS.MODAL.ERROR.NAME_MINLENGTH' | translate}}</div>
+                <div *ngIf="name.errors.maxlength">{{'SSH_KEYS.MODAL.ERROR.NAME_MAXLENGTH' | translate}}</div>
+                <div *ngIf="name.errors.notUnique">{{name.errors.message}}</div>
+
+            </div>
+            <input type="submit" class="btn btn-success" value="{{'SSH_KEYS.MODAL.BUTTON_ADD' | translate}}"
+                   [disabled]="!requestForm.valid">
+            <button type="button" class="btn btn-primary pull-right"
+                    (click)="modal.hide()">{{'SSH_KEYS.MODAL.BUTTON_CANCEL' | translate}}</button>
+
+        </form>
+    </div>
+</nmaas-modal>
\ No newline at end of file
diff --git a/src/app/shared/users/access-token/access-tokens.component.spec.ts b/src/app/shared/users/access-token/access-tokens.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..98e26efb7ba9c778fb53e550ba27eec87ff1677f
--- /dev/null
+++ b/src/app/shared/users/access-token/access-tokens.component.spec.ts
@@ -0,0 +1,38 @@
+import {ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {AccessTokensComponent} from './access-tokens.component';
+import {HttpClientTestingModule} from '@angular/common/http/testing';
+import {TranslateFakeLoader, TranslateLoader, TranslateModule} from '@ngx-translate/core';
+import {ReactiveFormsModule} from '@angular/forms';
+import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
+
+describe('AccessTokensComponent', () => {
+    let component: AccessTokensComponent;
+    let fixture: ComponentFixture<AccessTokensComponent>;
+
+    beforeEach(async () => {
+        await TestBed.configureTestingModule({
+            declarations: [AccessTokensComponent],
+            imports: [
+                HttpClientTestingModule,
+                ReactiveFormsModule,
+                TranslateModule.forRoot({
+                    loader: {
+                        provide: TranslateLoader,
+                        useClass: TranslateFakeLoader
+                    }
+                }),
+            ],
+            schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
+        })
+            .compileComponents();
+
+        fixture = TestBed.createComponent(AccessTokensComponent);
+        component = fixture.componentInstance;
+        fixture.detectChanges();
+    });
+
+    it('should create', () => {
+        expect(component).toBeTruthy();
+    });
+});
\ No newline at end of file
diff --git a/src/app/shared/users/access-token/access-tokens.component.ts b/src/app/shared/users/access-token/access-tokens.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c901eb760d28787fd0d3209eaf474a858ec8f588
--- /dev/null
+++ b/src/app/shared/users/access-token/access-tokens.component.ts
@@ -0,0 +1,79 @@
+
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {Observable} from 'rxjs';
+import {AccessToken} from './access-token';
+import {AccessTokenService} from './access-tokens.service';
+import {ModalComponent} from '../../modal';
+import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
+
+@Component({
+    selector: 'app-access-tokens',
+    templateUrl: './access-tokens.component.html',
+    styleUrls: []
+})
+export class AccessTokensComponent implements OnInit {
+
+    public tokens: Observable<AccessToken[]> = undefined;
+    public tokensList: AccessToken[] = [];
+
+    public requestForm: UntypedFormGroup = undefined;
+
+    public newTokenName = '';
+
+    @ViewChild(ModalComponent, {static: true})
+    public readonly modal: ModalComponent;
+
+    constructor(private tokenService: AccessTokenService,
+                private formBuilder: UntypedFormBuilder) {
+    }
+
+    ngOnInit() {
+        this.requestForm = this.formBuilder.group({
+            name: ['', [Validators.required, Validators.minLength(1), Validators.maxLength(16)]],
+        })
+
+        this.tokens = this.tokenService.getAll();
+        this.getData();
+    }
+
+    getData() {
+        this.tokensList = [];
+        this.tokens.subscribe(
+            data => this.tokensList.push(...data),
+            error => console.error(error)
+        )
+    }
+
+    invalidate(id: number) {
+        this.tokenService.invalidate(id).subscribe(
+            (_) => this.getData(),
+            error => console.error(error)
+        );
+    }
+
+    deleteToken(id: number) {
+        this.tokenService.deleteToken(id).subscribe(
+            (_) => this.getData(),
+            error => console.error(error.err)
+        );
+    }
+
+    public createNewToken() {
+        this.tokenService.createToken(this.requestForm.value.name.trim()).subscribe({
+            next: val => {
+                this.tokensList.push(val)
+                this.requestForm.reset();
+                this.modal.hide();
+            },
+            error: err => {
+                console.warn(err.error)
+                this.requestForm.controls['name'].setErrors({notUnique: true, message: err.error}); 
+                console.log(this.requestForm)
+            }
+        })
+    }
+
+    get name() {
+        return this.requestForm.get('name');
+    }
+}
\ No newline at end of file
diff --git a/src/app/shared/users/access-token/access-tokens.service.ts b/src/app/shared/users/access-token/access-tokens.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e3c8dec74292a256c24e33a3bade736e7928ec5b
--- /dev/null
+++ b/src/app/shared/users/access-token/access-tokens.service.ts
@@ -0,0 +1,36 @@
+import {Observable} from 'rxjs';
+import {AccessToken} from './access-token';
+import {Injectable} from '@angular/core';
+import {GenericDataService} from '../../../service/genericdata.service';
+import {HttpClient} from '@angular/common/http';
+import {AppConfigService} from '../../../service';
+
+@Injectable({
+    providedIn: 'root'
+})
+export class AccessTokenService extends GenericDataService {
+
+    constructor(http: HttpClient, appConfig: AppConfigService) {
+        super(http, appConfig);
+    }
+
+    public getAll(): Observable<AccessToken[]> {
+        return this.http.get<AccessToken[]>(this.getUrl())
+    }
+
+    public invalidate(id: number): Observable<void> {
+        return this.http.put<void>(`${this.getUrl()}/${id}`, '')
+    }
+
+    public deleteToken(id: number): Observable<void> {
+        return this.http.put<void>(`${this.getUrl()}/delete/${id}`, '')
+    }
+
+    public createToken(tokenName: string): Observable<AccessToken> {
+        return this.http.post<AccessToken>(this.getUrl(), tokenName)
+    }
+
+    private getUrl(): string {
+        return this.appConfig.getApiUrl() + '/tokens';
+    }
+}
\ No newline at end of file
diff --git a/src/app/shared/users/new-ssh-key/new-ssh-key.component.ts b/src/app/shared/users/new-ssh-key/new-ssh-key.component.ts
index 619104369b0f33a17d8f96fb4aaa925f0d1a573a..191b25ae717054a9c62fa618cadd1568f2fb31db 100644
--- a/src/app/shared/users/new-ssh-key/new-ssh-key.component.ts
+++ b/src/app/shared/users/new-ssh-key/new-ssh-key.component.ts
@@ -1,4 +1,4 @@
-import {Component, EventEmitter, OnInit, Output, ViewChild} from '@angular/core';
+import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
 import {SSHKeyService} from '../../../service/sshkey.service';
 import {SSHKeyRequest} from '../../../model/sshkey-request';
 import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
@@ -17,6 +17,12 @@ export class NewSshKeyComponent implements OnInit {
   @Output()
   public out: EventEmitter<any> = new EventEmitter<any>();
 
+  @Input()
+  public userMode = false;
+  
+  @Input()
+  public userId : number;
+
   public error: string = undefined;
 
   public requestForm: UntypedFormGroup = undefined;
@@ -38,17 +44,34 @@ export class NewSshKeyComponent implements OnInit {
     console.log(this.requestForm);
     request.name = this.requestForm.value.name.trim();
     request.key = this.requestForm.value.key.trim();
+    if(this.userMode) {
+      if(this.userId !== null) {
+        this.keyService.createKeyForUser(request, this.userId).subscribe(
+          data => {
+            this.error = undefined;
+            this.requestForm.reset();
+            this.modal.hide();
+            this.out.emit();
+          },
+          error => {
+            this.error = error.message;
+          }
+      );
+      }
+  } else { // profile view
     this.keyService.createKey(request).subscribe(
-        data => {
-          this.error = undefined;
-          this.requestForm.reset();
-          this.modal.hide();
-          this.out.emit();
-        },
-        error => {
-          this.error = error.message;
-        }
-    );
+      data => {
+        this.error = undefined;
+        this.requestForm.reset();
+        this.modal.hide();
+        this.out.emit();
+      },
+      error => {
+        this.error = error.message;
+      }
+  );
+  }
+    
   }
 
   get name() {
diff --git a/src/app/shared/users/ssh-keys/ssh-keys.component.html b/src/app/shared/users/ssh-keys/ssh-keys.component.html
index 2e8af662c2f5fde4d5d4b93737b90f7831a079e3..e9025bddb5cd7796a569b04f68bb8cd26b94c772 100644
--- a/src/app/shared/users/ssh-keys/ssh-keys.component.html
+++ b/src/app/shared/users/ssh-keys/ssh-keys.component.html
@@ -1,11 +1,8 @@
-<div style="padding-bottom: 15px;" class="background-section">
-    <div style="display: flex; justify-content:space-between">
-    <h4 style="font-size:15px; font-weight: bold" >{{'SSH_KEYS.HEADER' | translate}}</h4>
-        <app-new-ssh-key (out)="getData()"></app-new-ssh-key>
-    </div>
+<div style="margin-bottom: 15px;" class="panel panel-default">
+    <div class="panel-heading">{{'SSH_KEYS.HEADER' | translate}}</div>
     <div class="panel-body">
         <div class="flex justify-content-end mb-4">
-
+            <app-new-ssh-key [userMode]="userMode" [userId]="userId" (out)="getData()"></app-new-ssh-key>
         </div>
         <table class="table table-hover" aria-describedby="User ssh keys table">
             <thead>
diff --git a/src/app/shared/users/ssh-keys/ssh-keys.component.ts b/src/app/shared/users/ssh-keys/ssh-keys.component.ts
index 8bee8e6e677c36590e4fcd6a4b9a71725f0ec2c9..7def6034efd3074b784ac160800ff63b92dc70c5 100644
--- a/src/app/shared/users/ssh-keys/ssh-keys.component.ts
+++ b/src/app/shared/users/ssh-keys/ssh-keys.component.ts
@@ -1,4 +1,4 @@
-import {Component, OnInit} from '@angular/core';
+import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';
 import {SSHKeyService} from '../../../service/sshkey.service';
 import {Observable} from 'rxjs';
 import {SSHKeyView} from '../../../model/sshkey-view';
@@ -8,16 +8,37 @@ import {SSHKeyView} from '../../../model/sshkey-view';
   templateUrl: './ssh-keys.component.html',
   styleUrls: ['./ssh-keys.component.css']
 })
-export class SshKeysComponent implements OnInit {
+export class SshKeysComponent implements OnInit, OnChanges {
 
   public keys: Observable<SSHKeyView[]> = undefined;
   public keysList: SSHKeyView[] = [];
 
+  @Input()
+  public userMode = false;
+
+  @Input()
+  public userId : number;
+
   constructor(private keyService: SSHKeyService) { }
 
   ngOnInit() {
-    this.keys = this.keyService.getAll();
-    this.getData();
+    if(this.userMode) {
+        if(this.userId !== null) {
+            this.keys = this.keyService.getAllByUserId(this.userId);
+            this.getData();
+        }
+    } else { // profile view
+        this.keys = this.keyService.getAll();
+        this.getData();
+    }
+   
+  }
+
+  ngOnChanges(changes: SimpleChanges) {
+    if (changes['userId']) {
+        this.ngOnInit();
+      console.log('Nowa wartość userId:', this.userId);
+    }
   }
 
   getData() {
@@ -33,15 +54,28 @@ export class SshKeysComponent implements OnInit {
   }
 
   invalidate(id: number) {
-      this.keyService.invalidate(id).subscribe(
-          data => {
-              console.log('invalidating ssh key id: ' + id + ' success');
-              this.getData();
-          },
-          error => {
-              console.error(error);
-          }
-      );
+    if(this.userMode) {
+        this.keyService.invalidateUserKey(id, this.userId).subscribe(
+            data => {
+                console.log('invalidating ssh key id: ' + id + ' success');
+                this.getData();
+            },
+            error => {
+                console.error(error);
+            }
+        );
+    } else {
+        this.keyService.invalidate(id).subscribe(
+            data => {
+                console.log('invalidating ssh key id: ' + id + ' success');
+                this.getData();
+            },
+            error => {
+                console.error(error);
+            }
+        );
+    }
+      
   }
 
 }
diff --git a/src/app/welcome/login/login.component.html b/src/app/welcome/login/login.component.html
index 27418cc9a946d4901ca623c444d8dde34dfc66ca..7fd223061e3430e40066581208df5f152c1d463a 100644
--- a/src/app/welcome/login/login.component.html
+++ b/src/app/welcome/login/login.component.html
@@ -26,8 +26,7 @@
     </fieldset>
 </form>
 <div class="form-group">
-    <button type="submit" (click)="triggerSSO()" class="btn btn-primary btn-block"
-            [disabled]="!this.configuration?.ssoLoginAllowed || loading || ssoLoading">
+    <button type="submit" (click)="triggerOIDC()" class="btn btn-primary btn-block">
         {{ 'LOGIN.LOGIN_WITH' | translate }}
     </button>
     <img alt="sso" *ngIf="ssoLoading" src="data:"/>
diff --git a/src/app/welcome/login/login.component.spec.ts b/src/app/welcome/login/login.component.spec.ts
index 0fd649ba25d4732652f9919c17045d22051cf1e4..35e39bc620879877c64f1d11636786124b0439f8 100644
--- a/src/app/welcome/login/login.component.spec.ts
+++ b/src/app/welcome/login/login.component.spec.ts
@@ -10,6 +10,7 @@ import {ConfigurationService, UserService} from '../../service';
 import {SSOService} from '../../service/sso.service';
 import createSpyObj = jasmine.createSpyObj;
 import {of} from 'rxjs';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
 
 
 describe('Component: Login', () => {
@@ -28,6 +29,7 @@ describe('Component: Login', () => {
                 FormsModule,
                 ReactiveFormsModule,
                 RouterTestingModule,
+                HttpClientTestingModule,
                 TranslateModule.forRoot({
                     loader: {
                         provide: TranslateLoader,
diff --git a/src/app/welcome/login/login.component.ts b/src/app/welcome/login/login.component.ts
index f82e1de1e556d50bb80c48f8d1d624abdf883b80..dbfcc78194a47a0585edbfd2d35d4b8ee52d32ff 100644
--- a/src/app/welcome/login/login.component.ts
+++ b/src/app/welcome/login/login.component.ts
@@ -2,7 +2,7 @@ import {Component, OnInit, ViewChild, ViewEncapsulation} from '@angular/core';
 
 import {Router} from '@angular/router';
 import {AuthService} from '../../auth/auth.service';
-import {ConfigurationService, UserService} from '../../service';
+import {AppConfigService, ConfigurationService, UserService} from '../../service';
 import {Configuration} from '../../model/configuration';
 import {SSOService} from '../../service/sso.service';
 import {SSOConfig} from '../../model/sso';
@@ -37,7 +37,8 @@ export class LoginComponent implements OnInit {
                 private ssoService: SSOService,
                 private fb: UntypedFormBuilder,
                 private userService: UserService,
-                private translate: TranslateService) {
+                private translate: TranslateService,
+                private appConfig: AppConfigService) {
         this.resetPasswordForm = fb.group({
             email: ['', [Validators.required, Validators.email]]
         });
@@ -71,6 +72,9 @@ export class LoginComponent implements OnInit {
         );
     }
 
+    public triggerOIDC() {
+        window.location.href = this.appConfig.getOidcUrl();
+    }
 
     public checkSSO() {
         const params = this.router.parseUrl(this.router.url).queryParams;
diff --git a/src/app/welcome/profile/profile.component.html b/src/app/welcome/profile/profile.component.html
index 2a2623b44e76bee141239b93330e39675dca2978..a62e21156ef7784524d5b4106c17a1671874a87f 100644
--- a/src/app/welcome/profile/profile.component.html
+++ b/src/app/welcome/profile/profile.component.html
@@ -34,5 +34,6 @@
                               [allowedModes]="[ComponentMode.PROFILVIEW, ComponentMode.EDIT]">
         </nmaas-userprivileges>
         <nmaas-ssh-keys></nmaas-ssh-keys>
+        <app-access-tokens></app-access-tokens>
     </div>
 </div>