diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ca9b96403403231ff452d8fd94b9fe9207c104be..525ea473ea9619994d2809f548bcee4767e6ff8f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,6 +2,7 @@ stages:
   - test
   - sonar
   - build
+  - mend
 
 test:
   stage: test
@@ -64,4 +65,23 @@ build_and_push_release_image:
       docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD $DOCKER_REPOSITORY
       docker build -t $DOCKER_REPOSITORY_LOCAL:$IMAGE_TAG .
       docker push $DOCKER_REPOSITORY_LOCAL:$IMAGE_TAG
-      docker logout $DOCKER_REPOSITORY
\ No newline at end of file
+      docker logout $DOCKER_REPOSITORY
+
+mend:
+  stage: mend
+  image: openjdk:17-jdk-slim
+  only:
+    - /^release/
+  variables:
+    PRODUCT_NAME: "nmaas"
+    PROJECT_NAME: "nmaas-portal"
+  script:
+    - |
+      export PRODUCT_VERSION=$(echo $CI_COMMIT_BRANCH | cut -c 9-)
+      export PROJECT_VERSION=$PRODUCT_VERSION
+      apt-get update && apt-get install -y curl nodejs npm
+      npm install -g @angular/cli
+      npm ci
+      chmod +x ./gradlew
+      curl -LJO https://github.com/whitesource/unified-agent-distribution/releases/latest/download/wss-unified-agent.jar
+      java -jar wss-unified-agent.jar -userKey ${MEND_USER_KEY} -apiKey ${MEND_API_KEY} -projectVersion ${PROJECT_VERSION} -project ${PROJECT_NAME} -productVersion ${PRODUCT_VERSION} -product ${PRODUCT_NAME} -c ./ws/ws.config -d ./
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index a443e5382e46befdc5870955a7650591f7e79e96..508d65aa095ac10dfd5fe282e30b242f8b5820a8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ plugins {
 	id "org.sonarqube" version "3.2.0"
 }
 
-version = '1.7.0-SNAPSHOT'
+version = '1.7.0'
 
 task buildGUI(type: Exec) {
 	println 'Building using Angular CLI'
diff --git a/package-lock.json b/package-lock.json
index 881b777c79885b41a9fc397b3d9c20efa1751599..2a4d17934a1608ed75f4f025a032daf43a966821 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "nmaas-portal",
-  "version": "1.7.0",
+  "version": "1.7.1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "nmaas-portal",
-      "version": "1.7.0",
+      "version": "1.7.1",
       "license": "Apache 2.0",
       "dependencies": {
         "@angular/animations": "17.3.12",
diff --git a/package.json b/package.json
index 9402af9537167709179f216f116de9a9ef4cbefa..8f55d7ac4f42805f54c1b02aa107d713e937060b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nmaas-portal",
-  "version": "1.7.0",
+  "version": "1.7.1",
   "license": "Apache 2.0",
   "angular-cli": {},
   "scripts": {
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index 610c10ccf5c6a61d2610e4be2b3fdefe9e51fcde..31a968fec3b241c1d54e3257898a92a6e781fe71 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -6,6 +6,7 @@ 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';
+import {LinkAccountComponent} from './welcome/link-account/link-account.component';
 
 const appRoutes: Routes = [
     ...WelcomeRoutes,
@@ -13,6 +14,7 @@ const appRoutes: Routes = [
     ...ServiceUnavailableRoutes,
     { path: 'notfound', component: PageNotFoundComponent },
     { path: 'login-success', component: LoginSuccessComponent },
+    { path: 'login-linking', component: LinkAccountComponent},
     { path: '**', redirectTo: '/welcome' },
 
 ];
diff --git a/src/app/appmarket/appdetails/appdetails.component.ts b/src/app/appmarket/appdetails/appdetails.component.ts
index e5518794a0850eb436fcafbe67025c1e78c33d75..cb156314c0447fa5f6e4530551266420d105368f 100644
--- a/src/app/appmarket/appdetails/appdetails.component.ts
+++ b/src/app/appmarket/appdetails/appdetails.component.ts
@@ -146,7 +146,8 @@ export class AppDetailsComponent implements OnInit {
         }
 
         return this.authService.hasRole(Role[Role.ROLE_SYSTEM_ADMIN])
-            || this.authService.hasDomainRole(this.domainId, Role[Role.ROLE_DOMAIN_ADMIN]);
+            || this.authService.hasDomainRole(this.domainId, Role[Role.ROLE_DOMAIN_ADMIN])
+            || this.authService.hasDomainRole(this.domainId, Role[Role.ROLE_GROUP_DOMAIN_ADMIN]);
     }
 
     public isApplicationEnabledInDomain(): boolean {
diff --git a/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts b/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts
index 449459e4f4b881d437f763ae6433b6b45ad4b7b7..3634c03e89d9f7d5b1a1da649ce0908e432ff86b 100644
--- a/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts
+++ b/src/app/appmarket/appinstance/appinstance/appinstance.component.spec.ts
@@ -186,6 +186,7 @@ describe('Component: AppInstance', () => {
         createdAt: new Date(),
         descriptiveDeploymentId: 'test-oxidized-48',
         domainId: 4,
+        domainName: "Test Domain",
         id: 1,
         internalId: 'eccbaf70-7fdd-401a-bb3e-b8659bcfbdff',
         name: 'oxi-virt-1',
diff --git a/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.html b/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.html
index 88caaeecc4615f695012b5416a481ddead7964af..d97bd6f0962466ec5d1382e6f37d344ceb78cd61 100644
--- a/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.html
+++ b/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.html
@@ -78,7 +78,7 @@
                 <td class="col-lg-1 col-md-1">{{appInstance?.applicationVersion}}</td>
                 <td class="col-lg-2 col-md-2"
                     *ngIf="domainId === undefined || domainId === domainService.getGlobalDomainId()">
-                    {{getDomainNameById(appInstance?.domainId)}}
+                    {{appInstance?.domainName}}
                 </td>
                 <td class="col-lg-1 col-md-1">{{appInstance?.owner?.username}}</td>
                 <td class="col-lg-2 col-md-2">{{appInstance?.createdAt | localDate:'dd-MM-yyyy HH:mm'}}</td>
@@ -128,7 +128,7 @@
                 <td class="col-lg-2 col-md-2">{{appInstance?.applicationName}}</td>
                 <td class="col-lg-1 col-md-1"
                     *ngIf="domainId === undefined || domainId === domainService.getGlobalDomainId()">
-                    {{getDomainNameById(appInstance?.domainId)}}</td>
+                    {{appInstance?.domainName}}</td>
                 <td class="col-lg-1 col-md-1">{{appInstance?.owner?.username}}</td>
                 <td class="col-lg-2 col-md-2">{{appInstance?.createdAt | localDate:'dd-MM-yyyy HH:mm'}}</td>
                 <td class="col-lg-3 col-md-3">{{ translateState(appInstance?.state) }}</td>
diff --git a/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.ts b/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.ts
index 1a95ba43bb1153d842a4ccd17a8969143f2dbee5..b02be4cc73d46546d2600be1885040d0bbc19528 100644
--- a/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.ts
+++ b/src/app/appmarket/appinstance/appinstancelist/appinstancelist.component.ts
@@ -52,8 +52,6 @@ export class AppInstanceListComponent implements OnInit {
     public selectedUsername: string;
     public domainId = 0;
 
-    public domains: Domain[] = [];
-
     public searchValue = '';
     public selectionOptions = [
         { label: this.translateEnum(AppInstanceListSelection.ALL), value: AppInstanceListSelection.ALL },
@@ -73,9 +71,6 @@ export class AppInstanceListComponent implements OnInit {
 
     ngOnInit() {
         this.sessionService.registerCulture(this.translateService.currentLang);
-        this.domainService.getAll().subscribe(result => {
-            this.domains.push(...result);
-        });
         const i = sessionStorage.getItem(this.item_number_key);
         if (i) {
             this.maxItemsOnPage = +i;
@@ -110,12 +105,6 @@ export class AppInstanceListComponent implements OnInit {
 
     }
 
-    public getDomainNameById(id: number): string {
-        if (this.domains === undefined) {
-            return 'none';
-        }
-        return this.domains.find(value => value.id === id).name;
-    }
 
     public translateEnum(value: AppInstanceListSelection): string {
         let outValue = '';
diff --git a/src/app/appmarket/appinstance/modals/add-members-modal/add-members-modal.component.spec.ts b/src/app/appmarket/appinstance/modals/add-members-modal/add-members-modal.component.spec.ts
index 4a613f1394d03e28924f20c069a4f8c3e716cf28..0e2900d4ff0f8e9c11652b992abff6e0be6964e8 100644
--- a/src/app/appmarket/appinstance/modals/add-members-modal/add-members-modal.component.spec.ts
+++ b/src/app/appmarket/appinstance/modals/add-members-modal/add-members-modal.component.spec.ts
@@ -32,6 +32,7 @@ describe('AddMembersModalComponent', () => {
         createdAt: new Date(),
         descriptiveDeploymentId: 'test-oxidized-48',
         domainId: 4,
+        domainName: "Test Domain",
         id: 1,
         internalId: 'eccbaf70-7fdd-401a-bb3e-b8659bcfbdff',
         name: 'oxi-virt-1',
diff --git a/src/app/appmarket/domains/domain/domain.component.html b/src/app/appmarket/domains/domain/domain.component.html
index 00208f2f896690b530f2229310fa7dd3b6c375dc..c9c32db1e1e83a214897894a8ebca1958fc6dacb 100644
--- a/src/app/appmarket/domains/domain/domain.component.html
+++ b/src/app/appmarket/domains/domain/domain.component.html
@@ -260,6 +260,11 @@
 		<div class="flex justify-content-end">
 			<button *ngIf="!isInMode(ComponentMode.VIEW)" type="submit" class="btn btn-primary" [disabled]="!domainForm.form.valid">{{ 'DOMAIN_DETAILS.SUBMIT_BUTTON' | translate }}</button>
 		</div>
+
+		<br *ngIf="errorMessage">
+      <div class="alert alert-danger text-left" *ngIf="errorMessage">
+        {{errorMessage}}
+      </div>
 	</form>
 </div>
 
diff --git a/src/app/appmarket/domains/domain/domain.component.ts b/src/app/appmarket/domains/domain/domain.component.ts
index eecd96f7840b8cacb482cbfaa219fc6cab1cdf15..d74fcedd3bb6e0390478aba4961df539decde186 100644
--- a/src/app/appmarket/domains/domain/domain.component.ts
+++ b/src/app/appmarket/domains/domain/domain.component.ts
@@ -9,7 +9,7 @@ import {User} from '../../../model';
 import {Observable, of} from 'rxjs';
 import {UserRole} from '../../../model/userrole';
 import {AuthService} from '../../../auth/auth.service';
-import {ModalComponent} from '../../../shared';
+import {ModalComponent} from '../../../shared'; 
 import {map, shareReplay, take} from 'rxjs/operators';
 import {DcnDeploymentType} from '../../../model/dcndeploymenttype';
 import {CustomerNetwork} from '../../../model/customernetwork';
@@ -48,6 +48,8 @@ export class DomainComponent extends BaseComponent implements OnInit {
 
     public annotations : Observable<DomainAnnotation[]> = of([]);
 
+    public errorMessage = "";
+
     constructor(public domainService: DomainService,
                 protected userService: UserService,
                 private router: Router,
@@ -103,7 +105,14 @@ export class DomainComponent extends BaseComponent implements OnInit {
         if (this.domainId !== undefined) {
             this.updateExistingDomain();
         } else {
-            this.domainService.add(this.domain).subscribe(() => this.router.navigate(['admin/domains/']));
+            this.domainService.add(this.domain).subscribe(() => {
+                this.router.navigate(['admin/domains/'])
+        }, err => {
+            console.error(err);
+            if(err.statusCode !== 409 && err?.message !== undefined) this.errorMessage = err.message;
+            else this.errorMessage = err;
+    
+        });
         }
         this.domainService.setUpdateRequiredFlag(true);
     }
diff --git a/src/app/auth/auth.service.spec.ts b/src/app/auth/auth.service.spec.ts
index e9eef99417406df03337405ecd381adfb6f5a3c7..170ece28132bc78a75fd54ad8338c48914b82ea4 100644
--- a/src/app/auth/auth.service.spec.ts
+++ b/src/app/auth/auth.service.spec.ts
@@ -3,19 +3,18 @@ import {TestBed, waitForAsync} from '@angular/core/testing';
 import {AuthService} from './auth.service';
 import {AppConfigService, ConfigurationService} from '../service';
 import {JwtHelperService} from '@auth0/angular-jwt';
-import {HttpClientTestingModule} from '@angular/common/http/testing';
+import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
 import {Role, UserRole} from '../model/userrole';
 import {ProfileService} from '../service/profile.service';
 import {Observable, of} from 'rxjs';
-import { Configuration } from '../model/configuration';
-import { HttpHandler } from '@angular/common/http';
+import {Configuration} from '../model/configuration';
 
 describe('Service: Auth', () => {
     let authService: AuthService;
     let appConfigServiceSpy: jasmine.SpyObj<AppConfigService>;
     let jwtHelperServiceSpy: jasmine.SpyObj<JwtHelperService>;
     let maintenanceServiceSpy: jasmine.SpyObj<ConfigurationService>;
-
+    let httpMock: HttpTestingController;
     let store: any = {};
 
     beforeEach(waitForAsync(() => {
@@ -23,7 +22,8 @@ describe('Service: Auth', () => {
             config: {
                 apiUrl: 'http://api.url',
                 tokenName: 'token',
-            }
+            },
+            getTestInstanceModalKey: () => 'testModalKey'
         };
         const jwtSpy = jasmine.createSpyObj('JwtHelperService', ['decodeToken', 'isTokenExpired']);
         jwtSpy.decodeToken.and.returnValue({
@@ -41,19 +41,19 @@ describe('Service: Auth', () => {
 
         class MockConfigurationService {
             protected uri: string;
-        
+
             constructor() {
                 this.uri = 'http://localhost/api';
             }
-        
+
             public getApiUrl(): string {
                 return 'http://localhost/api';
             }
-        
+
             public getConfiguration(): Observable<Configuration> {
                 return of<Configuration>();
             }
-        
+
             public updateConfiguration(configuration: Configuration): Observable<any> {
                 return of<Configuration>();
             }
@@ -84,6 +84,7 @@ describe('Service: Auth', () => {
             ],
         });
 
+        httpMock = TestBed.inject(HttpTestingController)
         authService = TestBed.get(AuthService);
         authService.profile = [userRole, userRole2]
         appConfigServiceSpy = TestBed.get(AppConfigService);
@@ -104,6 +105,10 @@ describe('Service: Auth', () => {
         });
 
     }));
+    afterEach(() => {
+        httpMock.verify();
+        store = {};
+    });
 
     it('should create service', () => {
         expect(authService).toBeTruthy();
@@ -180,8 +185,11 @@ describe('Service: Auth', () => {
     });
 
     it('should remove token on logout', () => {
+        store['oidc-token'] = 'some-oidc-token';
         authService.logout();
         expect(store['token']).not.toBeDefined();
+        const req = httpMock.expectOne('http://api.url/oidc/logout/some-oidc-token');
+        req.flush({});
     });
 
     it('should be logged in when token is present and valid', () => {
@@ -197,4 +205,58 @@ describe('Service: Auth', () => {
         expect(r).toEqual(false);
     });
 
+    it('should store token and oidc token in localStorage', () => {
+        authService.storeToken('abc123');
+        expect(store['token']).toEqual('abc123');
+
+        authService.storeOidcToken('oidc456');
+        expect(store['oidc-token']).toEqual('oidc456');
+    });
+
+    it('should remove roles from localStorage', () => {
+        store['rolesToken'] = 'some_roles';
+        authService.removeRoles();
+        expect(store['rolesToken']).toBeUndefined();
+    });
+
+    it('should load and parse roles from localStorage', () => {
+        const roles = [{domainId: 1, role: Role.ROLE_USER, domainName: 'x'}];
+        store['rolesToken'] = JSON.stringify(roles);
+
+        const result = authService.loadRoles();
+        expect(result.length).toEqual(1);
+        expect(result[0].role).toEqual(Role.ROLE_USER);
+    });
+
+    it('should assign loaded roles to profile', () => {
+        const roles = [{domainId: 2, role: Role.ROLE_DOMAIN_ADMIN, domainName: 'x'}];
+        store['rolesToken'] = JSON.stringify(roles);
+        authService.loadAndSaveRoles();
+        expect(authService.profile[0].role).toEqual(Role.ROLE_DOMAIN_ADMIN);
+    });
+    it('should stringify and store roles', () => {
+        const roles = [new UserRole()];
+        roles[0].domainId = 1;
+        roles[0].role = Role.ROLE_USER;
+        roles[0].domainName = 'dom1';
+
+        authService.storeRoles(roles);
+        expect(store['rolesToken']).toContain('ROLE_USER');
+    });
+    it('should get global role from token', () => {
+        const result = authService.getGlobalRole();
+        expect(result).toContain('ROLE_SYSTEM_ADMIN');
+    });
+
+    it('should handle login error with catchError', waitForAsync(() => {
+        authService.login('user', 'pass').subscribe({
+            next: () => fail('Expected error'),
+            error: (err) => {
+                expect(err.status).toEqual(401);
+            }
+        });
+
+        const req = httpMock.expectOne('http://api.url/auth/basic/login');
+        req.flush({ message: 'Invalid credentials' }, { status: 401, statusText: 'Unauthorized' });
+    }));
 });
diff --git a/src/app/auth/auth.service.ts b/src/app/auth/auth.service.ts
index a3426c27b2b23a95efaec88574ee9c9078b05f85..6156c8e479cfd788ed7808556017f30cb57bc40f 100644
--- a/src/app/auth/auth.service.ts
+++ b/src/app/auth/auth.service.ts
@@ -1,13 +1,11 @@
-import {BehaviorSubject, Observable, Subject, throwError as observableThrowError, of} from 'rxjs';
+import {BehaviorSubject, Observable, of, Subject, throwError as observableThrowError} from 'rxjs';
 import {catchError, debounceTime, map} from 'rxjs/operators';
 import {Injectable} from '@angular/core';
 import {AppConfigService, ConfigurationService} from '../service';
 import {JwtHelperService} from '@auth0/angular-jwt';
 import {HttpClient, HttpHeaders} from '@angular/common/http';
-import {User} from '../model';
 import {ProfileService} from '../service/profile.service';
 import {Role, UserRole} from '../model/userrole';
-import {interval, Subscription} from 'rxjs';
 
 
 export class DomainRoles {
@@ -17,10 +15,6 @@ export class DomainRoles {
     ) {
     }
 
-    public getDomainId(): number {
-        return this.domainId;
-    }
-
     public getRoles(): string[] {
         return this.roles;
     }
@@ -183,15 +177,6 @@ export class AuthService {
         return this.jwtHelper.decodeToken(token).global_role;
     }
 
-    public getDomainsRoles() {
-        const token = this.getToken();
-        if (token == null) {
-            return null;
-        }
-        return this.jwtHelper.decodeToken(token).roles;
-
-    }
-
     public getDomainRoles(): Map<number, DomainRoles> {
         const domainRolesMap: Map<number, DomainRoles> = new Map<number, DomainRoles>();
 
@@ -253,6 +238,49 @@ export class AuthService {
         return domainsWithRole;
     }
 
+    public oidcLinkingLogin(oidcToken: string,
+                            email: string,
+                            password: string,
+                            uuid: string,
+                            firstName: string,
+                            lastName: string) {
+        const headers = new HttpHeaders({'Content-Type': 'application/json', 'Accept': 'application/json'});
+
+        return this.http.post(this.appConfig.config.apiUrl + '/oidc/link',
+            JSON.stringify(
+                {
+                    'oidcToken': oidcToken,
+                    'email': email,
+                    'password': password,
+                    'uuid': uuid,
+                    'firstName': firstName,
+                    'lastName': lastName,
+                }
+            ),
+            {headers: headers}).pipe(
+            debounceTime(1000),
+            map((res: Response) => {
+                    const token = res && res['token'];
+                    const oidcToken = res && res['oidcToken'];
+                    if (token && oidcToken) {
+                        this.storeToken(token);
+                        this.storeOidcToken(oidcToken);
+                        this.loginUsingSsoService = false;
+                        this.isLoggedInSubject.next(true);
+                        this.profileService.getRoles().subscribe(profile => {
+                            this.profile = profile
+                            this.storeRoles(profile);
+                            return true;
+                        })
+                    } else {
+                        this.isLoggedInSubject.next(false);
+                        return false;
+                    }
+                }
+            ),
+        )
+    }
+
     public login(username: string, password: string): Observable<boolean> {
         // hack so test instance modal is shown onl after login
         localStorage.setItem(this.appConfig.getTestInstanceModalKey(), 'True');
@@ -306,49 +334,6 @@ export class AuthService {
             }));
     }
 
-    public propagateSSOLogin(userid: string): Observable<boolean> {
-        console.debug('propagateSSOLogin');
-        console.debug('propagateSSOLogin ' + this.appConfig.config.apiUrl);
-        console.debug('propagateSSOLogin ' + this.appConfig.config.apiUrl + '/auth/sso/login');
-        console.debug('propagateSSOLogin ' + userid);
-        // hack so test instance modal is shown onl after login
-        localStorage.setItem(this.appConfig.getTestInstanceModalKey(), 'True');
-
-        if (this.maintenance) {
-            this.isLoggedInSubject.next(false);
-            return of(false);
-        }
-
-        const headers = new HttpHeaders({'Content-Type': 'application/json', 'Accept': 'application/json'});
-        return this.http.post(this.appConfig.config.apiUrl + '/auth/sso/login',
-            JSON.stringify({'userid': userid}), {headers: headers}).pipe(
-            debounceTime(10000),
-            map((response: Response) => {
-                console.debug('SSO login response: ' + response);
-                // login successful if there's a jwt token in the response
-                const token = response && response['token'];
-
-                if (token) {
-                    this.storeToken(token);
-                    console.debug('SSO AUTH | User: ' + this.getUsername());
-                    console.debug('SSO AUTH | Domains: ' + this.getDomains());
-                    console.debug('SSO AUTH | Roles: ' + this.getRoles());
-                    console.debug('SSO AUTH | DomainRoles: ' + this.getDomainRoles());
-                    this.loginUsingSsoService = true;
-                    this.isLoggedInSubject.next(true);
-                    return true;
-                } else {
-                    // return false to indicate failed login
-                    this.isLoggedInSubject.next(false);
-                    return false;
-                }
-            }),
-            catchError((error) => {
-                console.error('SSO login error: ' + error.error['message']);
-                return observableThrowError(error);
-            }));
-    }
-
     public logout(): void {
         const oidcToken = this.getOidcToken();
         this.refresh = null;
@@ -366,6 +351,11 @@ export class AuthService {
         }
     }
 
+    public oidcLogout(oidcToken: string): void {
+        this.http.get(this.appConfig.config.apiUrl + '/oidc/logout/' + oidcToken).subscribe(() => {
+        })
+    }
+
     public isLogged(): boolean {
         const token = this.getToken();
         if (token == null) {
@@ -374,11 +364,6 @@ export class AuthService {
         return (token ? !this.jwtHelper.isTokenExpired(token) : false);
     }
 
-    get isLoggedIn$(): Observable<boolean> {
-        return this.isLoggedInSubject.pipe(
-            debounceTime(100), // use debounceTime to aggregate multiple emissions https://rxjs.dev/api/operators/debounceTime
-        );
-    }
 
     public getDomainIds(): number[] {
         return Array.from(new Set(this.profile.map(ur => ur.domainId)));
diff --git a/src/app/auth/login-success/login-success.component.ts b/src/app/auth/login-success/login-success.component.ts
index e7fec74d4dcaa6d40ec0da867a432314d09eb307..4d5444dc694194d95293604a690ed49bc8ff5611 100644
--- a/src/app/auth/login-success/login-success.component.ts
+++ b/src/app/auth/login-success/login-success.component.ts
@@ -25,6 +25,7 @@ export class LoginSuccessComponent implements OnInit {
             if (refreshToken) {
                 this.authService.storeOidcToken(oidcToken);
             }
+            this.authService.loadUser();
             this.router.navigate(['/'])
         })
 
diff --git a/src/app/directive/roles-exluded.directive.ts b/src/app/directive/roles-exluded.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6b003ab52b1403e88a538ac016bc9e7cdde22636
--- /dev/null
+++ b/src/app/directive/roles-exluded.directive.ts
@@ -0,0 +1,30 @@
+import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
+import { AuthService } from '../auth/auth.service';
+
+@Directive({
+  selector: '[rolesExcluded]'
+})
+export class RolesExcludedDirective {
+  private _excluded: Array<string> = [];
+
+  constructor(
+    private _templateRef: TemplateRef<any>,
+    private _viewContainer: ViewContainerRef,
+    private authService: AuthService
+  ) {}
+
+  @Input() set rolesExcluded(excludedRoles: Array<string>) {
+    this._excluded = excludedRoles;
+    this.updateState();
+  }
+
+  private updateState() {
+    this._viewContainer.clear();
+
+    const hasExcludedRole = this._excluded.some(role => this.authService.hasRole(role));
+    if (!hasExcludedRole) {
+      // If user has exluded role hide the element 
+      this._viewContainer.createEmbeddedView(this._templateRef);
+    } 
+  }
+}
\ No newline at end of file
diff --git a/src/app/directive/roles.directive.ts b/src/app/directive/roles.directive.ts
index 68f2e12346693fe23de1f14c4f90b100cfd8b095..c2155e3c2a02438a75fd56ae119b5a12c910b3d8 100644
--- a/src/app/directive/roles.directive.ts
+++ b/src/app/directive/roles.directive.ts
@@ -3,10 +3,7 @@ import {Directive, Input, TemplateRef, ViewContainerRef} from '@angular/core';
 
 class RoleState {
     public allowed: Array<string> = new Array<string>();
-    public excluded: Array<string> = new Array<string>()
 }
-
-
 @Directive({
     selector: '[roles]',
     inputs: ['roles']
@@ -15,8 +12,6 @@ export class RolesDirective {
 
     private _allowed: Array<string> = new Array<string>();
 
-    private _excluded: Array<string> = new Array<string>();
-
     constructor(private _templateRef: TemplateRef<any>,
                 private _viewContainer: ViewContainerRef,
                 private authService: AuthService) {
@@ -26,53 +21,18 @@ export class RolesDirective {
     @Input() set roles(allowedRoles: Array<string>) {
         this._allowed = allowedRoles;
         this.updateState({
-            allowed: this._allowed,
-            excluded: this._excluded
-        })
-    }
-
-    // Excluded roles have priority than allowed roles
-    // If user have excluded role template would not be shown
-
-    @Input() set rolesExcluded(excluded: Array<string>) {
-        this._excluded = excluded;
-        this.updateState({
-            allowed: this._allowed,
-            excluded: this._excluded
+            allowed: this._allowed
         })
     }
 
     updateState(state: RoleState) {
         this._viewContainer.clear();
-
-        let show: boolean = false;
-        let notAllowed: boolean = false;
-
-        const allowedRoles = state.allowed;
-
-        for (let exclude of state.excluded) {
-            if (this.authService.hasRole(exclude)) {
-                notAllowed = true;
-                break;
-            }
+    
+    
+        const hasAllowedRole = state.allowed.some(role => this.authService.hasRole(role));
+        if (hasAllowedRole) {
+            this._viewContainer.createEmbeddedView(this._templateRef);
         }
-        if (notAllowed) {
-            this._viewContainer.clear();
-        } else {
-            for (let allowedRole of allowedRoles) {
-                if (this.authService.hasRole(allowedRole)) {
-                    show = true;
-                    break;
-                }
-            }
-
-            if (show) {
-                this._viewContainer.createEmbeddedView(this._templateRef);
-            } else {
-                this._viewContainer.clear();
-            }
-        }
-
     }
 
 }
diff --git a/src/app/model/app-instance.ts b/src/app/model/app-instance.ts
index 76edca2f6b68caf22d2f7702e9a2eb6f06d5c237..27119dad519db59323259ae6544037dc14fcd478 100644
--- a/src/app/model/app-instance.ts
+++ b/src/app/model/app-instance.ts
@@ -28,6 +28,7 @@ export class AppInstance {
 
   public id: number = undefined;
   public domainId: number = undefined;
+  public domainName: string = undefined;
   public applicationId: number = undefined;
   public applicationName: string = undefined;
   public applicationVersion: string = undefined;
diff --git a/src/app/shared/navbar/navbar.component.html b/src/app/shared/navbar/navbar.component.html
index cead22d4afd206aea61c47f15b9c44bff96b8767..11b5cb2ef50e26662dfd5e78efe942134349321a 100644
--- a/src/app/shared/navbar/navbar.component.html
+++ b/src/app/shared/navbar/navbar.component.html
@@ -77,9 +77,13 @@
                         <li *roles="['ROLE_SYSTEM_ADMIN']"><a
                                 [routerLink]="['/admin/users']">{{ 'NAVBAR.USERS' | translate }}</a>
                         </li>
-                        <li *roles="['ROLE_DOMAIN_ADMIN', 'ROLE_GROUP_DOMAIN_ADMIN']"><a
-                                [routerLink]="['/domain/users']">{{ 'NAVBAR.DOMAIN_USERS' | translate }}</a>
+                        
+                        <li *roles="['ROLE_DOMAIN_ADMIN', 'ROLE_GROUP_DOMAIN_ADMIN']">
+                                <a *rolesExcluded="['ROLE_SYSTEM_ADMIN']"
+                                    [routerLink]="['/domain/users']">{{ 'NAVBAR.DOMAIN_USERS' | translate }}</a>
+                           
                         </li>
+                    
                         <li *roles="['ROLE_SYSTEM_ADMIN']"><a
                                 [routerLink]="['/admin/languages']">{{ 'NAVBAR.LANGUAGES' | translate }}</a>
                         </li>
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index a6243e0198db0195b3b444eb4e99116ce403afeb..ae6442758d5d7eed07600cb1ddacc71b8535d573 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -1,6 +1,6 @@
 import {DefaultLogo} from '../directive/defaultlogo.directive';
 import {RolesDirective} from '../directive/roles.directive';
-import {NgModule} from '@angular/core';
+import {NgModule, NO_ERRORS_SCHEMA} from '@angular/core';
 import {FormsModule, ReactiveFormsModule} from '@angular/forms';
 import {CommonModule, DatePipe} from '@angular/common';
 
@@ -65,6 +65,7 @@ import { InputGroupModule } from 'primeng/inputgroup';
 import { InputGroupAddonModule } from 'primeng/inputgroupaddon';
 import { ButtonModule } from 'primeng/button';
 import { BrowserModule } from '@angular/platform-browser';
+import { RolesExcludedDirective } from '../directive/roles-exluded.directive';
 
 
 @NgModule({
@@ -103,6 +104,7 @@ import { BrowserModule } from '@angular/platform-browser';
         NavbarComponent,
         DefaultLogo,
         RolesDirective,
+        RolesExcludedDirective,
         MinLengthDirective,
         MaxLengthDirective,
         SearchComponent,
@@ -179,13 +181,16 @@ import { BrowserModule } from '@angular/platform-browser';
         ModalTestInstanceComponent,
         ModalNotificationSendComponent,
         DomainRolesDirective,
+        RolesExcludedDirective,
         SshKeysComponent,
         ModalProvideSshKeyComponent,
         PreferencesComponent,
         SortableHeaderDirective,
         DomainNamespaceAnnotationsComponent,
         AccessTokensComponent
-    ]
+    ],
+    schemas: [NO_ERRORS_SCHEMA], // Dodanie schematu
+
 })
 export class SharedModule {
 }
diff --git a/src/app/shared/users/access-token/access-tokens.component.html b/src/app/shared/users/access-token/access-tokens.component.html
index 9800061a0e11a4ba58e277a6b890c392c71b1b15..6ad21e0418c541ca58a6a394c32520b19778483a 100644
--- a/src/app/shared/users/access-token/access-tokens.component.html
+++ b/src/app/shared/users/access-token/access-tokens.component.html
@@ -6,22 +6,20 @@
             <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">
+                <td style="width: 25%;">{{token.id}}</td>
+                <td style="width: 25%;">{{token.name}}</td>
+                <td style="width: 25%;">{{token.valid}}</td>
+                <td style="width: 25%;" *ngIf="token.valid">
                     <button type="button" class="btn btn-danger"
                             (click)="invalidate(token.id)">{{'TOKENS.BUTTON_INVALIDATE' | translate}}</button>
                 </td>
-                <td *ngIf="!token.valid">
+                <td style="width: 25%;" *ngIf="!token.valid">
                     <button type="button" class="btn btn-danger"
                             (click)="deleteToken(token.id)">{{'TOKENS.BUTTON_DELETE' | translate}}</button>
                 </td>
diff --git a/src/app/shared/users/list/userslist.component.ts b/src/app/shared/users/list/userslist.component.ts
index 7394575d57a4f6d527893ff57c82ad1d4d71b007..1ae3116b57b2d986b67eaaef9d6ca6a47f96d777 100644
--- a/src/app/shared/users/list/userslist.component.ts
+++ b/src/app/shared/users/list/userslist.component.ts
@@ -101,11 +101,20 @@ export class UsersListComponent extends BaseComponent implements OnInit, OnChang
     }
 
     public getAllDomain() {
-        this.domainService.getAll().subscribe(domains => {
-            domains.forEach(domain => {
-                this.domainCache.setData(domain.id, domain)
+        if(this.domainMode) {
+            this.domainService.getMyDomains().subscribe(domains => {
+                domains.forEach(domain => { 
+                    this.domainCache.setData(domain.id, domain)
+                }
+            ) })
+        } else {
+            this.domainService.getAll().subscribe(domains => {
+                domains.forEach(domain => {
+                    this.domainCache.setData(domain.id, domain)
+                })
             })
-        })
+        }
+       
     }
 
     public getDomainName(domainId: number): Observable<string> {
diff --git a/src/app/welcome/link-account/link-account.component.css b/src/app/welcome/link-account/link-account.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc
--- /dev/null
+++ b/src/app/welcome/link-account/link-account.component.css
@@ -0,0 +1 @@
+
diff --git a/src/app/welcome/link-account/link-account.component.html b/src/app/welcome/link-account/link-account.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..2d75205238a0c5f83811c5aa3ebcb229b4d79d89
--- /dev/null
+++ b/src/app/welcome/link-account/link-account.component.html
@@ -0,0 +1,51 @@
+<div style="display: flex; justify-content: center;">
+    <div style="
+margin-top: 50px;
+ width: 60%
+" class="panel panel-default">
+        <div class="panel-heading">{{ 'ACCOUNT_LINKING.HEADER' | translate }}</div>
+        <div class="panel-body">
+            <form *ngIf="user"
+                  class="form-horizontal" #userDetailsForm="ngForm">
+                <div>
+                    <p>
+                        {{ 'ACCOUNT_LINKING.INFO' | translate }}
+                    </p>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-2 control-label">{{ 'USER_DETAILS.FIRST_NAME' | translate }}</label>
+                    <div class="col-sm-10">
+                        <p class="form-control-static">{{ user.firstname }}</p>
+                    </div>
+                </div>
+
+                <div class="form-group">
+                    <label class="col-sm-2 control-label">{{ 'USER_DETAILS.LAST_NAME' | translate }}</label>
+                    <div class="col-sm-10">
+                        <p class="form-control-static">{{ user.lastname }}</p>
+                    </div>
+                </div>
+
+                <div class="form-group">
+                    <label class="col-sm-2 control-label">{{ 'USER_DETAILS.EMAIL' | translate }}</label>
+                    <div class="col-sm-10">
+                        <p class="form-control-static">{{ user.email }}</p>
+                    </div>
+                </div>
+
+                <div class="form-group">
+                    <label for="password" class="col-sm-2 control-label">{{ 'PASSWORD.PASSWORD' | translate }}</label>
+                    <div class="col-sm-10">
+                        <input type="password" class="form-control" id="password"
+                               name="password" [(ngModel)]="password">
+                    </div>
+                </div>
+                <button type="submit" class="btn btn-primary"
+                        (click)="submit()">{{ 'ACCOUNT_LINKING.CONFIRM' | translate }}
+                </button>
+                <div *ngIf="error" class="alert alert-danger" style="margin-top: 20px">{{error}}</div>
+            </form>
+            <br>
+        </div>
+    </div>
+</div>
diff --git a/src/app/welcome/link-account/link-account.component.spec.ts b/src/app/welcome/link-account/link-account.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0b0a9f98c9b851dbd8f044e900df4b02595ca2ca
--- /dev/null
+++ b/src/app/welcome/link-account/link-account.component.spec.ts
@@ -0,0 +1,57 @@
+import {ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {LinkAccountComponent} from './link-account.component';
+import {ActivatedRoute} from '@angular/router';
+import {of} from 'rxjs';
+import {AuthService} from '../../auth/auth.service';
+import {TranslateFakeLoader, TranslateLoader, TranslateModule} from '@ngx-translate/core';
+
+describe('LinkAccountComponent', () => {
+    let component: LinkAccountComponent;
+    let fixture: ComponentFixture<LinkAccountComponent>;
+
+    beforeEach(async () => {
+        await TestBed.configureTestingModule({
+            declarations: [LinkAccountComponent],
+            imports: [TranslateModule.forRoot({
+                loader: {
+                    provide: TranslateLoader,
+                    useClass: TranslateFakeLoader
+                }
+            })],
+            providers: [
+                {
+                    provide: ActivatedRoute,
+                    useValue: {
+                        queryParams: of({
+                            oidc_token: 'mocked.jwt.token'
+                        }),
+                        snapshot: {
+                            paramMap: {
+                                get: () => null
+                            }
+                        }
+                    }
+                },
+                {
+                    provide: AuthService,
+                    useValue: {
+                        isLogged: () => true,
+                        oidcLogout: jasmine.createSpy('oidcLogout'),
+                        oidcLinkingLogin: jasmine.createSpy('oidcLinkingLogin').and.returnValue(of({}))
+                    }
+                },
+
+            ]
+        })
+            .compileComponents();
+
+        fixture = TestBed.createComponent(LinkAccountComponent);
+        component = fixture.componentInstance;
+        fixture.detectChanges();
+    });
+
+    it('should create', () => {
+        expect(component).toBeTruthy();
+    });
+});
diff --git a/src/app/welcome/link-account/link-account.component.ts b/src/app/welcome/link-account/link-account.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb60e030f051c169a57b0f1a72394101cee6157d
--- /dev/null
+++ b/src/app/welcome/link-account/link-account.component.ts
@@ -0,0 +1,84 @@
+import {Component, OnDestroy, OnInit} from '@angular/core';
+import {User} from '../../model';
+import {ActivatedRoute, Router} from '@angular/router';
+import jwtDecode from 'jwt-decode';
+import {AuthService} from '../../auth/auth.service';
+import {TranslateService} from '@ngx-translate/core';
+
+
+@Component({
+    selector: 'app-link-account',
+    templateUrl: './link-account.component.html',
+    styleUrl: './link-account.component.css'
+})
+export class LinkAccountComponent implements OnInit, OnDestroy {
+    public user: User;
+    private token: string;
+    public password: string;
+    public error: string;
+
+    constructor(
+        private readonly route: ActivatedRoute,
+        private readonly authService: AuthService,
+        private readonly router: Router,
+        private translate: TranslateService,
+    ) {
+    }
+
+    ngOnDestroy() {
+        if (!this.authService.isLogged()) {
+            this.authService.oidcLogout(this.token)
+        }
+    }
+
+    ngOnInit() {
+        this.route.queryParams.subscribe(param => {
+            this.token = param['oidc_token'];
+            const decoded: TokenPayload = jwtDecode<TokenPayload>(this.token);
+            this.user = new User();
+            this.user.username = decoded.sub;
+            this.user.firstname = decoded.given_name;
+            this.user.lastname = decoded.family_name;
+            this.user.email = decoded.email;
+        })
+
+    }
+
+    public submit(): void {
+        this.authService.oidcLinkingLogin(
+            this.token,
+            this.user.email,
+            this.password,
+            this.user.username,
+            this.user.firstname,
+            this.user.lastname,
+        ).subscribe(
+            () => {
+                this.router.navigate(['/']);
+            },
+            err => {
+                this.error = this.translate.instant(this.getMessage(err));
+            }
+        )
+    }
+    private getMessage(err: any): string {
+        switch (err['status']) {
+            case 401:
+                return 'LOGIN.LOGIN_FAILURE_MESSAGE';
+            case 406:
+                return 'LOGIN.APPLICATION_UNDER_MAINTENANCE_MESSAGE';
+            case 409:
+                return 'GENERIC_MESSAGE.UNAVAILABLE_MESSAGE';
+            default:
+                return 'GENERIC_MESSAGE.UNAVAILABLE_MESSAGE';
+        }
+    }
+}
+
+
+interface TokenPayload {
+    sub: string;
+    email: string;
+    given_name: string;
+    family_name: string;
+}
diff --git a/src/app/welcome/login/login.component.ts b/src/app/welcome/login/login.component.ts
index 62e1fc26688f7417969f4cd671b4a93317e49e2a..0a4481b66e12318164be2249a30b512a6dfcf0c9 100644
--- a/src/app/welcome/login/login.component.ts
+++ b/src/app/welcome/login/login.component.ts
@@ -64,8 +64,11 @@ export class LoginComponent implements OnInit {
         );
     }
 
+    // only for use in linking accounts
     public triggerOIDC() {
-        window.location.href = this.appConfig.getOidcUrl();
+        if (!this.configuration.maintenance) {
+            window.location.href = this.appConfig.getOidcUrl();
+        }
     }
 
     public sendResetNotification() {
diff --git a/src/app/welcome/welcome.module.ts b/src/app/welcome/welcome.module.ts
index 08fc1c81e12392217f5c403431925659eea6afb8..e212c4f059d959724211aa423e911d38b087f067 100644
--- a/src/app/welcome/welcome.module.ts
+++ b/src/app/welcome/welcome.module.ts
@@ -20,38 +20,41 @@ import {TranslateModule} from '@ngx-translate/core';
 import {PasswordResetComponent} from './passwordreset/password-reset.component';
 import {PasswordStrengthMeterComponent} from 'angular-password-strength-meter';
 import {PolicySubpageComponent} from './policy-subpage/policy-subpage.component';
+import {LinkAccountComponent} from './link-account/link-account.component';
 
 @NgModule({
-  declarations: [
-    WelcomeComponent,
-    LoginComponent,
-    LogoutComponent,
-    RegistrationComponent,
-    ProfileComponent,
-    CompleteComponent,
-    TermsAcceptanceComponent,
-    PasswordResetComponent,
-    PolicySubpageComponent
-  ],
-  imports: [
-    FormsModule,
-    ReactiveFormsModule,
-    CommonModule,
-    RouterModule,
-    SharedModule,
-    PipesModule,
-    AppMarketModule,
-    PasswordStrengthMeterComponent,
-    TranslateModule.forChild()
-  ],
-  exports: [
-    WelcomeComponent
-  ],
-  providers: [
-    RegistrationService,
-    UserService,
-    ChangelogService,
-    ContentDisplayService
-  ]
+    declarations: [
+        WelcomeComponent,
+        LoginComponent,
+        LogoutComponent,
+        RegistrationComponent,
+        ProfileComponent,
+        CompleteComponent,
+        TermsAcceptanceComponent,
+        PasswordResetComponent,
+        PolicySubpageComponent,
+        LinkAccountComponent
+    ],
+    imports: [
+        FormsModule,
+        ReactiveFormsModule,
+        CommonModule,
+        RouterModule,
+        SharedModule,
+        PipesModule,
+        AppMarketModule,
+        PasswordStrengthMeterComponent,
+        TranslateModule.forChild()
+    ],
+    exports: [
+        WelcomeComponent
+    ],
+    providers: [
+        RegistrationService,
+        UserService,
+        ChangelogService,
+        ContentDisplayService
+    ]
 })
-export class WelcomeModule {}
+export class WelcomeModule {
+}
diff --git a/ws/run_ws.sh b/ws/run_ws.sh
deleted file mode 100644
index 8763a587feed5aac2fcb74b297ebaed9481b0859..0000000000000000000000000000000000000000
--- a/ws/run_ws.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-echo "Downloading WhiteSource agent..."
-curl -LJO https://github.com/whitesource/unified-agent-distribution/releases/latest/download/wss-unified-agent.jar
-
-echo "Running WhiteSource scan..."
-java -jar wss-unified-agent.jar -userKey ${USER_KEY} -apiKey ${API_KEY} -projectVersion ${PROJECT_VERSION} -projectToken ${PROJECT_TOKEN} -productVersion ${PRODUCT_VERSION} -productToken ${PRODUCT_TOKEN} -c ws.config -d ../
\ No newline at end of file