diff --git a/changelog.txt b/changelog.txt
index 0f6c13938319850d7317e8f9f352c3eadd3915ee..ab2dec575b9b2f2f1b8e09fbe017892b6c24a076 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,7 @@
 eDelivery SMP 4.2
 - added new properties:
+    smp.passwordPolicy.validationRegex: Regular expression do define password minimum complexity rules!
+    smp.passwordPolicy.validationMessage: The error message shown to the user in case the password does not follow the regex put in the domibus.passwordPolicy.pattern property"
     smp.ui.authentication.types: Set list of '|' separated UI authentication types. Currently supported PASSWORD, SSO: ex. PASSWORD|SSO
     smp.automation.authentication.types: Set list of '|' separated automation authentication types (Web-Service integration). Currently supported PASSWORD, CERT: ex. PASSWORD|CERT
     smp.http.forwarded.headers.enabled to control usage of Forwarded parameters RP/LoadBalancer.
diff --git a/pom.xml b/pom.xml
index 5e08d1af1528909e9cbba9ced8db828d8c630a0d..750159a5f86c9bb3804a88baf3fabc759fb03e40 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,7 +53,6 @@
         <cxf.version>3.4.5</cxf.version>
         <dnsjava.version>2.1.7</dnsjava.version>
         <ehcache.version>2.10.6</ehcache.version>
-        <guava.version>24.1.1-jre</guava.version>
         <h2.version>1.4.187</h2.version>
         <hamcrest.version>2.0.0.0</hamcrest.version>
         <hibernate-jpa.version>1.0.2.Final</hibernate-jpa.version>
@@ -351,11 +350,6 @@
                 <artifactId>orika-core</artifactId>
                 <version>${orika.version}</version>
             </dependency>
-            <dependency>
-                <groupId>com.google.guava</groupId>
-                <artifactId>guava</artifactId>
-                <version>${guava.version}</version>
-            </dependency>
             <dependency>
                 <groupId>ch.qos.logback</groupId>
                 <artifactId>logback-classic</artifactId>
diff --git a/smp-angular/proxy-config.json b/smp-angular/proxy-config.json
index dc458d6f4ac03189d41aa649490f4f60bebc112a..b885c7fec301933136d38ed42c291b3ce9aae0b9 100644
--- a/smp-angular/proxy-config.json
+++ b/smp-angular/proxy-config.json
@@ -11,5 +11,31 @@
       "/smp": "/"
     },
     "cookieDomainRewrite": "localhost"
+  },
+  "/public/**": {
+    "target" : "http://localhost:8080/",
+    "secure" : "false",
+    "pathRewrite": {
+      "^/public": "/smp/ui/public"
+    },
+    "logLevel": "debug",
+    "changeOrigin": true,
+    "cookiePathRewrite": {
+      "/smp": "/"
+    },
+    "cookieDomainRewrite": "localhost"
+  },
+  "/internal/**": {
+    "target" : "http://localhost:8080/",
+    "secure" : "false",
+    "pathRewrite": {
+      "^/internal": "/smp/ui/internal"
+    },
+    "logLevel": "debug",
+    "changeOrigin": true,
+    "cookiePathRewrite": {
+      "/smp": "/"
+    },
+    "cookieDomainRewrite": "localhost"
   }
 }
diff --git a/smp-angular/src/app/app-config/smp-config.model.ts b/smp-angular/src/app/app-config/smp-config.model.ts
index 5d6942161083e64e171dddd1ae9316b0329b6416..c1469f866513fcfc980052dd86f81bdf0f90c6af 100644
--- a/smp-angular/src/app/app-config/smp-config.model.ts
+++ b/smp-angular/src/app/app-config/smp-config.model.ts
@@ -3,4 +3,6 @@ export interface SmpConfig {
   smlParticipantMultiDomainOn?: boolean;
   participantSchemaRegExp?: string;
   participantSchemaRegExpMessage?: string;
+  passwordValidationRegExp?: string;
+  passwordValidationRegExpMessage?: string;
 }
diff --git a/smp-angular/src/app/app-config/smp-config.service.ts b/smp-angular/src/app/app-config/smp-config.service.ts
index 07d3a590918b755564a31c06636ebce58fbbce0a..56aeeee659d613683f0efe6e1c9e9f66016e5fe9 100644
--- a/smp-angular/src/app/app-config/smp-config.service.ts
+++ b/smp-angular/src/app/app-config/smp-config.service.ts
@@ -12,7 +12,7 @@ export class SmpConfigService {
 
   getSmpInfo(): Observable<SmpConfig> {
     let subject = new ReplaySubject<SmpConfig>();
-    this.http.get<SmpConfig>(SmpConstants.REST_CONFIG)
+    this.http.get<SmpConfig>(SmpConstants.REST_INTERNAL_APPLICATION_CONFIG)
       .subscribe((res: SmpConfig) => {
         subject.next(res);
       }, error => {
diff --git a/smp-angular/src/app/app-info/smp-info.service.ts b/smp-angular/src/app/app-info/smp-info.service.ts
index a336538b8bacc21d1b9fe3e83029c8c32aa89b01..c8e898a8e166c49e92d5e32eefe0581184fe9f26 100644
--- a/smp-angular/src/app/app-info/smp-info.service.ts
+++ b/smp-angular/src/app/app-info/smp-info.service.ts
@@ -12,7 +12,7 @@ export class SmpInfoService {
 
   getSmpInfo(): Observable<SmpInfo> {
     let subject = new ReplaySubject<SmpInfo>();
-    this.http.get<SmpInfo>(SmpConstants.REST_APPLICATION)
+    this.http.get<SmpInfo>(SmpConstants.REST_PUBLIC_APPLICATION_INFO)
       .subscribe((res: SmpInfo) => {
         subject.next(res);
       }, error => {
diff --git a/smp-angular/src/app/app.component.html b/smp-angular/src/app/app.component.html
index d33059101c681ca80d210edcb0a66ffe97d424f9..aa95545668e3ff89763ee693766cb39ae7cf7e11 100644
--- a/smp-angular/src/app/app.component.html
+++ b/smp-angular/src/app/app.component.html
@@ -77,10 +77,17 @@
         <mat-menu x-position="before" #settingsMenu="matMenu">
           <div *ngIf="currentUser">
 
+
             <button mat-menu-item id="currentuser_id" (click)="editCurrentUser()">
               <mat-icon>person</mat-icon>
               <span>{{currentUser}}</span>
             </button>
+            <button mat-menu-item id="changePassword_id" (click)="changeCurrentUserPassword()">
+              <span>Change password</span>
+            </button>
+            <button mat-menu-item id="getAccessToken_id" (click)="regenerateAccesesToken()">
+              <span>Generated access token</span>
+            </button>
 
             <hr/>
 
diff --git a/smp-angular/src/app/app.component.ts b/smp-angular/src/app/app.component.ts
index c0995f8643125b510ed7faa6a849d717b47ec7c0..d1155654c11b0d9d3ed2e157ff06b0004342737a 100644
--- a/smp-angular/src/app/app.component.ts
+++ b/smp-angular/src/app/app.component.ts
@@ -59,6 +59,24 @@ export class AppComponent {
     });
   }
 
+  changeCurrentUserPassword() {
+    const formRef: MatDialogRef<any> = this.userController.changePasswordDialog({
+      data: this.securityService.getCurrentUser()
+    });
+  }
+
+  regenerateAccesesToken() {
+    const formRef: MatDialogRef<any> = this.userController.generateAccessTokenDialog({
+      data: this.securityService.getCurrentUser()
+    });
+    formRef.afterClosed().subscribe(result => {
+      /*if (result) {
+        const user = {...formRef.componentInstance.getCurrent(), status: SearchTableEntityStatus.UPDATED};
+        this.userService.updateUser(user);
+      }*/
+    });
+  }
+
   get currentUser(): string {
     let user = this.securityService.getCurrentUser();
     return user ? user.username : "";
diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts
index 8ef283709c79c69de34d0ea48e88f1de142cb5ca..9eac5577842c0dd626828dd56511c82825b7f4cb 100644
--- a/smp-angular/src/app/app.module.ts
+++ b/smp-angular/src/app/app.module.ts
@@ -71,8 +71,8 @@ import {ConfirmationDialogComponent} from './common/confirmation-dialog/confirma
 import {SpinnerComponent} from './common/spinner/spinner.component';
 import {UserService} from './user/user.service';
 import {UserDetailsService} from './user/user-details-dialog/user-details.service';
-import { ExpiredPasswordDialogComponent } from './common/expired-password-dialog/expired-password-dialog.component';
-import { DialogComponent } from './common/dialog/dialog.component';
+import {ExpiredPasswordDialogComponent} from './common/expired-password-dialog/expired-password-dialog.component';
+import {DialogComponent} from './common/dialog/dialog.component';
 import {KeystoreImportDialogComponent} from "./domain/keystore-import-dialog/keystore-import-dialog.component";
 import {KeystoreEditDialogComponent} from "./domain/keystore-edit-dialog/keystore-edit-dialog.component";
 import {CertificateDialogComponent} from "./common/certificate-dialog/certificate-dialog.component";
@@ -81,106 +81,110 @@ import {InformationDialogComponent} from "./common/information-dialog/informatio
 import {KeystoreService} from "./domain/keystore.service";
 import {TruststoreService} from "./user/truststore.service";
 import {SmlIntegrationService} from "./domain/sml-integration.service";
+import {PasswordChangeDialogComponent} from "./common/password-change-dialog/password-change-dialog.component";
+import {AccessTokenGenerationDialogComponent} from "./common/access-token-generation-dialog/access-token-generation-dialog.component";
 
 
 @NgModule({
-    declarations: [
-        AppComponent,
-        LoginComponent,
-        HomeComponent,
-        ServiceGroupEditComponent,
-        ServiceGroupSearchComponent,
-        DomainComponent,
-        DomainDetailsDialogComponent,
-        UserComponent,
-        AlertComponent,
-        FooterComponent,
-        SpinnerComponent,
-        IsAuthorized,
-        SaveDialogComponent,
-        ServiceGroupMetadataDialogComponent,
-        CancelDialogComponent,
-        ConfirmationDialogComponent,
-        InformationDialogComponent,
-        RowLimiterComponent,
-        DatePipe,
-        CapitalizeFirstPipe,
-        DefaultPasswordDialogComponent,
-        ServiceGroupDetailsDialogComponent,
-        ServiceGroupExtensionWizardDialogComponent,
-        ServiceMetadataWizardDialogComponent,
-        ColumnPickerComponent,
-        PageHelperComponent,
-        ClearInvalidDirective,
-        PageHeaderComponent,
-        DomainSelectorComponent,
-        SearchTableComponent,
-        UserDetailsDialogComponent,
-        ExpiredPasswordDialogComponent,
-        DialogComponent,
-        KeystoreImportDialogComponent,
-        KeystoreEditDialogComponent,
-        CertificateDialogComponent,
-        TruststoreEditDialogComponent,
-    ],
-    imports: [
-        BrowserModule,
-        FlexLayoutModule,
-        HttpClientModule,
-        HttpClientXsrfModule.withOptions({
-            cookieName: 'XSRF-TOKEN',
-            headerName: 'X-XSRF-TOKEN'
-        }),
-        BrowserAnimationsModule,
-        FormsModule,
-        NgxDatatableModule,
-        MatButtonModule,
-        MatCardModule,
-        MatDatepickerModule,
-        MatDialogModule,
-        MatTooltipModule,
-        MatToolbarModule,
-        MatMenuModule,
-        MatInputModule,
-        MatIconModule,
-        MatListModule,
-        MatSidenavModule,
-        MatSelectModule,
-        MatTabsModule,
-        MatSlideToggleModule,
-        MatProgressSpinnerModule,
-        routing,
-        ReactiveFormsModule,
-        SharedModule,
-        MatExpansionModule,
-    ],
-    providers: [
-        AuthenticatedGuard,
-        AuthorizedGuard,
-        AuthorizedAdminGuard,
-        DirtyGuard,
-        HttpEventService,
-        SecurityService,
-        SecurityEventService,
-        DomainService,
-        SmpInfoService,
-        AlertService,
-        DownloadService,
-        CertificateService,
-        KeystoreService,
-        TruststoreService,
-        SmlIntegrationService,
-        GlobalLookups,
-        DatePipe,
-        UserService,
-        UserDetailsService,
-        {
-            provide: ExtendedHttpClient,
-            useFactory: extendedHttpClientCreator,
-            deps: [HttpClient, HttpEventService, SecurityService]
-        }
-    ],
-    bootstrap: [AppComponent]
+  declarations: [
+    AppComponent,
+    LoginComponent,
+    HomeComponent,
+    ServiceGroupEditComponent,
+    ServiceGroupSearchComponent,
+    DomainComponent,
+    DomainDetailsDialogComponent,
+    UserComponent,
+    AlertComponent,
+    FooterComponent,
+    SpinnerComponent,
+    IsAuthorized,
+    SaveDialogComponent,
+    ServiceGroupMetadataDialogComponent,
+    CancelDialogComponent,
+    ConfirmationDialogComponent,
+    InformationDialogComponent,
+    RowLimiterComponent,
+    DatePipe,
+    CapitalizeFirstPipe,
+    DefaultPasswordDialogComponent,
+    ServiceGroupDetailsDialogComponent,
+    ServiceGroupExtensionWizardDialogComponent,
+    ServiceMetadataWizardDialogComponent,
+    ColumnPickerComponent,
+    PageHelperComponent,
+    ClearInvalidDirective,
+    PageHeaderComponent,
+    DomainSelectorComponent,
+    SearchTableComponent,
+    UserDetailsDialogComponent,
+    ExpiredPasswordDialogComponent,
+    PasswordChangeDialogComponent,
+    AccessTokenGenerationDialogComponent,
+    DialogComponent,
+    KeystoreImportDialogComponent,
+    KeystoreEditDialogComponent,
+    CertificateDialogComponent,
+    TruststoreEditDialogComponent,
+  ],
+  imports: [
+    BrowserModule,
+    FlexLayoutModule,
+    HttpClientModule,
+    HttpClientXsrfModule.withOptions({
+      cookieName: 'XSRF-TOKEN',
+      headerName: 'X-XSRF-TOKEN'
+    }),
+    BrowserAnimationsModule,
+    FormsModule,
+    NgxDatatableModule,
+    MatButtonModule,
+    MatCardModule,
+    MatDatepickerModule,
+    MatDialogModule,
+    MatTooltipModule,
+    MatToolbarModule,
+    MatMenuModule,
+    MatInputModule,
+    MatIconModule,
+    MatListModule,
+    MatSidenavModule,
+    MatSelectModule,
+    MatTabsModule,
+    MatSlideToggleModule,
+    MatProgressSpinnerModule,
+    routing,
+    ReactiveFormsModule,
+    SharedModule,
+    MatExpansionModule,
+  ],
+  providers: [
+    AuthenticatedGuard,
+    AuthorizedGuard,
+    AuthorizedAdminGuard,
+    DirtyGuard,
+    HttpEventService,
+    SecurityService,
+    SecurityEventService,
+    DomainService,
+    SmpInfoService,
+    AlertService,
+    DownloadService,
+    CertificateService,
+    KeystoreService,
+    TruststoreService,
+    SmlIntegrationService,
+    GlobalLookups,
+    DatePipe,
+    UserService,
+    UserDetailsService,
+    {
+      provide: ExtendedHttpClient,
+      useFactory: extendedHttpClientCreator,
+      deps: [HttpClient, HttpEventService, SecurityService]
+    }
+  ],
+  bootstrap: [AppComponent]
 })
 export class AppModule {
 }
diff --git a/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.css b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..e3fad2cbffc9ce3386e5695a983b544037216b08
--- /dev/null
+++ b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.css
@@ -0,0 +1,4 @@
+.password-panel .mat-form-field {
+  margin-bottom: 1.5em;
+  padding: 2px;
+}
diff --git a/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.html b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..3c48461f16f2267dbecd072b07c60ca59741f30f
--- /dev/null
+++ b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.html
@@ -0,0 +1,60 @@
+<h2 mat-dialog-title>{{formTitle}}</h2>
+<mat-dialog-content style="width:700px">
+
+  <div *ngIf="message" [ngClass]="{ 'alert-message': message, 'alert-message-success': messageType === 'success', 'alert-message-error':messageType === 'error' }" id="alertmessage_id">
+    <span class="alert-message-close-button" (click)="clearAlert()">&times;</span>
+    {{message}}
+  </div>
+  <form [formGroup]="dialogForm">
+    <mat-card>
+      <mat-card-content fxLayout="column">
+        <mat-form-field style="width:100%">
+          <input matInput placeholder="User email" formControlName="email" id="em_id" readonly="true">
+        </mat-form-field>
+        <mat-form-field style="width:100%">
+          <input matInput placeholder="Username" formControlName="username" id="un_id" readonly="true">
+        </mat-form-field>
+      </mat-card-content>
+    </mat-card>
+    <mat-card>
+      <mat-card-content>
+        <mat-card-actions >
+          <button mat-raised-button color="primary" (click)="regenerateAccessToken()"
+                  [disabled]="!dialogForm.valid" >
+            <mat-icon>check_circle</mat-icon>
+            <span>Regenerate access token</span>
+          </button>
+        </mat-card-actions>
+        <mat-form-field style="width:100%">
+            <input matInput placeholder="Current Password" [type]="hideCurrPwdFiled ? 'password' : 'text'"
+                   formControlName="current-password" required id="cp_id">
+            <mat-icon matSuffix
+                      (click)="hideCurrPwdFiled = !hideCurrPwdFiled">{{hideCurrPwdFiled ? 'visibility_off' : 'visibility'}}</mat-icon>
+            <mat-error *ngIf="passwordError('current-password', 'required')">Password is required</mat-error>
+          </mat-form-field>
+
+          <mat-form-field style="width:100%">
+            <input matInput placeholder="Access token id" formControlName="accessTokenId" id="at_id" readonly="true">
+          </mat-form-field>
+
+          <mat-form-field style="width:100%">
+            <input matInput placeholder="Valid until" formControlName="accessTokenExpireOn" id="expireOn_id"
+                   readonly="true">
+          </mat-form-field>
+
+      </mat-card-content>
+    </mat-card>
+  </form>
+
+  <table class="buttonsRow">
+    <tr>
+      <td>
+        <button mat-raised-button color="primary" mat-dialog-close>
+          <mat-icon>cancel</mat-icon>
+          <span>Close</span>
+        </button>
+      </td>
+    </tr>
+  </table>
+  <div class="required-fields">* required fields</div>
+</mat-dialog-content>
diff --git a/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.spec.ts b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d71a0fdc74e1e58fc014cb70720ef59668b23ced
--- /dev/null
+++ b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PasswordChangeDialogComponent } from './password-change-dialog.component';
+
+describe('PasswordChangeDialogComponent', () => {
+  let component: PasswordChangeDialogComponent;
+  let fixture: ComponentFixture<PasswordChangeDialogComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ PasswordChangeDialogComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PasswordChangeDialogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.ts b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e0dfb7e5198fbc4717870c69721647de654453cc
--- /dev/null
+++ b/smp-angular/src/app/common/access-token-generation-dialog/access-token-generation-dialog.component.ts
@@ -0,0 +1,101 @@
+import {Component, Inject} from '@angular/core';
+import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
+import {
+  AbstractControl,
+  FormBuilder,
+  FormControl,
+  FormGroup,
+  FormGroupDirective, NgForm,
+  ValidatorFn,
+  Validators
+} from "@angular/forms";
+import {User} from "../../security/user.model";
+import {GlobalLookups} from "../global-lookups";
+import {UserDetailsService} from "../../user/user-details-dialog/user-details.service";
+import {AccessTokenRo} from "./access-token-ro.model";
+import {SearchTableEntityStatus} from "../search-table/search-table-entity-status.model";
+import {SecurityService} from "../../security/security.service";
+
+@Component({
+  selector: 'smp-access-token-generation-dialog',
+  templateUrl: './access-token-generation-dialog.component.html',
+  styleUrls: ['./access-token-generation-dialog.component.css']
+})
+export class AccessTokenGenerationDialogComponent {
+
+  formTitle = "Access token generation dialog!";
+  dialogForm: FormGroup;
+  hideCurrPwdFiled: boolean = true;
+  hideNewPwdFiled: boolean = true;
+  hideConfPwdFiled: boolean = true;
+  current: User;
+  message: string;
+  messageType: string = "alert-error";
+
+  constructor(
+    public dialogRef: MatDialogRef<AccessTokenGenerationDialogComponent>,
+    @Inject(MAT_DIALOG_DATA) public data: User,
+    private lookups: GlobalLookups,
+    private userDetailsService: UserDetailsService,
+    private securityService: SecurityService,
+    private fb: FormBuilder
+  ) {
+    this.current = {...data}
+
+
+    this.dialogForm = fb.group({
+      'email': new FormControl({value: null, readonly: true}, null),
+      'username': new FormControl({value: null, readonly: true}, null),
+      'accessTokenId': new FormControl({value: null, readonly: true}, null),
+      'accessTokenExpireOn': new FormControl({value: null, readonly: true}, null),
+      'current-password': new FormControl({value: null, readonly: false}, [Validators.required]),
+    });
+
+    this.dialogForm.controls['email'].setValue(this.current.emailAddress);
+    this.dialogForm.controls['username'].setValue(this.current.username);
+    this.dialogForm.controls['accessTokenId'].setValue(this.current.accessTokenId);
+    this.dialogForm.controls['accessTokenExpireOn'].setValue(this.current.accessTokenExpireOn);
+    this.dialogForm.controls['current-password'].setValue('');
+  }
+
+  public passwordError = (controlName: string, errorName: string) => {
+    return this.dialogForm.controls[controlName].hasError(errorName);
+  }
+
+  regenerateAccessToken() {
+    this.clearAlert();
+
+    // update password
+    this.userDetailsService.regenerateAccessToken(this.current.userId,
+      this.dialogForm.controls['current-password'].value).subscribe((response: AccessTokenRo) => {
+        this.showSuccessMessage("Token with id: " + response.identifier + " and value: " + response.value + " was generated!")
+        this.current.accessTokenId = response.identifier;
+        this.current.accessTokenExpireOn = response.expireOn;
+        // set to current form
+        this.dialogForm.controls['accessTokenId'].setValue(this.current.accessTokenId);
+        this.dialogForm.controls['accessTokenExpireOn'].setValue(this.current.accessTokenExpireOn);
+        // save new values
+        const user = {...this.current, status: SearchTableEntityStatus.UPDATED};
+        this.securityService.updateUserDetails(user);
+      },
+      (err) => {
+        this.showErrorMessage(err.error.errorDescription);
+      }
+    );
+  }
+
+  showSuccessMessage(value: string) {
+    this.message = value;
+    this.messageType = "success";
+  }
+
+  showErrorMessage(value: string) {
+    this.message = value;
+    this.messageType = "error";
+  }
+
+  clearAlert() {
+    this.message = null;
+    this.messageType = null;
+  }
+}
diff --git a/smp-angular/src/app/user/access-token-ro.model.ts b/smp-angular/src/app/common/access-token-generation-dialog/access-token-ro.model.ts
similarity index 83%
rename from smp-angular/src/app/user/access-token-ro.model.ts
rename to smp-angular/src/app/common/access-token-generation-dialog/access-token-ro.model.ts
index c399755ffb79a973254633205c18f5d1f02feb2e..0dd11abcb4093355df42427ed4773c4c950e9c88 100644
--- a/smp-angular/src/app/user/access-token-ro.model.ts
+++ b/smp-angular/src/app/common/access-token-generation-dialog/access-token-ro.model.ts
@@ -2,4 +2,5 @@ export interface AccessTokenRo {
   identifier: string;
   value: string;
   generatedOn?: Date;
+  expireOn?: Date;
 }
diff --git a/smp-angular/src/app/common/error/error-model.ts b/smp-angular/src/app/common/error/error-model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..53cd1b8dfdffe5b21e227742f980eac9c9f24354
--- /dev/null
+++ b/smp-angular/src/app/common/error/error-model.ts
@@ -0,0 +1,5 @@
+export interface ErrorResponseRO {
+  businessCode?: string;
+  errorDescription?: string;
+  errorUniqueId?: string;
+}
diff --git a/smp-angular/src/app/common/global-lookups.ts b/smp-angular/src/app/common/global-lookups.ts
index 3d693cb222ca59fb51f562924c89494428a51419..d80706a4bc85b7a21619ee3b2afe9ca51c9c3070 100644
--- a/smp-angular/src/app/common/global-lookups.ts
+++ b/smp-angular/src/app/common/global-lookups.ts
@@ -9,6 +9,8 @@ import {AlertService} from "../alert/alert.service";
 import {Subscription} from "rxjs/internal/Subscription";
 import {SmpInfo} from "../app-info/smp-info.model";
 import {SmpConfig} from "../app-config/smp-config.model";
+import {SecurityEventService} from "../security/security-event.service";
+import {ExpiredPasswordDialogComponent} from "./expired-password-dialog/expired-password-dialog.component";
 
 /**
  * Purpose of object is to fetch lookups as domains and users
@@ -30,12 +32,16 @@ export class GlobalLookups implements OnInit {
   cachedApplicationConfig: SmpConfig;
   cachedTrustedCertificateList: Array<any> = [];
 
+  loginSubscription: Subscription;
+  logoutSubscription: Subscription;
 
 
-  constructor(protected alertService: AlertService,  protected securityService: SecurityService, protected http: HttpClient) {
+  constructor(protected alertService: AlertService,
+              protected securityService: SecurityService,
+              protected http: HttpClient,
+              private securityEventService: SecurityEventService) {
     securityService.refreshLoggedUserFromServer();
     this.refreshDomainLookup();
-    this.refreshUserLookup();
     this.refreshCertificateLookup();
     this.refreshApplicationInfo();
     this.refreshApplicationConfiguration();
@@ -43,28 +49,32 @@ export class GlobalLookups implements OnInit {
   }
 
   ngOnInit() {
-
   }
 
   public refreshDomainLookup() {
+    let domainUrl = SmpConstants.REST_PUBLIC_DOMAIN_SEARCH;
+    // for authenticated admin use internal url which returns more data!
+    if (this.securityService.isCurrentUserSMPAdmin() || this.securityService.isCurrentUserSystemAdmin()) {
+      domainUrl = SmpConstants.REST_INTERNAL_DOMAIN_MANAGE;
+    }
     let params: HttpParams = new HttpParams()
       .set('page', '-1')
       .set('pageSize', '-1');
     // init domains
-    this.domainObserver = this.http.get<SearchTableResult>(SmpConstants.REST_DOMAIN, {params});
+    this.domainObserver = this.http.get<SearchTableResult>(domainUrl, {params});
     this.domainObserver.subscribe((domains: SearchTableResult) => {
       this.cachedDomainList = domains.serviceEntities.map(serviceEntity => {
-        return {...serviceEntity}
-      },
-      (error:any) => {
+          return {...serviceEntity}
+        },
+        (error: any) => {
           this.alertService.error("Error occurred while loading domain lookup [" + error + "].")
-      });
+        });
     });
   }
 
   public refreshApplicationInfo() {
 
-    this.http.get<SmpInfo>(SmpConstants.REST_APPLICATION)
+    this.http.get<SmpInfo>(SmpConstants.REST_PUBLIC_APPLICATION_INFO)
       .subscribe((res: SmpInfo) => {
           this.cachedApplicationInfo = res;
         }, error => {
@@ -73,11 +83,12 @@ export class GlobalLookups implements OnInit {
       );
 
   }
+
   public refreshApplicationConfiguration() {
-  // check if authenticated
+    // check if authenticated
     this.securityService.isAuthenticated(false).subscribe((isAuthenticated: boolean) => {
-      if(isAuthenticated) {
-        this.http.get<SmpConfig>(SmpConstants.REST_CONFIG)
+      if (isAuthenticated) {
+        this.http.get<SmpConfig>(SmpConstants.REST_INTERNAL_APPLICATION_CONFIG)
           .subscribe((res: SmpConfig) => {
               this.cachedApplicationConfig = res;
             }, error => {
@@ -90,47 +101,47 @@ export class GlobalLookups implements OnInit {
 
   public refreshUserLookup() {
     // call only for authenticated users.
-    if (this.securityService.isCurrentUserSMPAdmin() || this.securityService.isCurrentUserSystemAdmin() ) {
+    if (this.securityService.isCurrentUserSMPAdmin() || this.securityService.isCurrentUserSystemAdmin()) {
       let params: HttpParams = new HttpParams()
         .set('page', '-1')
         .set('pageSize', '-1');
 
       // return only smp and service group admins..
-      if (this.securityService.isCurrentUserSMPAdmin() ) {
-        params = params .set('roles', Role.SMP_ADMIN +","+Role.SERVICE_GROUP_ADMIN);
+      if (this.securityService.isCurrentUserSMPAdmin()) {
+        params = params.set('roles', Role.SMP_ADMIN + "," + Role.SERVICE_GROUP_ADMIN);
       }
 
-      // init users
-      this.userObserver = this.http.get<SearchTableResult>(SmpConstants.REST_USER, {params});
+      // retrieve user list
+      this.userObserver = this.http.get<SearchTableResult>(SmpConstants.REST_INTERNAL_USER_MANAGE, {params});
       let sub: Subscription = this.userObserver.subscribe((users: SearchTableResult) => {
         this.cachedServiceGroupOwnerList = users.serviceEntities.map(serviceEntity => {
           return {...serviceEntity}
 
         });
         sub.unsubscribe();
-      },(error:any) => {
+      }, (error: any) => {
         // check if unauthorized
         // just console try latter
         sub.unsubscribe();
-          console.log("Error occurred while loading user owners lookup [" + error + "]");
-        });
+        console.log("Error occurred while loading user owners lookup [" + error + "]");
+      });
     }
 
   }
 
   public refreshCertificateLookup() {
     // call only for authenticated users.
-    if ( this.securityService.isCurrentUserSystemAdmin() ) {
+    if (this.securityService.isCurrentUserSystemAdmin()) {
 
       // init users
-      this.certificateObserver = this.http.get<SearchTableResult>(SmpConstants.REST_KEYSTORE );
+      this.certificateObserver = this.http.get<SearchTableResult>(SmpConstants.REST_INTERNAL_KEYSTORE);
       this.certificateObserver.subscribe((certs: SearchTableResult) => {
         this.cachedCertificateList = certs.serviceEntities.map(serviceEntity => {
           return {...serviceEntity}
         });
         //update alias list
-        this.cachedCertificateAliasList =this.cachedCertificateList.map(cert => cert.alias);
-      },(error:any) => {
+        this.cachedCertificateAliasList = this.cachedCertificateList.map(cert => cert.alias);
+      }, (error: any) => {
         // check if unauthorized
         // just console try latter
         console.log("Error occurred while loading user owners lookup [" + error + "]");
@@ -141,16 +152,16 @@ export class GlobalLookups implements OnInit {
 
   public refreshTrustedCertificateLookup() {
     // call only for authenticated users.
-    if ( this.securityService.isCurrentUserSystemAdmin() ) {
+    if (this.securityService.isCurrentUserSystemAdmin()) {
 
       // init users
-      this.trustedCertificateObserver = this.http.get<SearchTableResult>(SmpConstants.REST_TRUSTSTORE );
+      this.trustedCertificateObserver = this.http.get<SearchTableResult>(SmpConstants.REST_INTERNAL_TRUSTSTORE);
       this.trustedCertificateObserver.subscribe((certs: SearchTableResult) => {
         this.cachedTrustedCertificateList = certs.serviceEntities.map(serviceEntity => {
           return {...serviceEntity}
 
         });
-      },(error:any) => {
+      }, (error: any) => {
         // check if unauthorized
         // just console try latter
         console.log("Error occurred while loading trusted certifcates lookup [" + error + "]");
diff --git a/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.css b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..6336193ff3f2c5a889890b25a7e4407b4f4382d0
--- /dev/null
+++ b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.css
@@ -0,0 +1,16 @@
+.password-panel .mat-form-field {
+  margin-bottom: 1.5em;
+  padding: 2px;
+}
+
+
+.alert {
+  padding: 20px;
+  color: white;
+  opacity: 1;
+  transition: opacity 0.6s;
+  margin-bottom: 15px;
+  z-index: 1000;
+  background-color: #f44336;
+}
+
diff --git a/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.html b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..1078ed25caaa65ab889584603fb8f3c16ea7339d
--- /dev/null
+++ b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.html
@@ -0,0 +1,72 @@
+<h2 mat-dialog-title>{{formTitle}}</h2>
+<mat-dialog-content style="width:500px">
+
+  <div *ngIf="message" [ngClass]="{ 'alert-message': message, 'alert-message-success': messageType === 'success', 'alert-message-error':messageType === 'error' }" id="alertmessage_id">
+    <span class="alert-message-close-button" (click)="clearAlert()">&times;</span>
+    {{message}}
+  </div>
+  <form [formGroup]="dialogForm">
+    <mat-card>
+      <mat-card-content fxLayout="column">
+        <mat-form-field style="width:100%">
+          <input matInput placeholder="User email" formControlName="email" id="em_id" readonly="true">
+        </mat-form-field>
+        <mat-form-field style="width:100%">
+          <input matInput placeholder="Username" formControlName="username" id="un_id" readonly="true">
+        </mat-form-field>
+      </mat-card-content>
+    </mat-card>
+    <mat-card class="password-panel">
+      <mat-card-content>
+        <mat-card-actions >
+          <button mat-raised-button color="primary" (click)="changeCurrentUserPassword()"
+                  [disabled]="!dialogForm.valid ">
+            <mat-icon>check_circle</mat-icon>
+            <span>Change password</span>
+          </button>
+        </mat-card-actions>
+        <mat-form-field style="width:100%">
+          <input matInput placeholder="Current Password" [type]="hideCurrPwdFiled ? 'password' : 'text'"
+                 formControlName="current-password" required id="cp_id">
+          <mat-icon matSuffix
+                    (click)="hideCurrPwdFiled = !hideCurrPwdFiled">{{hideCurrPwdFiled ? 'visibility_off' : 'visibility'}}</mat-icon>
+        </mat-form-field>
+
+        <mat-form-field style="width:100%">
+          <input matInput placeholder="New Password" [type]="hideNewPwdFiled ? 'password' : 'text'"
+                 formControlName="new-password" required id="np_id">
+          <mat-icon matSuffix
+                    (click)="hideNewPwdFiled = !hideNewPwdFiled">{{hideNewPwdFiled ? 'visibility_off' : 'visibility'}}</mat-icon>
+          <mat-error *ngIf="passwordError('new-password', 'required')">New password is required</mat-error>
+          <mat-error *ngIf="passwordError('new-password', 'equal')">New password must not be equal than old current
+            password!
+          </mat-error>
+          <mat-error *ngIf="passwordError('new-password', 'pattern')">{{passwordValidationMessage}}</mat-error>
+        </mat-form-field>
+
+        <mat-form-field style="width:100%">
+          <input matInput placeholder="Confirm New Password" [type]="hideConfPwdFiled ? 'password' : 'text'"
+                 formControlName="confirm-new-password" required id="cnp_id">
+          <mat-icon matSuffix
+                    (click)="hideConfPwdFiled = !hideConfPwdFiled">{{hideConfPwdFiled ? 'visibility_off' : 'visibility'}}</mat-icon>
+          <mat-error *ngIf="passwordError('confirm-new-password', 'equal')">Confirm valued does not match new password!
+          </mat-error>
+          <mat-error *ngIf="passwordError('confirm-new-password', 'required')">Confirm New password is required
+          </mat-error>
+        </mat-form-field>
+      </mat-card-content>
+    </mat-card>
+  </form>
+
+  <table class="buttonsRow" >
+    <tr>
+      <td>
+        <button mat-raised-button color="primary" mat-dialog-close>
+          <mat-icon>cancel</mat-icon>
+          <span>Close</span>
+        </button>
+      </td>
+    </tr>
+  </table>
+  <div class="required-fields">* required fields</div>
+</mat-dialog-content>
diff --git a/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.spec.ts b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d71a0fdc74e1e58fc014cb70720ef59668b23ced
--- /dev/null
+++ b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PasswordChangeDialogComponent } from './password-change-dialog.component';
+
+describe('PasswordChangeDialogComponent', () => {
+  let component: PasswordChangeDialogComponent;
+  let fixture: ComponentFixture<PasswordChangeDialogComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ PasswordChangeDialogComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PasswordChangeDialogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.ts b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8a3782954b4f39003e1ffc2cf98223e276c582bf
--- /dev/null
+++ b/smp-angular/src/app/common/password-change-dialog/password-change-dialog.component.ts
@@ -0,0 +1,113 @@
+import {Component, Inject} from '@angular/core';
+import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
+import {
+  AbstractControl,
+  FormBuilder,
+  FormControl,
+  FormGroup,
+  FormGroupDirective, NgForm,
+  ValidatorFn,
+  Validators
+} from "@angular/forms";
+import {User} from "../../security/user.model";
+import {GlobalLookups} from "../global-lookups";
+import {ErrorStateMatcher} from "@angular/material/core";
+import {UserDetailsService} from "../../user/user-details-dialog/user-details.service";
+import {CertificateRo} from "../../user/certificate-ro.model";
+import {AlertService} from "../../alert/alert.service";
+import {ErrorResponseRO} from "../error/error-model";
+
+@Component({
+  selector: 'smp-password-change-dialog',
+  templateUrl: './password-change-dialog.component.html',
+  styleUrls: ['./password-change-dialog.component.css']
+})
+export class PasswordChangeDialogComponent {
+
+  formTitle = "Change password dialog!";
+  dialogForm: FormGroup;
+  hideCurrPwdFiled: boolean = true;
+  hideNewPwdFiled: boolean = true;
+  hideConfPwdFiled: boolean = true;
+  current: User;
+  message: string;
+  messageType: string = "alert-error";
+
+  constructor(
+    public dialogRef: MatDialogRef<PasswordChangeDialogComponent>,
+    @Inject(MAT_DIALOG_DATA) public data: User,
+    private lookups: GlobalLookups,
+    private userDetailsService: UserDetailsService,
+    private alertService: AlertService,
+    private fb: FormBuilder
+  ) {
+    this.current = {...data}
+
+    let currentPasswdFormControl: FormControl = new FormControl({value: null, readonly: false}, [Validators.required]);
+    let newPasswdFormControl: FormControl = new FormControl({value: null, readonly: false},
+      [Validators.required, Validators.pattern(this.passwordValidationRegExp), equal(currentPasswdFormControl, false)]);
+    let confirmNewPasswdFormControl: FormControl = new FormControl({value: null, readonly: false},
+      [Validators.required, equal(newPasswdFormControl, true)]);
+
+    this.dialogForm = fb.group({
+      'email': new FormControl({value: null, readonly: true}, null),
+      'username': new FormControl({value: null, readonly: true}, null),
+      'current-password': currentPasswdFormControl,
+      'new-password': newPasswdFormControl,
+      'confirm-new-password': confirmNewPasswdFormControl
+    });
+
+    this.dialogForm.controls['email'].setValue(this.current.emailAddress);
+    this.dialogForm.controls['username'].setValue(this.current.username);
+    this.dialogForm.controls['current-password'].setValue('');
+    this.dialogForm.controls['new-password'].setValue('');
+    this.dialogForm.controls['confirm-new-password'].setValue('');
+  }
+
+  public passwordError = (controlName: string, errorName: string) => {
+    return this.dialogForm.controls[controlName].hasError(errorName);
+  }
+
+  get passwordValidationMessage() {
+    return this.lookups.cachedApplicationConfig?.passwordValidationRegExpMessage;
+  }
+
+  get passwordValidationRegExp() {
+    return this.lookups.cachedApplicationConfig?.passwordValidationRegExp;
+  }
+
+  changeCurrentUserPassword() {
+    this.clearAlert();
+
+    // update password
+    this.userDetailsService.changePassword(this.current.userId,
+      this.dialogForm.controls['new-password'].value,
+      this.dialogForm.controls['current-password'].value).subscribe((res: boolean) => {
+        this.showSuccessMessage("Password has been changed!")
+      },
+      (err) => {
+        this.showErrorMessage(err.error.errorDescription);
+      }
+    );
+  }
+  showSuccessMessage(value: string) {
+    this.message = value;
+    this.messageType = "success";
+  }
+
+  showErrorMessage(value: string) {
+    this.message = value;
+    this.messageType = "error";
+  }
+
+  clearAlert() {
+    this.message = null;
+    this.messageType = null;
+  }
+}
+
+export function equal(currentPasswdFormControl: FormControl, matchEqual: boolean): ValidatorFn {
+  return (control: AbstractControl): { [key: string]: any } | null =>
+    (matchEqual ? control.value === currentPasswdFormControl.value : control.value !== currentPasswdFormControl.value)
+      ? null : {error: control.value};
+}
diff --git a/smp-angular/src/app/common/search-table/search-table.component.ts b/smp-angular/src/app/common/search-table/search-table.component.ts
index cb045136f5352bea4b0a039e5e0249a01a7ed3f2..0f71a62d377aa2164d0b8a2cd6676383a0d56caf 100644
--- a/smp-angular/src/app/common/search-table/search-table.component.ts
+++ b/smp-angular/src/app/common/search-table/search-table.component.ts
@@ -38,7 +38,8 @@ export class SearchTableComponent implements OnInit {
   @Input() id: String = "";
   @Input() title: String = "";
   @Input() columnPicker: ColumnPicker;
-  @Input() url: string = '';
+  @Input() url: string = ''; // URL for query (and if manageUrl is null also for "managing")
+  @Input() manageUrl: string = ''; // (for "managing" the entities (add, update, remove) )
   @Input() searchTableController: SearchTableController;
   @Input() filter: any = {};
   @Input() showActionButtons: boolean = true;
@@ -294,7 +295,7 @@ export class SearchTableComponent implements OnInit {
           const modifiedRowEntities = this.rows.filter(el => el.status !== SearchTableEntityStatus.PERSISTED);
           // this.isBusy = true;
           this.showSpinner = true;
-          this.http.put(this.url, modifiedRowEntities).toPromise().then(res => {
+          this.http.put(this.managementUrl, modifiedRowEntities).toPromise().then(res => {
             this.showSpinner = false;
             // this.isBusy = false;
             // this.getUsers();
@@ -352,6 +353,10 @@ export class SearchTableComponent implements OnInit {
     return this.selected && this.selected.length == 1 && !this.selected[0].deleted;
   }
 
+  get managementUrl(): string {
+    return (this.manageUrl == null || this.manageUrl.length === 0)? this.url:this.manageUrl;
+  }
+
   get deleteButtonEnabled(): boolean {
     return this.selected && this.selected.length > 0 && !this.selected.every(el => el.deleted);
   }
diff --git a/smp-angular/src/app/domain/domain-controller.ts b/smp-angular/src/app/domain/domain-controller.ts
index af77488ee4a75e544144e349f605fe86d3e786f0..a01842f226040e83a17814deeef7d1f20594d9ef 100644
--- a/smp-angular/src/app/domain/domain-controller.ts
+++ b/smp-angular/src/app/domain/domain-controller.ts
@@ -54,7 +54,7 @@ export class DomainController implements SearchTableController {
 
   validateDeleteOperation(rows: Array<SearchTableEntity>){
     var deleteRowIds = rows.map(rows => rows.id);
-    return  this.http.post<SearchTableValidationResult>(SmpConstants.REST_DOMAIN_VALIDATE_DELETE, deleteRowIds);
+    return  this.http.post<SearchTableValidationResult>(SmpConstants.REST_INTERNAL_DOMAIN_VALIDATE_DELETE, deleteRowIds);
   }
 
   public newValidationResult(result: boolean, message: string): SearchTableValidationResult {
diff --git a/smp-angular/src/app/domain/domain.component.html b/smp-angular/src/app/domain/domain.component.html
index 040bbf05b8b4f6ba4936d986d1245a5be99cc5ea..fb41969834cd0ca0907838e05115b86769bb15e9 100644
--- a/smp-angular/src/app/domain/domain.component.html
+++ b/smp-angular/src/app/domain/domain.component.html
@@ -10,24 +10,16 @@
   [filter]="filter"
   [allowNewItems]="securityService.isCurrentUserSystemAdmin()"
   [allowDeleteItems]="securityService.isCurrentUserSystemAdmin()"
-
 >
 
-  <ng-template #domainCodeColumnTemplate let-row="row"  ngx-datatable-cell-template>
-    <span [class]='aliasCssForDomainCodeClass(row)'  [matTooltip]='getDomainConfigurationWarning(row)'  >{{row.domainCode}}</span>
-  </ng-template>
-
-  <ng-template #signKeyColumnTemplate let-row="row"  ngx-datatable-cell-template>
-    <span [class]='aliasCssClass(row.signatureKeyAlias, row)'>{{row.signatureKeyAlias}}</span>
+  <ng-template #domainCodeColumnTemplate let-row="row" let-value="value"  ngx-datatable-cell-template>
+    <span [class]='aliasCssForDomainCodeClass(row)'  [matTooltip]='getDomainConfigurationWarning(row)'  >{{value}}</span>
   </ng-template>
 
-  <ng-template #smlKeyColumnTemplate let-row="row" ngx-datatable-cell-template>
-    <span [class]='aliasCssClass(row.smlClientKeyAlias, row)'>{{row.smlClientKeyAlias}}</span>
+  <ng-template #certificateAliasTemplate let-row="row" let-value="value" ngx-datatable-cell-template>
+    <span [class]='aliasCssClass(value, row)'>{{value}}</span>
   </ng-template>
 
-
-
-
   <ng-template #additionalToolButtons >
     <span style="width: 2px;background-color: deepskyblue;">&nbsp;</span>
 
diff --git a/smp-angular/src/app/domain/domain.component.ts b/smp-angular/src/app/domain/domain.component.ts
index c38eae3540e43a335e232d487c55878ea9d2e20f..c675b32e801bce74583141a46295f38d205c745e 100644
--- a/smp-angular/src/app/domain/domain.component.ts
+++ b/smp-angular/src/app/domain/domain.component.ts
@@ -1,4 +1,4 @@
-import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
+import {AfterViewInit, Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
 import {ColumnPicker} from '../common/column-picker/column-picker.model';
 import {MatDialog, MatDialogRef} from '@angular/material/dialog';
 
@@ -23,17 +23,16 @@ import {SMLResult} from "./sml-result.model";
   templateUrl: './domain.component.html',
   styleUrls: ['./domain.component.css']
 })
-export class DomainComponent implements OnInit {
+export class DomainComponent implements AfterViewInit {
 
   @ViewChild('rowMetadataAction') rowMetadataAction: TemplateRef<any>;
-  @ViewChild('signKeyColumnTemplate') signKeyColumnTemplate: TemplateRef<any>;
-  @ViewChild('smlKeyColumnTemplate') smlKeyColumnTemplate: TemplateRef<any>;
+  @ViewChild('certificateAliasTemplate') certificateAliasColumn: TemplateRef<any>;
   @ViewChild('domainCodeColumnTemplate') domainCodeColumnTemplate: TemplateRef<any>;
   @ViewChild('rowActions') rowActions: TemplateRef<any>;
   @ViewChild('searchTable') searchTable: SearchTableComponent;
 
 
-  baseUrl = SmpConstants.REST_DOMAIN;
+  baseUrl = SmpConstants.REST_INTERNAL_DOMAIN_MANAGE;
   columnPicker: ColumnPicker = new ColumnPicker();
   domainController: DomainController;
   filter: any = {};
@@ -60,13 +59,14 @@ export class DomainComponent implements OnInit {
     }
   }
 
-  ngOnInit() {
+  ngAfterViewInit() {
     this.domainController = new DomainController(this.http, this.lookups, this.dialog);
 
     this.columnPicker.allColumns = [
       {
         name: 'Domain code',
         title: "Unique domain code.",
+        prop: 'domainCode',
         cellTemplate: this.domainCodeColumnTemplate,
         width: 250
 
@@ -80,7 +80,8 @@ export class DomainComponent implements OnInit {
       {
         name: 'Signature CertAlias',
         title: "Certificate for signing REST responses",
-        cellTemplate: this.signKeyColumnTemplate,
+        prop: 'signatureKeyAlias',
+        cellTemplate: this.certificateAliasColumn,
         width: 150
       },
 
@@ -92,7 +93,8 @@ export class DomainComponent implements OnInit {
       },
       {
         name: 'SML ClientCert Alias',
-        cellTemplate: this.smlKeyColumnTemplate,
+        prop: 'smlClientKeyAlias',
+        cellTemplate: this.certificateAliasColumn,
         width: 150
       },
       {
@@ -116,7 +118,6 @@ export class DomainComponent implements OnInit {
     if (alias) {
       return this.lookups.cachedCertificateAliasList.includes(alias);
     } else {
-
       return false;
     }
   }
diff --git a/smp-angular/src/app/domain/keystore.service.ts b/smp-angular/src/app/domain/keystore.service.ts
index 9c38ac6f00a4a4d26760cd85c813e53d355a0070..e0f9b41f4f23e3efa3c2f7da05cf00128e923100 100644
--- a/smp-angular/src/app/domain/keystore.service.ts
+++ b/smp-angular/src/app/domain/keystore.service.ts
@@ -25,7 +25,7 @@ export class KeystoreService {
     let passwordEncoded = encodeURIComponent(password);
 
     const currentUser: User = this.securityService.getCurrentUser();
-    return this.http.post<KeystoreResult>(`${SmpConstants.REST_KEYSTORE}/${currentUser.id}/upload/${keystoreType}/${passwordEncoded}`, selectedFile, {
+    return this.http.post<KeystoreResult>(`${SmpConstants.REST_INTERNAL_KEYSTORE}/${currentUser.userId}/upload/${keystoreType}/${passwordEncoded}`, selectedFile, {
       headers
     });
   }
@@ -36,6 +36,6 @@ export class KeystoreService {
     let certificateAliasEncoded = encodeURIComponent(certificateAlias);
 
     const currentUser: User = this.securityService.getCurrentUser();
-    return this.http.delete<KeystoreResult>(`${SmpConstants.REST_KEYSTORE}/${currentUser.id}/delete/${certificateAliasEncoded}`);
+    return this.http.delete<KeystoreResult>(`${SmpConstants.REST_INTERNAL_KEYSTORE}/${currentUser.userId}/delete/${certificateAliasEncoded}`);
   }
 }
diff --git a/smp-angular/src/app/domain/sml-integration.service.ts b/smp-angular/src/app/domain/sml-integration.service.ts
index 932ef1344b71d9d38235fff4a2940779181056ee..9aabf0071c684114a3a3186888f350761aa64dd7 100644
--- a/smp-angular/src/app/domain/sml-integration.service.ts
+++ b/smp-angular/src/app/domain/sml-integration.service.ts
@@ -18,11 +18,11 @@ export class SmlIntegrationService {
 
   registerDomainToSML$(domainCode): Observable<SMLResult> {
     const currentUser: User = this.securityService.getCurrentUser();
-    return this.http.post<SMLResult>(`${SmpConstants.REST_DOMAIN}/${currentUser.id}/smlregister/${domainCode}`, {});
+    return this.http.put<SMLResult>(`${SmpConstants.REST_INTERNAL_DOMAIN_MANAGE}/${currentUser.userId}/sml-register/${domainCode}`, {});
   }
 
   unregisterDomainToSML$(domainCode): Observable<SMLResult> {
     const currentUser: User = this.securityService.getCurrentUser();
-    return this.http.post<SMLResult>(`${SmpConstants.REST_DOMAIN}/${currentUser.id}/smlunregister/${domainCode}`, {});
+    return this.http.put<SMLResult>(`${SmpConstants.REST_INTERNAL_DOMAIN_MANAGE}/${currentUser.userId}/sml-unregister/${domainCode}`, {});
   }
 }
diff --git a/smp-angular/src/app/login/login.component.ts b/smp-angular/src/app/login/login.component.ts
index ddcfc7da64ef95100c6e32b666a596ff91d8f250..1fc24581a74e5bef5162b4fce29cefcf9b71ca73 100644
--- a/smp-angular/src/app/login/login.component.ts
+++ b/smp-angular/src/app/login/login.component.ts
@@ -43,6 +43,7 @@ export class LoginComponent implements OnInit, OnDestroy {
         } else {
           this.router.navigate([this.returnUrl]);
         }
+        this.lookups.refreshApplicationConfiguration();
       });
 
     this.securityEventService.onLoginErrorEvent().subscribe(
diff --git a/smp-angular/src/app/security/security.service.ts b/smp-angular/src/app/security/security.service.ts
index ee767814760ff55bc4da9fc95b0bde97c1726e1d..6bfe4e5e66cc76ed3e563882e258d4eddd776500 100644
--- a/smp-angular/src/app/security/security.service.ts
+++ b/smp-angular/src/app/security/security.service.ts
@@ -24,7 +24,7 @@ export class SecurityService {
 
   login(username: string, password: string) {
     let headers: HttpHeaders = new HttpHeaders({'Content-Type': 'application/json'});
-    return this.http.post<string>(SmpConstants.REST_SECURITY_AUTHENTICATION,
+    return this.http.post<string>(SmpConstants.REST_PUBLIC_SECURITY_AUTHENTICATION,
       JSON.stringify({
         username: username,
         password: password
@@ -50,7 +50,7 @@ export class SecurityService {
   }
 
   logout() {
-    this.http.delete(SmpConstants.REST_SECURITY_AUTHENTICATION).subscribe((res: Response) => {
+    this.http.delete(SmpConstants.REST_PUBLIC_SECURITY_AUTHENTICATION).subscribe((res: Response) => {
         this.clearLocalStorage();
         this.securityEventService.notifyLogoutSuccessEvent(res);
       },
@@ -65,7 +65,7 @@ export class SecurityService {
 
   private getCurrentUsernameFromServer(): Observable<string> {
     let subject = new ReplaySubject<string>();
-    this.http.get<string>(SmpConstants.REST_SECURITY_USER)
+    this.http.get<string>(SmpConstants.REST_PUBLIC_SECURITY_USER)
       .subscribe((res: string) => {
         subject.next(res);
       }, (error: any) => {
diff --git a/smp-angular/src/app/security/user.model.ts b/smp-angular/src/app/security/user.model.ts
index 929b76b6d4dfef350222ebd9a0030d61ab9bfce3..40fe572ea159c59dea05c1b3223bec2b59a76c43 100644
--- a/smp-angular/src/app/security/user.model.ts
+++ b/smp-angular/src/app/security/user.model.ts
@@ -1,9 +1,11 @@
 import {Authority} from "./authority.model";
 
 export interface User {
-  id: number;
+  userId: string;
+  emailAddress: string;
   username: string;
   accessTokenId?: string;
+  accessTokenExpireOn?: Date;
   authorities: Array<Authority>;
   defaultPasswordUsed: boolean;
 }
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.css b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.css
index 5e47b4070b9aa525e16025657e4f85929f57ab0d..0545fd5b2564bd76936b476fca4c36dbf1a50542 100644
--- a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.css
+++ b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.css
@@ -12,3 +12,11 @@
   font-weight: bold;
   color:#c6c639;
 }
+
+
+.list-form-item  .mat-form-field-wrapper {
+  margin-bottom: -1.25em;
+  padding: 0;
+  margin: 0;
+}
+
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
index e508111f3e6e154b1a4f7a1dae0ee6c4eef19bd4..e94bdf35d04587be74db60faaf75b1f6e0011ba1 100644
--- a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
+++ b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.html
@@ -106,10 +106,8 @@
                                    style="height: 200px;  overflow-y: scroll; overflow-x: auto;">
                 <mat-list-option *ngFor="let domain of lookups.cachedDomainList" [value]='domain'
                                  style="max-width: 450px !important; word-wrap: break-word !important; height: auto; min-height: 30px !important;"
-                                 [disabled]="!isDomainProperlyConfigured(domain)"
-                                 [matTooltip]="getDomainConfigurationWarning(domain)" >
-                  <span [class]="getDomainCodeClass(domain)">
-                  {{domain.domainCode}} ({{domain.smlSubdomain}})</span>
+                                  >
+                  <label [class]="getDomainCodeClass(domain)" [title]="getDomainConfigurationWarning(domain)">{{domain.domainCode}} ({{domain.smlSubdomain}})</label>
                 </mat-list-option>
               </mat-selection-list>
             </mat-expansion-panel>
@@ -207,3 +205,8 @@
   </div>
 </mat-dialog-actions>
 <div style="text-align: right; font-size: 70%">* required fields</div>
+
+<ng-template mat-tab-label>
+  <label  class="labelHeading" matTooltip="See Pictures"matTooltipClass="example-tooltip-red1">Bounced Users
+  </label>
+</ng-template>
diff --git a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
index 52300ece25c14c7d7c346eceb999888a026c6d84..da55d19e1a11ca74aa5b9da7f66acef9f61fa431 100644
--- a/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
+++ b/smp-angular/src/app/service-group-edit/service-group-details-dialog/service-group-details-dialog.component.ts
@@ -169,6 +169,7 @@ export class ServiceGroupDetailsDialogComponent implements OnInit {
     }
     return msg;
   }
+
   isDomainProperlyConfigured(domain: DomainRo){
     return !this.getDomainConfigurationWarning(domain);
   }
diff --git a/smp-angular/src/app/service-group-edit/service-group-edit.component.ts b/smp-angular/src/app/service-group-edit/service-group-edit.component.ts
index 5de7d4012ced51abfa456d47c412df6ffad2af21..62cd9aaa0b525e2da16f5255430db1862321f876 100644
--- a/smp-angular/src/app/service-group-edit/service-group-edit.component.ts
+++ b/smp-angular/src/app/service-group-edit/service-group-edit.component.ts
@@ -25,7 +25,7 @@ export class ServiceGroupEditComponent implements OnInit {
   columnPicker: ColumnPicker = new ColumnPicker();
   serviceGroupEditController: ServiceGroupEditController;
   filter: any = {};
-  baseUrl: string = SmpConstants.REST_EDIT;
+  baseUrl: string = SmpConstants.REST_PUBLIC_SERVICE_GROUP;
   contextPath: string = location.pathname.substring(0, location.pathname.length - 3); // remove /ui s
 
   constructor(public securityService: SecurityService,
diff --git a/smp-angular/src/app/service-group-search/service-group-search.component.html b/smp-angular/src/app/service-group-search/service-group-search.component.html
index b8f070230b26a2520407fcdc7904c74b64198032..ffbb6dfbd6dcddc2d912076b1abd8dd635690f7a 100644
--- a/smp-angular/src/app/service-group-search/service-group-search.component.html
+++ b/smp-angular/src/app/service-group-search/service-group-search.component.html
@@ -58,7 +58,7 @@
     <div *ngIf="row.serviceMetadata.length !== 0">
       <ngx-datatable
         class='inner-table material striped'
-        [loadingIndicator]="loading"
+        [loadingIndicator]="'Loading ...'"
         [rows]='row.serviceMetadata'
         [columnMode]='"force"'
         [headerHeight]='50'
diff --git a/smp-angular/src/app/service-group-search/service-group-search.component.ts b/smp-angular/src/app/service-group-search/service-group-search.component.ts
index 031900db4a695f928de0b40b60feec459265e146..a64932caac98c3656e57e6672cf28ca1a719b238 100644
--- a/smp-angular/src/app/service-group-search/service-group-search.component.ts
+++ b/smp-angular/src/app/service-group-search/service-group-search.component.ts
@@ -23,7 +23,7 @@ export class ServiceGroupSearchComponent implements OnInit {
   serviceGroupSearchController: ServiceGroupSearchController;
   filter: any = {};
   contextPath: string = location.pathname.substring(0, location.pathname.length - 3); // remove /ui s
-  baseUrl: string = SmpConstants.REST_SEARCH;
+  baseUrl: string = SmpConstants.REST_PUBLIC_SEARCH_SERVICE_GROUP;
 
   constructor(protected lookups: GlobalLookups, protected http: HttpClient, protected alertService: AlertService, public dialog: MatDialog) {
 
diff --git a/smp-angular/src/app/smp.constants.ts b/smp-angular/src/app/smp.constants.ts
index 0be8f1cb327450b114bb67b9a0ecd57f5fc07bd1..0323792a8a815cd796f74fe374a3d4a87ef32f45 100644
--- a/smp-angular/src/app/smp.constants.ts
+++ b/smp-angular/src/app/smp.constants.ts
@@ -1,25 +1,45 @@
 export class SmpConstants {
+  //------------------------------
+  // public endpoints
+  public static readonly REST_PUBLIC = 'public/rest/';
+  public static readonly REST_INTERNAL = 'internal/rest/';
+  public static readonly REST_PUBLIC_SEARCH_SERVICE_GROUP = SmpConstants.REST_PUBLIC + 'search';
+  public static readonly REST_PUBLIC_DOMAIN_SEARCH = SmpConstants.REST_PUBLIC + 'domain';
+  public static readonly REST_PUBLIC_APPLICATION_INFO = SmpConstants.REST_PUBLIC + 'application/info';
+  // user public services
+  public static readonly REST_PUBLIC_USER = SmpConstants.REST_PUBLIC + 'user';
+  public static readonly REST_PUBLIC_USER_UPDATE = SmpConstants.REST_PUBLIC_USER + '/{user-id}/';
+  public static readonly REST_PUBLIC_USER_CERT_VALIDATE = SmpConstants.REST_PUBLIC_USER_UPDATE + 'validate-certificate';
+  public static readonly REST_PUBLIC_USER_GENERATE_ACCESS_TOKEN = SmpConstants.REST_PUBLIC_USER_UPDATE + 'generate-access-token';
+  public static readonly REST_PUBLIC_USER_CHANGE_PASSWORD = SmpConstants.REST_PUBLIC_USER_UPDATE + 'change-password';
+  public static readonly REST_PUBLIC_TRUSTSTORE = SmpConstants.REST_PUBLIC + 'truststore/{user-id}/';
+  public static readonly REST_PUBLIC_TRUSTSTORE_VALIDATE_CERT = SmpConstants.REST_PUBLIC_TRUSTSTORE + 'validate-certificate';
+  // public authentication services
+  public static readonly REST_PUBLIC_SECURITY_AUTHENTICATION = SmpConstants.REST_PUBLIC + 'security/authentication';
+  public static readonly REST_PUBLIC_SECURITY_USER = SmpConstants.REST_PUBLIC + 'security/user';
 
-  public static readonly REST_DOMAIN = 'rest/domain';
-  public static readonly REST_USER = 'rest/user';
-  public static readonly REST_SEARCH = 'rest/search';
-  public static readonly REST_EDIT = 'rest/servicegroup';
-  public static readonly REST_METADATA = 'rest/servicemetadata';
-  public static readonly REST_SECURITY_AUTHENTICATION = 'rest/security/authentication';
-  public static readonly REST_SECURITY_CAS_AUTHENTICATION = 'rest/security/cas';
-
-  public static readonly REST_SECURITY_USER = 'rest/security/user';
-  public static readonly REST_APPLICATION = 'rest/application/info';
-  public static readonly REST_CONFIG = 'rest/application/config';
-  public static readonly REST_KEYSTORE = 'rest/keystore';
-  public static readonly REST_TRUSTSTORE = 'rest/truststore';
-
-  public static readonly REST_USER_VALIDATE_DELETE = `${SmpConstants.REST_USER}/validateDelete`;
-  public static readonly REST_DOMAIN_VALIDATE_DELETE = `${SmpConstants.REST_DOMAIN}/validateDelete`;
-  public static readonly REST_SERVICE_GROUP_EXTENSION = `${SmpConstants.REST_EDIT}/extension`;
+  public static readonly REST_PUBLIC_SERVICE_GROUP = SmpConstants.REST_PUBLIC + 'service-group';
+  public static readonly REST_SERVICE_GROUP_EXTENSION = `${SmpConstants.REST_PUBLIC_SERVICE_GROUP}/extension`;
   public static readonly REST_SERVICE_GROUP_EXTENSION_VALIDATE = `${SmpConstants.REST_SERVICE_GROUP_EXTENSION}/validate`;
   public static readonly REST_SERVICE_GROUP_EXTENSION_FORMAT = `${SmpConstants.REST_SERVICE_GROUP_EXTENSION}/format`;
+
+  public static readonly REST_METADATA = SmpConstants.REST_PUBLIC +'service-metadata';
   public static readonly REST_METADATA_VALIDATE = `${SmpConstants.REST_METADATA}/validate`;
 
 
+  //------------------------------
+  // internal endpoints
+  public static readonly REST_INTERNAL_DOMAIN_MANAGE = SmpConstants.REST_INTERNAL + 'domain';
+  public static readonly REST_INTERNAL_DOMAIN_VALIDATE_DELETE = SmpConstants.REST_INTERNAL_DOMAIN_MANAGE + '/validate-delete';
+  public static readonly REST_INTERNAL_USER_MANAGE = SmpConstants.REST_INTERNAL + 'user';
+  public static readonly REST_INTERNAL_USER_VALIDATE_DELETE = `${SmpConstants.REST_INTERNAL_USER_MANAGE}/validate-delete`;
+  public static readonly REST_INTERNAL_APPLICATION_CONFIG = SmpConstants.REST_INTERNAL + 'application/config';
+  public static readonly REST_INTERNAL_KEYSTORE = SmpConstants.REST_INTERNAL + 'keystore';
+  public static readonly REST_INTERNAL_TRUSTSTORE = SmpConstants.REST_INTERNAL + 'truststore';
+
+
+
+
+
+
 }
diff --git a/smp-angular/src/app/user/certificate.service.ts b/smp-angular/src/app/user/certificate.service.ts
index 41fa7ecca837839fb1d34971eab2813654b9fb6d..f1bf5be8dbf3d8e3a0366718553881b8bf669892 100644
--- a/smp-angular/src/app/user/certificate.service.ts
+++ b/smp-angular/src/app/user/certificate.service.ts
@@ -24,6 +24,19 @@ export class CertificateService {
       .set("Content-Type", "application/octet-stream");
 
     const currentUser: User = this.securityService.getCurrentUser();
-    return this.http.post<CertificateRo>(`${SmpConstants.REST_USER}/${currentUser.id}/certdata`, payload, {headers});
+    return this.http.post<CertificateRo>(SmpConstants.REST_PUBLIC_TRUSTSTORE_VALIDATE_CERT.replace('{user-id}', currentUser.userId+""), payload, {headers});
+  }
+
+  validateCertificate(payload): Observable<CertificateRo> {
+    // The user identifier below belongs to the currently logged in user and it may or may not be the same as the
+    // identifier of the user being modified (e.g. a normal user editing his own details vs. a system administrator
+    // adding or editing another user)
+
+    // upload file as binary file
+    const headers = new HttpHeaders()
+      .set("Content-Type", "application/octet-stream");
+
+    const currentUser: User = this.securityService.getCurrentUser();
+    return this.http.post<CertificateRo>(SmpConstants.REST_PUBLIC_TRUSTSTORE_VALIDATE_CERT.replace('{user-id}', currentUser.userId+""), payload, {headers});
   }
 }
diff --git a/smp-angular/src/app/user/truststore.service.ts b/smp-angular/src/app/user/truststore.service.ts
index 3a76d31b318eca1c9a9fd79a7465e378843aca9b..cd43eec0115b735cca749caa94b061d621ab14ca 100644
--- a/smp-angular/src/app/user/truststore.service.ts
+++ b/smp-angular/src/app/user/truststore.service.ts
@@ -26,7 +26,7 @@ export class TruststoreService {
       .set("Content-Type", "application/octet-stream");
 
     const currentUser: User = this.securityService.getCurrentUser();
-    return this.http.post<CertificateRo>(`${SmpConstants.REST_TRUSTSTORE}/${currentUser.id}/certdata`, payload, {headers});
+    return this.http.post<CertificateRo>(`${SmpConstants.REST_INTERNAL_TRUSTSTORE}/${currentUser.userId}/validate-certificate`, payload, {headers});
   }
 
   deleteCertificateFromKeystore$(certificateAlias): Observable<TruststoreResult> {
@@ -35,6 +35,6 @@ export class TruststoreService {
     let certificateAliasEncoded = encodeURIComponent(certificateAlias);
 
     const currentUser: User = this.securityService.getCurrentUser();
-    return this.http.delete<TruststoreResult>(`${SmpConstants.REST_TRUSTSTORE}/${currentUser.id}/delete/${certificateAliasEncoded}`);
+    return this.http.delete<TruststoreResult>(`${SmpConstants.REST_INTERNAL_TRUSTSTORE}/${currentUser.userId}/delete/${certificateAliasEncoded}`);
   }
 }
diff --git a/smp-angular/src/app/user/user-controller.ts b/smp-angular/src/app/user/user-controller.ts
index 0d0002a18dbc7c703775124c78bf170ed13d6474..91e693ea17980ccec877abd0aa52ad0c9fade01a 100644
--- a/smp-angular/src/app/user/user-controller.ts
+++ b/smp-angular/src/app/user/user-controller.ts
@@ -9,6 +9,8 @@ import {SearchTableValidationResult} from "../common/search-table/search-table-v
 import {SmpConstants} from "../smp.constants";
 import {HttpClient} from "@angular/common/http";
 import {CertificateRo} from "./certificate-ro.model";
+import {PasswordChangeDialogComponent} from "../common/password-change-dialog/password-change-dialog.component";
+import {AccessTokenGenerationDialogComponent} from "../common/access-token-generation-dialog/access-token-generation-dialog.component";
 
 export class UserController implements SearchTableController {
 
@@ -40,6 +42,14 @@ export class UserController implements SearchTableController {
     return this.dialog.open(UserDetailsDialogComponent, this.convertWithMode(config));
   }
 
+  public changePasswordDialog(config?: MatDialogConfig): MatDialogRef<PasswordChangeDialogComponent> {
+    return this.dialog.open(PasswordChangeDialogComponent, this.convertWithMode(config));
+  }
+
+  public generateAccessTokenDialog(config?: MatDialogConfig): MatDialogRef<AccessTokenGenerationDialogComponent> {
+    return this.dialog.open(AccessTokenGenerationDialogComponent, this.convertWithMode(config));
+  }
+
   private convertWithMode(config) {
     return (config && config.data)
       ? {
@@ -71,7 +81,7 @@ export class UserController implements SearchTableController {
 
   validateDeleteOperation(rows: Array<SearchTableEntity>) {
     var deleteRowIds = rows.map(rows => rows.id);
-    return this.http.post<SearchTableValidationResult>(SmpConstants.REST_USER_VALIDATE_DELETE, deleteRowIds);
+    return this.http.post<SearchTableValidationResult>(SmpConstants.REST_INTERNAL_USER_VALIDATE_DELETE, deleteRowIds);
   }
 
   public newValidationResult(lst: Array<number>): SearchTableValidationResult {
diff --git a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
index 6deed874c2f6c0b0824d0742ddcd611b95f6e899..cee2655804740b3bb1c9fd0805cc08b33a105995 100644
--- a/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
+++ b/smp-angular/src/app/user/user-details-dialog/user-details-dialog.component.ts
@@ -23,7 +23,7 @@ import {Observable, of} from "rxjs";
 import {catchError, map} from "rxjs/operators";
 import {UserDetailsService} from "./user-details.service";
 import {MatSlideToggleChange} from "@angular/material/slide-toggle";
-import {AccessTokenRo} from "../access-token-ro.model";
+import {AccessTokenRo} from "../../common/access-token-generation-dialog/access-token-ro.model";
 
 @Component({
   selector: 'user-details-dialog',
@@ -41,7 +41,7 @@ export class UserDetailsDialogComponent {
 
   mode: UserDetailsDialogMode;
   editMode: boolean;
-  userId: number;
+  userId: string;
   userRoles = [];
   certificateValidationMessage: string = null;
   isCertificateInvalid: boolean = true;
@@ -50,6 +50,7 @@ export class UserDetailsDialogComponent {
   current: UserRo;
   tempStoreForCertificate: CertificateRo = this.newCertificateRo();
   tempStoreForUser: UserRo = this.newUserRo();
+  newCertFile:File=null;
 
   private passwordConfirmationValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
     const userToggle = control.get('userToggle');
@@ -86,25 +87,7 @@ export class UserDetailsDialogComponent {
     && listIds.includes(certificateId.value) && this.current.certificate && certificateId.value !== this.current.certificate.certificateId ? {certificateIdExists: true} : null;
   };
 
-  private asyncPasswordValidator: AsyncValidatorFn = (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
-    if (this.isPreferencesMode()) {
-      const userToggle = control.get('userToggle');
-      const passwordToggle = control.get('passwordToggle');
-      const password = control.get('password');
-      const confirmation = control.get('confirmation');
-
-      if (userToggle && passwordToggle && password
-        && this.userId && userToggle.value && passwordToggle.value && password.value) {
-        return this.userDetailsService.isSamePreviousPasswordUsed$(this.userId, password.value).pipe(
-          map(previousPasswordUsed => previousPasswordUsed ? {previousPasswordUsed: true} : null),
-          catchError(() => {
-            this.alertService.error("Error occurred while validating the password against the previously chosen one!");
-            return of(null);
-          }));
-      }
-    }
-    return of(null);
-  };
+
 
   notInList(list: string[]) {
     return (c: AbstractControl): { [key: string]: any } => {
@@ -125,7 +108,7 @@ export class UserDetailsDialogComponent {
               @Inject(MAT_DIALOG_DATA) public data: any,
               private fb: FormBuilder) {
     this.mode = data.mode;
-    this.userId = data.row && data.row.id;
+    this.userId = data.row && data.row.userId;
     this.editMode = this.mode !== UserDetailsDialogMode.NEW_MODE;
 
     this.current = this.editMode
@@ -195,8 +178,7 @@ export class UserDetailsDialogComponent {
         this.atLeastOneToggleCheckedValidator,
         this.certificateValidator,
         this.certificateExistValidator,
-      ],
-      asyncValidator: this.asyncPasswordValidator,
+      ]
     });
     // bind values to form! not property
     this.userForm.controls['active'].setValue(this.current.active);
@@ -233,6 +215,7 @@ export class UserDetailsDialogComponent {
   }
 
   regenerateAccessToken() {
+    /*
     let accessTokenPromise: Promise<AccessTokenRo> = this.userDetailsService.regenerateAccessToken(this.userId, "AccessPassword");
     accessTokenPromise.then(response => {
       this.alertService.success("Token with\n id: " + response.identifier + " and\nvalue: " + response.value + " was generated!")
@@ -240,12 +223,13 @@ export class UserDetailsDialogComponent {
         'accessTokenId': response.identifier})
     }, err => {
       this.alertService.error("Failed to generated access token. Please try again. If this happens again please contact Administrator!")
-    });
+    });*/
   }
 
   uploadCertificate(event) {
+    this.newCertFile=null;
     const file = event.target.files[0];
-    this.certificateService.uploadCertificate$(file).subscribe((res: CertificateRo) => {
+    this.certificateService.validateCertificate(file).subscribe((res: CertificateRo) => {
         if (res && res.certificateId) {
           this.userForm.patchValue({
             'subject': res.subject,
@@ -260,7 +244,7 @@ export class UserDetailsDialogComponent {
           });
           this.certificateValidationMessage = res.invalidReason;
           this.isCertificateInvalid = res.invalid;
-
+          this.newCertFile=file;
         } else {
           this.alertService.exception("Error occurred while reading certificate.", "Check if uploaded file has valid certificate type.", false);
         }
diff --git a/smp-angular/src/app/user/user-details-dialog/user-details.service.ts b/smp-angular/src/app/user/user-details-dialog/user-details.service.ts
index edc1db69c0339ddbbf34343bf45614fa29d637e7..9de63ebdf78fea685a6b5cd5fbca1e827b4ff63b 100644
--- a/smp-angular/src/app/user/user-details-dialog/user-details.service.ts
+++ b/smp-angular/src/app/user/user-details-dialog/user-details.service.ts
@@ -1,9 +1,8 @@
 import {Injectable} from "@angular/core";
 import {HttpClient} from "@angular/common/http";
-import {catchError, map} from "rxjs/operators";
 import {SmpConstants} from "../../smp.constants";
 import {Observable} from "rxjs";
-import {AccessTokenRo} from "../access-token-ro.model";
+import {AccessTokenRo} from "../../common/access-token-generation-dialog/access-token-ro.model";
 import {AlertService} from "../../alert/alert.service";
 
 @Injectable()
@@ -12,14 +11,28 @@ export class UserDetailsService {
   constructor(
     private http: HttpClient,
     private alertService: AlertService,
-  ) { }
-
-  isSamePreviousPasswordUsed$(userId: number, password: string): Observable<boolean> {
-    return this.http.post<boolean>(`${SmpConstants.REST_USER}/${userId}/samePreviousPasswordUsed`, password);
+  ) {
   }
 
-  regenerateAccessToken(userId: number, password: string):Promise<AccessTokenRo> {
-    return this.http.post<AccessTokenRo>(`${SmpConstants.REST_USER}/${userId}/generate-access-token`,password).toPromise()
+  /**
+   * Submits password to validate password
+   * @param userId
+   * @param password
+   */
+  changePassword(userId: string, newPassword: string, currentPassword: string): Observable<boolean> {
+    return this.http.put<boolean>(SmpConstants.REST_PUBLIC_USER_CHANGE_PASSWORD.replace('{user-id}', userId),
+      {
+          currentPassword:currentPassword,
+          newPassword:newPassword
+      });
+  }
 
+  /**
+   * Submit request to regenerated request token!
+   * @param userId
+   * @param password - password to authenticate user before regenerating the access token.
+   */
+  regenerateAccessToken(userId: string, password: string): Observable<AccessTokenRo> {
+    return this.http.post<AccessTokenRo>(SmpConstants.REST_PUBLIC_USER_GENERATE_ACCESS_TOKEN.replace('{user-id}', userId), password)
   }
 }
diff --git a/smp-angular/src/app/user/user.component.html b/smp-angular/src/app/user/user.component.html
index 98b091f2de366567ffee1b76b10b8844f9de7a2d..b44ede3e20d21b8a58a023e624533e8c8d8e5e89 100644
--- a/smp-angular/src/app/user/user.component.html
+++ b/smp-angular/src/app/user/user.component.html
@@ -3,7 +3,7 @@
   page_id="user_id"
   [title]="'Users'"
   [columnPicker]="columnPicker"
-  [url]="'rest/user'"
+  [url]="baseUrl"
   [additionalToolButtons]="additionalToolButtons"
   [searchTableController]="userController"
   [showSearchPanel]="false"
@@ -14,10 +14,8 @@
 
   <ng-template #roleCellTemplate let-value="value" ngx-datatable-cell-template>{{getRoleLabel(value)}}</ng-template>
 
-  <ng-template #certificateTemplate let-row="row"  ngx-datatable-cell-template>
-    <span [class]='certCssClass(row)'
-          matTooltip="{{row.certificate?.invalidReason}}"
-    >{{row.certificate?.certificateId}}</span>
+  <ng-template #certificateTemplate let-row="row" let-value="value" ngx-datatable-cell-template>
+    <span [class]='certCssClass(row)' matTooltip="{{value?.invalidReason}}">{{value?.certificateId}}</span>
   </ng-template>
 
   <ng-template #additionalToolButtons >
diff --git a/smp-angular/src/app/user/user.component.ts b/smp-angular/src/app/user/user.component.ts
index 7a70e024b08d95d4aa574357cae703205530d9f2..fed30e362ace126b99c5a0495d7244d704d8c1a7 100644
--- a/smp-angular/src/app/user/user.component.ts
+++ b/smp-angular/src/app/user/user.component.ts
@@ -1,4 +1,4 @@
-import {Component, OnInit, TemplateRef, ViewChild} from '@angular/core';
+import {AfterViewInit, Component, TemplateRef, ViewChild} from '@angular/core';
 import {ColumnPicker} from '../common/column-picker/column-picker.model';
 import {MatDialog, MatDialogRef} from '@angular/material/dialog';
 import {AlertService} from '../alert/alert.service';
@@ -9,12 +9,13 @@ import {SecurityService} from "../security/security.service";
 import {GlobalLookups} from "../common/global-lookups";
 import {TruststoreEditDialogComponent} from "./truststore-edit-dialog/truststore-edit-dialog.component";
 import {SearchTableEntityStatus} from "../common/search-table/search-table-entity-status.model";
+import {SmpConstants} from "../smp.constants";
 
 @Component({
   templateUrl:'./user.component.html',
   styleUrls: ['./user.component.css']
 })
-export class UserComponent implements OnInit {
+export class UserComponent implements AfterViewInit {
 
   @ViewChild('rowMetadataAction') rowMetadataAction: TemplateRef<any>;
   @ViewChild('rowExtensionAction') rowExtensionAction: TemplateRef<any>;
@@ -25,6 +26,7 @@ export class UserComponent implements OnInit {
   columnPicker: ColumnPicker = new ColumnPicker();
   userController: UserController;
   filter: any = {};
+  baseUrl:string=SmpConstants.REST_INTERNAL_USER_MANAGE;
 
   constructor(private lookups: GlobalLookups,
               public securityService: SecurityService,
@@ -33,7 +35,7 @@ export class UserComponent implements OnInit {
               public dialog: MatDialog) {
   }
 
-  ngOnInit() {
+  ngAfterViewInit() {
     this.userController = new UserController(this.http, this.lookups, this.dialog);
 
     this.columnPicker.allColumns = [
@@ -44,6 +46,7 @@ export class UserComponent implements OnInit {
       },
       {
         name: 'Certificate',
+        prop: 'certificate',
         cellTemplate: this.certificateTemplate,
         canAutoResize: true
       },
diff --git a/smp-angular/src/app/user/user.service.ts b/smp-angular/src/app/user/user.service.ts
index 5e06900c18f995cfca807f8c9cfd2e91c4b3a0e5..8ddd4d0743ac75cd8d6b84741ce5c3b14acedcff 100644
--- a/smp-angular/src/app/user/user.service.ts
+++ b/smp-angular/src/app/user/user.service.ts
@@ -6,7 +6,7 @@ import {SmpConstants} from "../smp.constants";
 import {User} from "../security/user.model";
 import {AlertService} from "../alert/alert.service";
 import {SecurityService} from "../security/security.service";
-import {AccessTokenRo} from "./access-token-ro.model";
+import {AccessTokenRo} from "../common/access-token-generation-dialog/access-token-ro.model";
 
 @Injectable()
 export class UserService {
@@ -18,7 +18,7 @@ export class UserService {
   ) { }
 
   updateUser(user: User) {
-    this.http.put<string>(`${SmpConstants.REST_USER}/${user.id}`, user).subscribe(response => {
+    this.http.put<string>(SmpConstants.REST_PUBLIC_USER_UPDATE.replace('{user-id}', user.userId), user).subscribe(response => {
       this.securityService.updateUserDetails(response);
       this.alertService.success('The operation \'update user\' completed successfully.');
     }, err => {
diff --git a/smp-angular/src/styles.css b/smp-angular/src/styles.css
index 769cbaba2f19a919e5f0834bad01bf281b887797..a8c0d75e9bc5dd41172cd2850a45840b1cebe619 100644
--- a/smp-angular/src/styles.css
+++ b/smp-angular/src/styles.css
@@ -74,6 +74,8 @@ ngx-datatable span:before {
   word-wrap: break-word;
 }
 .buttonsRow {
+  display: flex;
+  justify-content: flex-end;
   width: 100%;
   margin: 2px;
   padding: 5px;
@@ -325,3 +327,29 @@ mat-card {
   border: 1px solid rgba(0, 0, 0, 0.12);
 }
 
+.alert-message {
+  padding: 20px;
+  color: white;
+  opacity: 1;
+  transition: opacity 0.6s;
+  margin-bottom: 15px;
+  z-index: 1000;
+}
+.alert-message-error {background-color: #f44336;}
+.alert-message-success {background-color: #4CAF50;}
+
+.alert-message-close-button {
+  margin-left: 15px;
+  padding: 4px;
+  color: white;
+  font-weight: bold;
+  float: right;
+  font-size: 24px;
+  line-height: 24px;
+  cursor: pointer;
+  transition: 0.3s;
+}
+
+.alert-message-close-button:hover {
+  color: black;
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationToken.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationToken.java
similarity index 67%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationToken.java
rename to smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationToken.java
index f7b7bc016a500ce16237bd38b97b500804772592..f34588bdbe368e8b0d81d259439494165bbc16cd 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationToken.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationToken.java
@@ -1,6 +1,9 @@
 package eu.europa.ec.edelivery.smp.auth;
 
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.utils.SecurityUtils;
 import org.springframework.security.authentication.AbstractAuthenticationToken;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.GrantedAuthority;
@@ -9,8 +12,11 @@ import java.util.Collection;
 import java.util.Objects;
 
 public class SMPAuthenticationToken extends UsernamePasswordAuthenticationToken {
-
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SMPAuthenticationToken.class);
     DBUser user;
+    // session encryption key to encrypt sensitive data
+    // at the moment used for UI sessions
+    SecurityUtils.Secret secret=null;
 
     public SMPAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
         super(principal,credentials, authorities );
@@ -25,6 +31,15 @@ public class SMPAuthenticationToken extends UsernamePasswordAuthenticationToken
         return user;
     }
 
+    public SecurityUtils.Secret getSecret(){
+        if (secret==null) {
+            LOG.debug("Secret does not yet exist. Create user session secret!");
+            secret = SecurityUtils.generatePrivateSymmetricKey();
+            LOG.debug("User session secret created!");
+        }
+        return secret;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -37,7 +52,6 @@ public class SMPAuthenticationToken extends UsernamePasswordAuthenticationToken
 
     @Override
     public int hashCode() {
-
         return Objects.hash(super.hashCode(), user);
     }
 }
\ No newline at end of file
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBUserToUserROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBUserToUserROConverter.java
index ba9c5797841b9586e3db72266f27e03917550584..98f92104c8efa353e38aa6e57092b5002f603b91 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBUserToUserROConverter.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBUserToUserROConverter.java
@@ -3,6 +3,7 @@ package eu.europa.ec.edelivery.smp.conversion;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
 import eu.europa.ec.edelivery.smp.data.ui.CertificateRO;
 import eu.europa.ec.edelivery.smp.data.ui.UserRO;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.convert.ConversionService;
@@ -23,15 +24,20 @@ public class DBUserToUserROConverter implements Converter<DBUser, UserRO> {
 
     @Override
     public UserRO convert(DBUser source) {
+
         UserRO target = new UserRO();
         target.setEmailAddress(source.getEmailAddress());
         target.setUsername(source.getUsername());
         target.setRole(source.getRole());
         target.setPassword(source.getPassword());
         target.setAccessTokenId(source.getAccessTokenIdentifier());
+        target.setPasswordExpireOn(source.getPasswordExpireOn());
+        target.setAccessTokenExpireOn(source.getAccessTokenExpireOn());
         target.setPasswordExpired(isPasswordExpired(source));
+
         target.setActive(source.isActive());
-        target.setId(source.getId());
+        // do not expose internal id
+        target.setUserId(SessionSecurityUtils.encryptedEntityId(source.getId()));
         if (source.getCertificate() != null) {
             CertificateRO certificateRO = conversionService.convert(source.getCertificate(), CertificateRO.class);
             target.setCertificate(certificateRO);
@@ -45,6 +51,7 @@ public class DBUserToUserROConverter implements Converter<DBUser, UserRO> {
         return target;
     }
 
+
     private boolean isPasswordExpired(DBUser source) {
         return StringUtils.isNotEmpty(source.getPassword())
                 && (isPasswordRecentlyReset(source) || isPasswordChangedLongerThanThreeMonthsAgo(source));
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/UserROToDBUserConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/UserROToDBUserConverter.java
index 325b6f585dfefa40a26a3a8c7a17f80d4027a163..2c11c86841069870e83820d7e5268d4dceb5b071 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/UserROToDBUserConverter.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/UserROToDBUserConverter.java
@@ -1,12 +1,16 @@
 package eu.europa.ec.edelivery.smp.conversion;
 
+import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationToken;
 import eu.europa.ec.edelivery.smp.data.model.DBCertificate;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
 import eu.europa.ec.edelivery.smp.data.ui.UserRO;
+import eu.europa.ec.edelivery.smp.utils.SecurityUtils;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Component;
 
 import java.util.Objects;
@@ -26,13 +30,11 @@ public class UserROToDBUserConverter implements Converter<UserRO, DBUser> {
         target.setEmailAddress(source.getEmailAddress());
         target.setUsername(source.getUsername());
         target.setRole(source.getRole());
-        target.setPassword(source.getPassword());
         target.setActive(source.isActive());
-        target.setId(source.getId());
+        target.setId(SessionSecurityUtils.decryptEntityId(source.getUserId()));
         if (source.getCertificate() != null) {
             DBCertificate certData = conversionService.convert(source.getCertificate(), DBCertificate.class);
             target.setCertificate(certData);
-
             if(StringUtils.isBlank(source.getUsername())) {
                 // set username with certificate id.
                 // username as cert id is set to database to force unique users
@@ -42,4 +44,6 @@ public class UserROToDBUserConverter implements Converter<UserRO, DBUser> {
         }
         return target;
     }
+
+
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUser.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUser.java
index c3734d5dcd093ef9905e5349f2fde234ff02e2d8..ebffa082cab5a8b697a77c27141645f742bd0b7a 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUser.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUser.java
@@ -62,8 +62,8 @@ public class DBUser extends BaseEntity {
     @ColumnDescription(comment = "User email")
     private String emailAddress;
     // username
-    @Column(name = "USERNAME", length = CommonColumnsLengths.MAX_USERNAME_LENGTH, unique = true)
-    @ColumnDescription(comment = "Login username")
+    @Column(name = "USERNAME", length = CommonColumnsLengths.MAX_USERNAME_LENGTH, unique = true,  nullable = false)
+    @ColumnDescription(comment = "Unique username identifier. The Username must not be null")
     private String username;
     @Column(name = "PASSWORD", length = CommonColumnsLengths.MAX_PASSWORD_LENGTH)
     @ColumnDescription(comment = "BCrypted password for username/password login")
@@ -71,17 +71,28 @@ public class DBUser extends BaseEntity {
     @Column(name = "PASSWORD_CHANGED")
     @ColumnDescription(comment = "Last date when password was changed")
     LocalDateTime passwordChanged;
-    // Personal access token
+
+    @Column(name = "PASSWORD_EXPIRE_ON")
+    @ColumnDescription(comment = "Date when password will expire")
+    LocalDateTime passwordExpireOn;
+
+        // Personal access token
     @Column(name = "ACCESS_TOKEN_ID", length = CommonColumnsLengths.MAX_USERNAME_LENGTH, unique = true)
     @ColumnDescription(comment = "Personal access token id")
     private String accessTokenIdentifier;
     @Column(name = "ACCESS_TOKEN", length = CommonColumnsLengths.MAX_PASSWORD_LENGTH)
     @ColumnDescription(comment = "BCrypted personal access token")
     private String accessToken;
-    @Column(name = "PAT_GENERATED")
+    @Column(name = "ACCESS_TOKEN_GENERATED_ON")
     @ColumnDescription(comment = "Date when personal access token was generated")
     LocalDateTime accessTokenGeneratedOn;
 
+    @Column(name = "ACCESS_TOKEN_EXPIRE_ON")
+    @ColumnDescription(comment = "Date when personal access token will expire")
+    LocalDateTime accessTokenExpireOn;
+
+
+
     @Column(name = "ACTIVE", nullable = false)
     @ColumnDescription(comment = "Is user active")
     private boolean active = true;
@@ -159,6 +170,22 @@ public class DBUser extends BaseEntity {
         this.accessTokenGeneratedOn = accessTokenGeneratedOn;
     }
 
+    public LocalDateTime getPasswordExpireOn() {
+        return passwordExpireOn;
+    }
+
+    public void setPasswordExpireOn(LocalDateTime passwordExpireOn) {
+        this.passwordExpireOn = passwordExpireOn;
+    }
+
+    public LocalDateTime getAccessTokenExpireOn() {
+        return accessTokenExpireOn;
+    }
+
+    public void setAccessTokenExpireOn(LocalDateTime accessTokenExpireOn) {
+        this.accessTokenExpireOn = accessTokenExpireOn;
+    }
+
     public String getRole() {
         return role;
     }
@@ -213,7 +240,7 @@ public class DBUser extends BaseEntity {
 
     @Override
     public int hashCode() {
-        return Objects.hash(super.hashCode(), id, username, certificate);
+        return Objects.hash(super.hashCode(), id, username);
     }
 
     @PrePersist
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/AccessTokenRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/AccessTokenRO.java
index ca89868aad6bc73ddaf8243429c3a076c7cea3ab..ca8f7a31e8c9d5bcf520cbf4c224bbdb47efb9b1 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/AccessTokenRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/AccessTokenRO.java
@@ -1,5 +1,9 @@
 package eu.europa.ec.edelivery.smp.data.ui;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import eu.europa.ec.edelivery.smp.utils.SMPConstants;
+import org.springframework.format.annotation.DateTimeFormat;
+
 import java.io.Serializable;
 import java.time.LocalDateTime;
 
@@ -9,7 +13,10 @@ public class AccessTokenRO implements Serializable {
 
     private String identifier;
     private String value;
+    @JsonFormat(pattern = SMPConstants.JSON_DATETIME_ISO)
     LocalDateTime generatedOn;
+    @JsonFormat(pattern = SMPConstants.JSON_DATETIME_ISO)
+    LocalDateTime expireOn;
 
     public String getIdentifier() {
         return identifier;
@@ -34,4 +41,12 @@ public class AccessTokenRO implements Serializable {
     public void setGeneratedOn(LocalDateTime generatedOn) {
         this.generatedOn = generatedOn;
     }
+
+    public LocalDateTime getExpireOn() {
+        return expireOn;
+    }
+
+    public void setExpireOn(LocalDateTime expireOn) {
+        this.expireOn = expireOn;
+    }
 }
\ No newline at end of file
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CertificateRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CertificateRO.java
index b09b32e022d28760a21092faa949b3dae3a9a836..5b55027aafcf8502df3f9bf51a595d3d03ed16f6 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CertificateRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/CertificateRO.java
@@ -1,6 +1,7 @@
 package eu.europa.ec.edelivery.smp.data.ui;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import eu.europa.ec.edelivery.smp.utils.SMPConstants;
 
 import java.util.Date;
 
@@ -24,9 +25,9 @@ public class CertificateRO extends BaseRO {
     private String invalidReason;
 
 
-    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd,HH:mm", timezone="CET")
+    @JsonFormat(pattern = SMPConstants.JSON_DATETIME_ISO)
     private Date validFrom;
-    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd,HH:mm", timezone="CET")
+    @JsonFormat(pattern = SMPConstants.JSON_DATETIME_ISO)
     private Date validTo;
 
     public CertificateRO() {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainPublicRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainPublicRO.java
new file mode 100644
index 0000000000000000000000000000000000000000..30699e799f63bf178a690d8d28c075e497e1018f
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainPublicRO.java
@@ -0,0 +1,34 @@
+package eu.europa.ec.edelivery.smp.data.ui;
+
+
+/**
+ * Domain resource object containing only public data
+ *
+ * @author Joze Rihtarsic
+ * @since 5.0
+ */
+public class DomainPublicRO extends BaseRO  {
+
+    private static final long serialVersionUID = -9008583888835630561L;
+
+    String domainCode;
+    String smlSubdomain;
+
+    public String getDomainCode() {
+        return domainCode;
+    }
+
+    public void setDomainCode(String domainCode) {
+        this.domainCode = domainCode;
+    }
+
+    public String getSmlSubdomain() {
+        return smlSubdomain;
+    }
+
+    public void setSmlSubdomain(String smlSubdomain) {
+        this.smlSubdomain = smlSubdomain;
+    }
+
+
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PasswordChangeRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PasswordChangeRO.java
new file mode 100644
index 0000000000000000000000000000000000000000..c00b5668f1065f6178d32efaaf7300750e8c2025
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PasswordChangeRO.java
@@ -0,0 +1,31 @@
+package eu.europa.ec.edelivery.smp.data.ui;
+
+import java.io.Serializable;
+
+
+/**
+ * Password change request
+ *
+ * @author Joze Rihtarsic
+ * @since 4.2
+ */
+public class PasswordChangeRO implements Serializable  {
+    String currentPassword;
+    String newPassword;
+
+    public String getCurrentPassword() {
+        return currentPassword;
+    }
+
+    public void setCurrentPassword(String currentPassword) {
+        this.currentPassword = currentPassword;
+    }
+
+    public String getNewPassword() {
+        return newPassword;
+    }
+
+    public void setNewPassword(String newPassword) {
+        this.newPassword = newPassword;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/SmpConfigRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/SmpConfigRO.java
index 7714fe5c6fe105234ffaa28aaf808a309c47d643..2602e70b87e8bdcb5d37446f7c607b8db90035c5 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/SmpConfigRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/SmpConfigRO.java
@@ -11,6 +11,10 @@ public class SmpConfigRO implements Serializable {
     String participantSchemaRegExpMessage;
 
 
+    String passwordValidationRegExp;
+    String passwordValidationRegExpMessage;
+
+
     public boolean isSmlIntegrationOn() {
         return smlIntegrationOn;
     }
@@ -42,4 +46,20 @@ public class SmpConfigRO implements Serializable {
     public void setParticipantSchemaRegExpMessage(String participantSchemaRegExpMessage) {
         this.participantSchemaRegExpMessage = participantSchemaRegExpMessage;
     }
+
+    public String getPasswordValidationRegExp() {
+        return passwordValidationRegExp;
+    }
+
+    public void setPasswordValidationRegExp(String passwordValidationRegExp) {
+        this.passwordValidationRegExp = passwordValidationRegExp;
+    }
+
+    public String getPasswordValidationRegExpMessage() {
+        return passwordValidationRegExpMessage;
+    }
+
+    public void setPasswordValidationRegExpMessage(String passwordValidationRegExpMessage) {
+        this.passwordValidationRegExpMessage = passwordValidationRegExpMessage;
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java
index 77a17abe16bb7094766a828ddbd71375547caec8..71cf350703e043dafddaf2b6aea91dc7a4eb3ffa 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/UserRO.java
@@ -1,11 +1,15 @@
 package eu.europa.ec.edelivery.smp.data.ui;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
+import eu.europa.ec.edelivery.smp.utils.SMPConstants;
 import org.springframework.security.core.userdetails.UserDetails;
 
+import java.time.LocalDateTime;
 import java.util.Collection;
+import java.util.Date;
 
 
 /**
@@ -14,26 +18,37 @@ import java.util.Collection;
  */
 public class UserRO extends BaseRO implements UserDetails {
 
-    private static final long serialVersionUID = 2821447495333163882L;
+    static final long serialVersionUID = 2821447495333163882L;
 
-    private String username;
-    private String password;
-    private String accessTokenId;
-    private String emailAddress;
-    private Collection<SMPAuthority> authorities;
-    private boolean active = true;
-    private String role;
-    private Long id;
-    private CertificateRO certificate;
-    private int statusPassword = EntityROStatus.PERSISTED.getStatusNumber();
-    private boolean passwordExpired;
+    String username;
 
-    public Long getId() {
-        return id;
+    String password;
+    @JsonFormat(pattern = SMPConstants.JSON_DATETIME_ISO)
+    LocalDateTime passwordExpireOn;
+    String accessTokenId;
+    @JsonFormat(pattern = SMPConstants.JSON_DATETIME_ISO)
+    LocalDateTime accessTokenExpireOn;
+    String emailAddress;
+    Collection<SMPAuthority> authorities;
+    boolean active = true;
+    String role;
+    String userId;
+    CertificateRO certificate;
+    int statusPassword = EntityROStatus.PERSISTED.getStatusNumber();
+    boolean passwordExpired;
+
+    /**
+     * Get DB user hash value. It can be used as unique ID for the user. Use hash value for the webservice/ui and do not
+     * expose internal database user identity
+     *
+     * @return hash value of database user entity.
+     */
+    public String getUserId() {
+        return userId;
     }
 
-    public void setId(Long id) {
-        this.id = id;
+    public void setUserId(String userId) {
+        this.userId = userId;
     }
 
     public String getUsername() {
@@ -84,6 +99,22 @@ public class UserRO extends BaseRO implements UserDetails {
         this.active = active;
     }
 
+    public LocalDateTime getPasswordExpireOn() {
+        return passwordExpireOn;
+    }
+
+    public void setPasswordExpireOn(LocalDateTime passwordExpireOn) {
+        this.passwordExpireOn = passwordExpireOn;
+    }
+
+    public LocalDateTime getAccessTokenExpireOn() {
+        return accessTokenExpireOn;
+    }
+
+    public void setAccessTokenExpireOn(LocalDateTime accessTokenExpireOn) {
+        this.accessTokenExpireOn = accessTokenExpireOn;
+    }
+
     public String getRole() {
         return role;
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPAuthority.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPAuthority.java
index 55ea765aaeb0faa2057586c38355f3225674d8a9..962621e9de77bb7f9d85b1cd66e539bf30e80fe8 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPAuthority.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPAuthority.java
@@ -24,6 +24,10 @@ public class SMPAuthority implements GrantedAuthority {
     public static final SMPAuthority S_AUTHORITY_SERVICE_GROUP = new SMPAuthority(SMPRole.SERVICE_GROUP_ADMIN.getCode());
     public static final SMPAuthority S_AUTHORITY_ANONYMOUS = new SMPAuthority(SMPRole.ANONYMOUS.getCode());
 
+    public static final SMPAuthority S_AUTHORITY_WS_SYSTEM_ADMIN = new SMPAuthority(SMPRole.WS_SYSTEM_ADMIN.getCode());
+    public static final SMPAuthority S_AUTHORITY_WS_SMP_ADMIN = new SMPAuthority(SMPRole.WS_SMP_ADMIN.getCode());
+    public static final SMPAuthority S_AUTHORITY_WS_SERVICE_GROUP = new SMPAuthority(SMPRole.WS_SERVICE_GROUP_ADMIN.getCode());
+
     String role;
 
     public SMPAuthority(String role) {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPRole.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPRole.java
index 6ec4a3ad3609becb7a43550793699f8d47d09b36..d9b41097160c2e1029c23f1a0f0359424e61fb67 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPRole.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/auth/SMPRole.java
@@ -3,9 +3,13 @@ package eu.europa.ec.edelivery.smp.data.ui.auth;
 public enum SMPRole {
 
     ANONYMOUS("ANONYMOUS"),
-    SMP_ADMIN("SMP_ADMIN"),
+    GROUP_ADMIN("GROUP_ADMIN"),
     SERVICE_GROUP_ADMIN("SERVICE_GROUP_ADMIN"),
-    SYSTEM_ADMIN("SYSTEM_ADMIN");
+    SMP_ADMIN("SMP_ADMIN"),
+    SYSTEM_ADMIN("SYSTEM_ADMIN"),
+    WS_SERVICE_GROUP_ADMIN("WS_SERVICE_GROUP_ADMIN"),
+    WS_SMP_ADMIN("WS_SMP_ADMIN"),
+    WS_SYSTEM_ADMIN("WS_SYSTEM_ADMIN");
 
     String code;
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
index 85ffaa2243d14b04f2166438669a9679643a9583..167216dcb50bd9b244dbc85393274f17fa6c255e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
@@ -5,77 +5,92 @@ import org.apache.commons.lang3.StringUtils;
 import java.util.Arrays;
 import java.util.Optional;
 
+import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyTypeEnum.*;
+
 public enum SMPPropertyEnum {
     BLUE_COAT_ENABLED("authentication.blueCoat.enabled", "false", "Authentication with Blue Coat means that all HTTP requests " +
             "having 'Client-Cert' header will be authenticated as username placed in the header.Never expose SMP to the WEB " +
-            "without properly configured reverse-proxy and active blue coat.", false, false, false, SMPPropertyTypeEnum.BOOLEAN),
+            "without properly configured reverse-proxy and active blue coat.", false, false, false, BOOLEAN),
 
-    OUTPUT_CONTEXT_PATH("contextPath.output", "true", "This property controls pattern of URLs produced by SMP in GET ServiceGroup responses.", true, false, true, SMPPropertyTypeEnum.BOOLEAN),
-    HTTP_FORWARDED_HEADERS_ENABLED("smp.http.forwarded.headers.enabled", "false", "Use (value true) or remove (value false) forwarded headers! There are security considerations for forwarded headers since an application cannot know if the headers were added by a proxy, as intended, or by a malicious client.", false, false, false, SMPPropertyTypeEnum.BOOLEAN),
-    HTTP_HSTS_MAX_AGE("smp.http.httpStrictTransportSecurity.maxAge", "31536000", "How long(in seconds) HSTS should last in the browser's cache(default one year)", false, false, true, SMPPropertyTypeEnum.INTEGER),
-    HTTP_HEADER_SEC_POLICY("smp.http.header.security.policy", "default-src 'self'; script-src 'self'; child-src 'none'; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; form-action 'self';", "Content Security Policy (CSP)", false, false, true, SMPPropertyTypeEnum.INTEGER),
+    OUTPUT_CONTEXT_PATH("contextPath.output", "true", "This property controls pattern of URLs produced by SMP in GET ServiceGroup responses.", true, false, true, BOOLEAN),
+    HTTP_FORWARDED_HEADERS_ENABLED("smp.http.forwarded.headers.enabled", "false", "Use (value true) or remove (value false) forwarded headers! There are security considerations for forwarded headers since an application cannot know if the headers were added by a proxy, as intended, or by a malicious client.", false, false, false, BOOLEAN),
+    HTTP_HSTS_MAX_AGE("smp.http.httpStrictTransportSecurity.maxAge", "31536000", "How long(in seconds) HSTS should last in the browser's cache(default one year)", false, false, true, INTEGER),
+    HTTP_HEADER_SEC_POLICY("smp.http.header.security.policy", "default-src 'self'; script-src 'self'; child-src 'none'; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; form-action 'self';", "Content Security Policy (CSP)", false, false, true, STRING),
     // http proxy configuration
-    HTTP_PROXY_HOST("smp.proxy.host", "", "The http proxy host", false, false, false, SMPPropertyTypeEnum.STRING),
-    HTTP_NO_PROXY_HOSTS("smp.noproxy.hosts", "localhost|127.0.0.1", "list of nor proxy hosts. Ex.: localhost|127.0.0.1", false, false, false, SMPPropertyTypeEnum.STRING),
-    HTTP_PROXY_PASSWORD("smp.proxy.password", "", "Base64 encrypted password for Proxy.", false, true, false, SMPPropertyTypeEnum.STRING),
-    HTTP_PROXY_PORT("smp.proxy.port", "80", "The http proxy port", false, false, false, SMPPropertyTypeEnum.INTEGER),
-    HTTP_PROXY_USER("smp.proxy.user", "", "The proxy user", false, false, false, SMPPropertyTypeEnum.STRING),
+    HTTP_PROXY_HOST("smp.proxy.host", "", "The http proxy host", false, false, false, STRING),
+    HTTP_NO_PROXY_HOSTS("smp.noproxy.hosts", "localhost|127.0.0.1", "list of nor proxy hosts. Ex.: localhost|127.0.0.1", false, false, false, STRING),
+    HTTP_PROXY_PASSWORD("smp.proxy.password", "", "Base64 encrypted password for Proxy.", false, true, false, STRING),
+    HTTP_PROXY_PORT("smp.proxy.port", "80", "The http proxy port", false, false, false, INTEGER),
+    HTTP_PROXY_USER("smp.proxy.user", "", "The proxy user", false, false, false, STRING),
 
-    PARTC_SCH_REGEXP("identifiersBehaviour.ParticipantIdentifierScheme.validationRegex", "^((?!^.{26})([a-z0-9]+-[a-z0-9]+-[a-z0-9]+)|urn:oasis:names:tc:ebcore:partyid-type:(iso6523|unregistered)(:.+)?$)", "Participant Identifier Schema of each PUT ServiceGroup request is validated against this schema.", false, false, false, SMPPropertyTypeEnum.REGEXP),
+    PARTC_SCH_REGEXP("identifiersBehaviour.ParticipantIdentifierScheme.validationRegex", "^((?!^.{26})([a-z0-9]+-[a-z0-9]+-[a-z0-9]+)|urn:oasis:names:tc:ebcore:partyid-type:(iso6523|unregistered)(:.+)?$)", "Participant Identifier Schema of each PUT ServiceGroup request is validated against this schema.", false, false, false, REGEXP),
     PARTC_SCH_REGEXP_MSG("identifiersBehaviour.ParticipantIdentifierScheme.validationRegexMessage",
-            "Participant scheme must start with:urn:oasis:names:tc:ebcore:partyid-type:(iso6523:|unregistered:) OR must be up to 25 characters long with form [domain]-[identifierArea]-[identifierType] (ex.: 'busdox-actorid-upis') and may only contain the following characters: [a-z0-9].", "Error message for UI", false, false, false, SMPPropertyTypeEnum.STRING),
-    CS_PARTICIPANTS("identifiersBehaviour.caseSensitive.ParticipantIdentifierSchemes", "sensitive-participant-sc1|sensitive-participant-sc2", "Specifies schemes of participant identifiers that must be considered CASE-SENSITIVE.", false, false, false, SMPPropertyTypeEnum.LIST_STRING),
-    CS_DOCUMENTS("identifiersBehaviour.caseSensitive.DocumentIdentifierSchemes", "casesensitive-doc-scheme1|casesensitive-doc-scheme2", "Specifies schemes of document identifiers that must be considered CASE-SENSITIVE.", false, false, false, SMPPropertyTypeEnum.LIST_STRING),
+            "Participant scheme must start with:urn:oasis:names:tc:ebcore:partyid-type:(iso6523:|unregistered:) OR must be up to 25 characters long with form [domain]-[identifierArea]-[identifierType] (ex.: 'busdox-actorid-upis') and may only contain the following characters: [a-z0-9].", "Error message for UI", false, false, false, STRING),
+    CS_PARTICIPANTS("identifiersBehaviour.caseSensitive.ParticipantIdentifierSchemes", "sensitive-participant-sc1|sensitive-participant-sc2", "Specifies schemes of participant identifiers that must be considered CASE-SENSITIVE.", false, false, false, LIST_STRING),
+    CS_DOCUMENTS("identifiersBehaviour.caseSensitive.DocumentIdentifierSchemes", "casesensitive-doc-scheme1|casesensitive-doc-scheme2", "Specifies schemes of document identifiers that must be considered CASE-SENSITIVE.", false, false, false, LIST_STRING),
     // SML integration!
-    SML_ENABLED("bdmsl.integration.enabled", "false", "BDMSL (SML) integration ON/OFF switch", false, false, false, SMPPropertyTypeEnum.BOOLEAN),
-    SML_PARTICIPANT_MULTIDOMAIN("bdmsl.participant.multidomain.enabled", "false", "Set to true if SML support participant on multidomain", false, false, true, SMPPropertyTypeEnum.BOOLEAN),
-    SML_URL("bdmsl.integration.url", "http://localhost:8080/edelivery-sml", "BDMSL (SML) endpoint", false, false, false, SMPPropertyTypeEnum.URL),
-    SML_TLS_DISABLE_CN_CHECK("bdmsl.integration.tls.disableCNCheck", "false", "If SML Url is HTTPs - Disable CN check if needed.", false, false, false, SMPPropertyTypeEnum.BOOLEAN),
-    SML_TLS_SERVER_CERT_SUBJECT_REGEXP("bdmsl.integration.tls.serverSubjectRegex", ".*", "Regular expression for server TLS certificate subject verification  CertEx. .*CN=acc.edelivery.tech.ec.europa.eu.*.", false, false, false, SMPPropertyTypeEnum.REGEXP),
-    SML_LOGICAL_ADDRESS("bdmsl.integration.logical.address", "http://localhost:8080/smp/", "Logical SMP endpoint which will be registered on SML when registering new domain", false, false, false, SMPPropertyTypeEnum.URL),
-    SML_PHYSICAL_ADDRESS("bdmsl.integration.physical.address", "0.0.0.0", "Physical SMP endpoint which will be registered on SML when registering new domain.", false, false, false, SMPPropertyTypeEnum.STRING),
+    SML_ENABLED("bdmsl.integration.enabled", "false", "BDMSL (SML) integration ON/OFF switch", false, false, false, BOOLEAN),
+    SML_PARTICIPANT_MULTIDOMAIN("bdmsl.participant.multidomain.enabled", "false", "Set to true if SML support participant on multidomain", false, false, true, BOOLEAN),
+    SML_URL("bdmsl.integration.url", "http://localhost:8080/edelivery-sml", "BDMSL (SML) endpoint", false, false, false, URL),
+    SML_TLS_DISABLE_CN_CHECK("bdmsl.integration.tls.disableCNCheck", "false", "If SML Url is HTTPs - Disable CN check if needed.", false, false, false, BOOLEAN),
+    SML_TLS_SERVER_CERT_SUBJECT_REGEXP("bdmsl.integration.tls.serverSubjectRegex", ".*", "Regular expression for server TLS certificate subject verification  CertEx. .*CN=acc.edelivery.tech.ec.europa.eu.*.", false, false, false, REGEXP),
+    SML_LOGICAL_ADDRESS("bdmsl.integration.logical.address", "http://localhost:8080/smp/", "Logical SMP endpoint which will be registered on SML when registering new domain", false, false, false, URL),
+    SML_PHYSICAL_ADDRESS("bdmsl.integration.physical.address", "0.0.0.0", "Physical SMP endpoint which will be registered on SML when registering new domain.", false, false, false, STRING),
     // keystore truststore
-    KEYSTORE_PASSWORD("smp.keystore.password", "", "Encrypted keystore (and keys) password ", false, true, false, SMPPropertyTypeEnum.STRING),
-    KEYSTORE_FILENAME("smp.keystore.filename", "smp-keystore.jks", "Keystore filename ", true, false, false, SMPPropertyTypeEnum.FILENAME),
-    TRUSTSTORE_PASSWORD("smp.truststore.password", "", "Encrypted truststore password ", false, true, false, SMPPropertyTypeEnum.STRING),
-    TRUSTSTORE_FILENAME("smp.truststore.filename", "", "Truststore filename ", false, false, false, SMPPropertyTypeEnum.FILENAME),
-    CERTIFICATE_CRL_FORCE("smp.certificate.crl.force", "false", "If false then if CRL is not reachable ignore CRL validation", false, false, false, SMPPropertyTypeEnum.BOOLEAN),
-    CONFIGURATION_DIR("configuration.dir", "smp", "Path to the folder containing all the configuration files (keystore and encryption key)", true, false, true, SMPPropertyTypeEnum.PATH),
-    ENCRYPTION_FILENAME("encryption.key.filename", "encryptionPrivateKey.private", "Key filename to encrypt passwords", false, false, true, SMPPropertyTypeEnum.FILENAME),
-    KEYSTORE_PASSWORD_DECRYPTED("smp.keystore.password.decrypted", "", "Only for backup purposes when  password is automatically created. Store password somewhere save and delete this entry!", false, false, false, SMPPropertyTypeEnum.STRING),
-    TRUSTSTORE_PASSWORD_DECRYPTED("smp.truststore.password.decrypted", "", "Only for backup purposes when  password is automatically created. Store password somewhere save and delete this entry!", false, false, false, SMPPropertyTypeEnum.STRING),
-    CERTIFICATE_ALLOWED_CERTIFICATEPOLICY_OIDS("smp.certificate.validation.allowedCertificatePolicyOIDs","","List of certificate policy OIDs separated by comma where at least one must be in the CertifictePolicy extension", false, false,false, SMPPropertyTypeEnum.STRING),
-    CERTIFICATE_SUBJECT_REGULAR_EXPRESSION("smp.certificate.validation.subjectRegex",".*","Regular expression to validate subject of the certificate", false, false,false, SMPPropertyTypeEnum.REGEXP),
-
-    SMP_PROPERTY_REFRESH_CRON("smp.property.refresh.cronJobExpression", "0 48 */1 * * *", "Property refresh cron expression (def 12 minutes to each hour). Property change is refreshed at restart!", false, false, true, SMPPropertyTypeEnum.STRING),
+    KEYSTORE_PASSWORD("smp.keystore.password", "", "Encrypted keystore (and keys) password ", false, true, false, STRING),
+    KEYSTORE_FILENAME("smp.keystore.filename", "smp-keystore.jks", "Keystore filename ", true, false, false, FILENAME),
+    TRUSTSTORE_PASSWORD("smp.truststore.password", "", "Encrypted truststore password ", false, true, false, STRING),
+    TRUSTSTORE_FILENAME("smp.truststore.filename", "", "Truststore filename ", false, false, false, FILENAME),
+    CERTIFICATE_CRL_FORCE("smp.certificate.crl.force", "false", "If false then if CRL is not reachable ignore CRL validation", false, false, false, BOOLEAN),
+    CONFIGURATION_DIR("configuration.dir", "smp", "Path to the folder containing all the configuration files (keystore and encryption key)", true, false, true, PATH),
+    ENCRYPTION_FILENAME("encryption.key.filename", "encryptionPrivateKey.private", "Key filename to encrypt passwords", false, false, true, FILENAME),
+    KEYSTORE_PASSWORD_DECRYPTED("smp.keystore.password.decrypted", "", "Only for backup purposes when  password is automatically created. Store password somewhere save and delete this entry!", false, false, false, STRING),
+    TRUSTSTORE_PASSWORD_DECRYPTED("smp.truststore.password.decrypted", "", "Only for backup purposes when  password is automatically created. Store password somewhere save and delete this entry!", false, false, false, STRING),
+    CERTIFICATE_ALLOWED_CERTIFICATEPOLICY_OIDS("smp.certificate.validation.allowedCertificatePolicyOIDs","","List of certificate policy OIDs separated by comma where at least one must be in the CertifictePolicy extension", false, false,false, STRING),
+    CERTIFICATE_SUBJECT_REGULAR_EXPRESSION("smp.certificate.validation.subjectRegex",".*","Regular expression to validate subject of the certificate", false, false,false, REGEXP),
+
+    SMP_PROPERTY_REFRESH_CRON("smp.property.refresh.cronJobExpression", "0 48 */1 * * *", "Property refresh cron expression (def 12 minutes to each hour). Property change is refreshed at restart!", false, false, true, STRING),
     // UI COOKIE configuration
-    UI_COOKIE_SESSION_SECURE("smp.ui.session.secure", "false", "Cookie is only sent to the server when a request is made with the https: scheme (except on localhost), and therefore is more resistant to man-in-the-middle attacks.", false, false, false, SMPPropertyTypeEnum.BOOLEAN),
-    UI_COOKIE_SESSION_MAX_AGE("smp.ui.session.max-age", "", "Number of seconds until the cookie expires. A zero or negative number will expire the cookie immediately. Empty value will not set parameter", false, false, false, SMPPropertyTypeEnum.INTEGER),
-    UI_COOKIE_SESSION_SITE("smp.ui.session.strict", "Lax", "Controls whether a cookie is sent with cross-origin requests, providing some protection against cross-site request forgery attacks. Possible values are: Strict, None, Lax. (Cookies with SameSite=None require a secure context/HTTPS)!!)", false, false, false, SMPPropertyTypeEnum.STRING),
-    UI_COOKIE_SESSION_PATH("smp.ui.session.path", "", "A path that must exist in the requested URL, or the browser won't send the Cookie header.  Null/Empty value sets the authentication requests context by default. The forward slash (/) character is interpreted as a directory separator, and subdirectories will be matched as well: for Path=/docs, /docs, /docs/Web/, and /docs/Web/HTTP will all match", false, false, false, SMPPropertyTypeEnum.STRING),
-    UI_COOKIE_SESSION_IDLE_TIMEOUT_ADMIN("smp.ui.session.idle_timeout.admin", "300", "Specifies the time, in seconds, between client requests before the SMP will invalidate session for ADMIN users (System)!", false, false, false, SMPPropertyTypeEnum.INTEGER),
-    UI_COOKIE_SESSION_IDLE_TIMEOUT_USER("smp.ui.session.idle_timeout.user", "1800", "Specifies the time, in seconds, between client requests before the SMP will invalidate session for users (Service group, SMP Admin)", false, false, false, SMPPropertyTypeEnum.INTEGER),
-    // authentication
-    UI_AUTHENTICATION_TYPES("smp.ui.authentication.types", "PASSWORD", "Set list of '|' separated authentication types: PASSWORD|SSO.", false, false, false, SMPPropertyTypeEnum.LIST_STRING),
-    AUTOMATION_AUTHENTICATION_TYPES("smp.automation.authentication.types", "PASSWORD|CERTIFICATE", "Set list of '|' separated application-automation authentication types (Web-Service integration). Currently supported PASSWORD, CERT: ex. PASSWORD|CERT", false, false, false, SMPPropertyTypeEnum.LIST_STRING),
+    UI_COOKIE_SESSION_SECURE("smp.ui.session.secure", "false", "Cookie is only sent to the server when a request is made with the https: scheme (except on localhost), and therefore is more resistant to man-in-the-middle attacks.", false, false, false, BOOLEAN),
+    UI_COOKIE_SESSION_MAX_AGE("smp.ui.session.max-age", "", "Number of seconds until the cookie expires. A zero or negative number will expire the cookie immediately. Empty value will not set parameter", false, false, false, INTEGER),
+    UI_COOKIE_SESSION_SITE("smp.ui.session.strict", "Lax", "Controls whether a cookie is sent with cross-origin requests, providing some protection against cross-site request forgery attacks. Possible values are: Strict, None, Lax. (Cookies with SameSite=None require a secure context/HTTPS)!!)", false, false, false, STRING),
+    UI_COOKIE_SESSION_PATH("smp.ui.session.path", "", "A path that must exist in the requested URL, or the browser won't send the Cookie header.  Null/Empty value sets the authentication requests context by default. The forward slash (/) character is interpreted as a directory separator, and subdirectories will be matched as well: for Path=/docs, /docs, /docs/Web/, and /docs/Web/HTTP will all match", false, false, false, STRING),
+    UI_COOKIE_SESSION_IDLE_TIMEOUT_ADMIN("smp.ui.session.idle_timeout.admin", "300", "Specifies the time, in seconds, between client requests before the SMP will invalidate session for ADMIN users (System)!", false, false, false, INTEGER),
+    UI_COOKIE_SESSION_IDLE_TIMEOUT_USER("smp.ui.session.idle_timeout.user", "1800", "Specifies the time, in seconds, between client requests before the SMP will invalidate session for users (Service group, SMP Admin)", false, false, false, INTEGER),
+
+    PASSWORD_POLICY_REGULAR_EXPRESSION("smp.passwordPolicy.validationRegex","^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~`!@#$%^&+=\\-_<>.,?:;*/()|\\[\\]{}'\"\\\\]).{16,32}$",
+            "Password minimum complexity rules!", false, false,false, REGEXP),
+
+    PASSWORD_POLICY_MESSAGE("smp.passwordPolicy.validationMessage","Minimum length: 16 characters;Maximum length: 32 characters;At least one letter in lowercase;At least one letter in uppercase;At least one digit;At least one special character",
+            "The error message shown to the user in case the password does not follow the regex put in the domibus.passwordPolicy.pattern property", false, false,false, STRING),
+    PASSWORD_POLICY_VALID_DAYS("smp.passwordPolicy.validDays","90",
+            "Number of days password is valid", false, false,false, INTEGER),
+
+    ACCESS_TOKEN_POLICY_VALID_DAYS("smp.accessToken.validDays","60",
+            "Number of days access token is valid is valid", false, false,false, INTEGER),
+
+
+        // authentication
+    UI_AUTHENTICATION_TYPES("smp.ui.authentication.types", "PASSWORD", "Set list of '|' separated authentication types: PASSWORD|SSO.", false, false, false, LIST_STRING),
+    AUTOMATION_AUTHENTICATION_TYPES("smp.automation.authentication.types", "PASSWORD|CERTIFICATE", "Set list of '|' separated application-automation authentication types (Web-Service integration). Currently supported PASSWORD, CERT: ex. PASSWORD|CERT", false, false, false, LIST_STRING),
     // SSO configuration
-    SSO_CAS_UI_LABEL("smp.sso.cas.ui.label", "EU Login", "The SSO service provider label.", false, false, true, SMPPropertyTypeEnum.STRING),
-    SSO_CAS_URL("smp.sso.cas.url", "http://localhost:8080/cas/", "The SSO CAS URL enpoint", false, false, true, SMPPropertyTypeEnum.URL),
-    SSO_CAS_URLPATH_LOGIN("smp.sso.cas.urlpath.login", "login", "The CAS URL path for login. Complete URL is composed from parameters: ${smp.sso.cas.url}/${smp.sso.cas.urlpath.login}.", false, false, true, SMPPropertyTypeEnum.STRING),
-    SSO_CAS_CALLBACK_URL("smp.sso.cas.callback.url", "http://localhost:8080/smp/ui/rest/security/cas", "The URL is the callback URL belonging to the local SMP Security System. If using RP make sure it target SMP path '/ui/rest/security/cas'", false, false, true, SMPPropertyTypeEnum.URL),
-    SSO_CAS_TOKEN_VALIDATION_URLPATH("smp.sso.cas.token.validation.urlpath", "http://localhost:8080/cas/", "The CAS URL path for login. Complete URL is composed from parameters: ${smp.sso.cas.url}/${smp.sso.cas.urlpath.token.validation}.", false, false, true, SMPPropertyTypeEnum.STRING),
-    SSO_CAS_TOKEN_VALIDATION_PARAMS("smp.sso.cas.token.validation.params", "acceptStrengths:BASIC,CLIENT_CERT|assuranceLevel:TOP", "The CAS token validation key:value properties separated with '|'.Ex: 'acceptStrengths:BASIC,CLIENT_CERT|assuranceLevel:TOP'", false, false, true, SMPPropertyTypeEnum.MAP_STRING),
-    SSO_CAS_TOKEN_VALIDATION_GROUPS("smp.sso.cas.token.validation.groups", "DIGIT_SMP|DIGIT_ADMIN", "'|' separated CAS groups user must belong to.", false, false, true, SMPPropertyTypeEnum.LIST_STRING),
+    SSO_CAS_UI_LABEL("smp.sso.cas.ui.label", "EU Login", "The SSO service provider label.", false, false, true, STRING),
+    SSO_CAS_URL("smp.sso.cas.url", "http://localhost:8080/cas/", "The SSO CAS URL enpoint", false, false, true, URL),
+    SSO_CAS_URLPATH_LOGIN("smp.sso.cas.urlpath.login", "login", "The CAS URL path for login. Complete URL is composed from parameters: ${smp.sso.cas.url}/${smp.sso.cas.urlpath.login}.", false, false, true, STRING),
+    SSO_CAS_CALLBACK_URL("smp.sso.cas.callback.url", "http://localhost:8080/smp/ui/rest/security/cas", "The URL is the callback URL belonging to the local SMP Security System. If using RP make sure it target SMP path '/ui/rest/security/cas'", false, false, true, URL),
+    SSO_CAS_TOKEN_VALIDATION_URLPATH("smp.sso.cas.token.validation.urlpath", "http://localhost:8080/cas/", "The CAS URL path for login. Complete URL is composed from parameters: ${smp.sso.cas.url}/${smp.sso.cas.urlpath.token.validation}.", false, false, true, STRING),
+    SSO_CAS_TOKEN_VALIDATION_PARAMS("smp.sso.cas.token.validation.params", "acceptStrengths:BASIC,CLIENT_CERT|assuranceLevel:TOP", "The CAS token validation key:value properties separated with '|'.Ex: 'acceptStrengths:BASIC,CLIENT_CERT|assuranceLevel:TOP'", false, false, true, MAP_STRING),
+    SSO_CAS_TOKEN_VALIDATION_GROUPS("smp.sso.cas.token.validation.groups", "DIGIT_SMP|DIGIT_ADMIN", "'|' separated CAS groups user must belong to.", false, false, true, LIST_STRING),
 
     //deprecated properties
-    SML_KEYSTORE_PASSWORD("bdmsl.integration.keystore.password", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.STRING),
-    SML_KEYSTORE_PATH("bdmsl.integration.keystore.path", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.STRING),
-    SIGNATURE_KEYSTORE_PASSWORD("xmldsig.keystore.password", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.STRING),
-    SIGNATURE_KEYSTORE_PATH("xmldsig.keystore.classpath", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.STRING),
-    SML_PROXY_HOST("bdmsl.integration.proxy.server", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.STRING),
-    SML_PROXY_PORT("bdmsl.integration.proxy.port", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.INTEGER),
-    SML_PROXY_USER("bdmsl.integration.proxy.user", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.STRING),
-    SML_PROXY_PASSWORD("bdmsl.integration.proxy.password", "", "Deprecated", false, false, false, SMPPropertyTypeEnum.STRING),
+    SML_KEYSTORE_PASSWORD("bdmsl.integration.keystore.password", "", "Deprecated", false, false, false, STRING),
+    SML_KEYSTORE_PATH("bdmsl.integration.keystore.path", "", "Deprecated", false, false, false, STRING),
+    SIGNATURE_KEYSTORE_PASSWORD("xmldsig.keystore.password", "", "Deprecated", false, false, false, STRING),
+    SIGNATURE_KEYSTORE_PATH("xmldsig.keystore.classpath", "", "Deprecated", false, false, false, STRING),
+    SML_PROXY_HOST("bdmsl.integration.proxy.server", "", "Deprecated", false, false, false, STRING),
+    SML_PROXY_PORT("bdmsl.integration.proxy.port", "", "Deprecated", false, false, false, INTEGER),
+    SML_PROXY_USER("bdmsl.integration.proxy.user", "", "Deprecated", false, false, false, STRING),
+    SML_PROXY_PASSWORD("bdmsl.integration.proxy.password", "", "Deprecated", false, false, false, STRING),
     ;
 
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/exceptions/ErrorResponseRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/exceptions/ErrorResponseRO.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdc776e9ae99b9013a5c0e236775df350b1b7fae
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/exceptions/ErrorResponseRO.java
@@ -0,0 +1,86 @@
+package eu.europa.ec.edelivery.smp.data.ui.exceptions;
+
+
+import java.util.Objects;
+
+
+/**
+ * @author Joze Rihtarsic
+ * @since 4.2
+ */
+public class ErrorResponseRO {
+    protected String businessCode;
+    protected String errorDescription;
+    protected String errorUniqueId;
+
+    /**
+     * Default no-arg constructor
+     */
+    public ErrorResponseRO() {
+
+    }
+
+    /**
+     * Fully-initialising value constructor
+     */
+    public ErrorResponseRO(final String businessCode, final String errorDescription, final String errorUniqueId) {
+        this.businessCode = businessCode;
+        this.errorDescription = errorDescription;
+        this.errorUniqueId = errorUniqueId;
+    }
+
+
+    public String getBusinessCode() {
+        return businessCode;
+    }
+
+
+    public void setBusinessCode(String value) {
+        this.businessCode = value;
+    }
+
+
+    public String getErrorDescription() {
+        return errorDescription;
+    }
+
+
+    public void setErrorDescription(String value) {
+        this.errorDescription = value;
+    }
+
+
+    public String getErrorUniqueId() {
+        return errorUniqueId;
+    }
+
+
+    public void setErrorUniqueId(String value) {
+        this.errorUniqueId = value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ErrorResponseRO that = (ErrorResponseRO) o;
+        return businessCode.equals(that.businessCode) &&
+                Objects.equals(errorDescription, that.errorDescription) &&
+                errorUniqueId.equals(that.errorUniqueId);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(businessCode, errorDescription, errorUniqueId);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer sb = new StringBuffer("ErrorResponseRO{");
+        sb.append("'businessCode'='").append(businessCode).append('\'');
+        sb.append(", 'errorDescription'='").append(errorDescription).append('\'');
+        sb.append(", 'errorUniqueId'='").append(errorUniqueId).append('\'');
+        sb.append('}');
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPLogger.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPLogger.java
index d306a34e5e931731376d3736ec4e59a5457908f9..9eaedaa4494c4663655fef933282924c57a2aec4 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPLogger.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/logging/SMPLogger.java
@@ -19,13 +19,13 @@ import java.util.Map;
  */
 public class SMPLogger extends CategoryLogger {
 
-    public static final String MDC_USER = "userId";
-    public static final String MDC_SESSION_ID = "messageId";
-    public static final String MDC_DOMAIN = "domain";
-
 
     public static final String MDC_PROPERTY_PREFIX = "smp_";
 
+    public static final String MDC_USER = MDC_PROPERTY_PREFIX+"user";
+    public static final String MDC_REQUEST_ID = MDC_PROPERTY_PREFIX+"request_id";
+    public static final String MDC_SESSION_ID = MDC_PROPERTY_PREFIX+"session_id";
+
     public static final Marker BUSINESS_MARKER = MarkerFactory.getMarker("BUSINESS");
     public static final Marker SECURITY_MARKER = MarkerFactory.getMarker("SECURITY");
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java
index 83bd3547bb73ea2728daa431627df7ebd9f087f3..6d8cc577ced60c2af9c9d109e9d0b910cb15f8be 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java
@@ -69,6 +69,23 @@ public class ConfigurationService {
     public String getParticipantIdentifierSchemeRexExpMessage() {
         return configurationDAO.getCachedProperty(PARTC_SCH_REGEXP_MSG);
     }
+    public Pattern getPasswordPolicyRexExp() {
+        return (Pattern) configurationDAO.getCachedPropertyValue(PASSWORD_POLICY_REGULAR_EXPRESSION);
+    }
+    public String getPasswordPolicyRexExpPattern() {
+        return configurationDAO.getCachedProperty(PASSWORD_POLICY_REGULAR_EXPRESSION);
+    }
+
+    public String getPasswordPolicyValidationMessage() {
+        return configurationDAO.getCachedProperty(PASSWORD_POLICY_MESSAGE);
+    }
+
+    public Integer getPasswordPolicyValidDays() {
+        return (Integer) configurationDAO.getCachedPropertyValue(PASSWORD_POLICY_VALID_DAYS);
+    }
+    public Integer getAccessTokenPolicyValidDays() {
+        return (Integer) configurationDAO.getCachedPropertyValue(ACCESS_TOKEN_POLICY_VALID_DAYS);
+    }
 
     public Integer getHttpHeaderHstsMaxAge() {
         return (Integer) configurationDAO.getCachedPropertyValue(HTTP_HSTS_MAX_AGE);
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainPublicService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainPublicService.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f6d59b1957b70a05a53cee7370e0022645173cb
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainPublicService.java
@@ -0,0 +1,57 @@
+package eu.europa.ec.edelivery.smp.services.ui;
+
+import eu.europa.ec.edelivery.smp.data.dao.BaseDao;
+import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.DBDomainDeleteValidation;
+import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
+import eu.europa.ec.edelivery.smp.data.ui.DomainPublicRO;
+import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.sml.SmlConnector;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.StringWriter;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * Service bean provides only public domain entity data for the Domain.
+ *
+ * @author Joze Rihtarsic
+ * @since 4.2
+ */
+@Service
+public class UIDomainPublicService extends UIServiceBase<DBDomain, DomainPublicRO> {
+
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDomainPublicService.class);
+    @Autowired
+    DomainDao domainDao;
+
+    @Override
+    protected BaseDao<DBDomain> getDatabaseDao() {
+        return domainDao;
+    }
+
+    /**
+     * Method returns Domain resource object list for page.
+     *
+     * @param page
+     * @param pageSize
+     * @param sortField
+     * @param sortOrder
+     * @param filter
+     * @return
+     */
+    public ServiceResult<DomainPublicRO> getTableList(int page, int pageSize,
+                                                String sortField,
+                                                String sortOrder, Object filter) {
+        LOG.debug("Query for public domain data: page: [{}], page size [{}], sort: [{}], filter: [{}].", page, pageSize, sortField, filter);
+        return super.getTableList(page, pageSize, sortField, sortOrder, filter);
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java
index 55ba05e2ff476db5a2cc5c3a56c32a10a49b60c5..f645aaf1e84f4ba17bf8a037cd567c5f23e62ca0 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainService.java
@@ -5,6 +5,7 @@ import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBDomainDeleteValidation;
 import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
+import eu.europa.ec.edelivery.smp.data.ui.DomainPublicRO;
 import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
 import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
@@ -52,6 +53,7 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
         return super.getTableList(page, pageSize, sortField, sortOrder, filter);
     }
 
+
     @Transactional
     public void updateDomainList(List<DomainRO> lst) {
         boolean suc = false;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java
index 5e752a48944a005a1dcf72ff9ecd01ccdf9e92c8..4b35cbe3b298f4e76b94f78a1b84695def24f2ca 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceBase.java
@@ -44,8 +44,6 @@ abstract class UIServiceBase<E extends BaseEntity, R> {
      * @param sortOrder
      * @return
      */
-
-    @Transactional
     public ServiceResult<R> getTableList(int page, int pageSize,
                                          String sortField,
                                          String sortOrder,
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
index b1f94840113da7343bf42dfca6d07a80b9824267..697363e34be439c2af513f6b155514d2652b8de5 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIServiceGroupService.java
@@ -499,12 +499,12 @@ public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, Service
         dbServiceGroup.getUsers().clear();
         List<UserRO> lstUsers = serviceGroupRO.getUsers();
         for (UserRO userRO : lstUsers) {
-            DBUser du = userDao.find(userRO.getId());
-            if (du==null) {
+            Optional<DBUser> optUser = userDao.findUserByUsername(userRO.getUsername());
+            if (!optUser.isPresent()) {
                 throw new SMPRuntimeException(INTERNAL_ERROR,
                         "Database changed",  "User "+userRO.getUsername()+ " not exists! (Refresh data)");
             }
-            dbServiceGroup.getUsers().add(du);
+            dbServiceGroup.getUsers().add(optUser.get());
         }
     }
 
@@ -589,7 +589,7 @@ public class UIServiceGroupService extends UIServiceBase<DBServiceGroup, Service
         // add users
         dbServiceGroup.getUsers().forEach(usr -> {
             UserRO userRO = new UserRO();
-            userRO.setId(usr.getId());
+            userRO.setUserId(usr.getId()+"");
             userRO.setUsername(usr.getUsername());
             userRO.setActive(usr.isActive());
             userRO.setEmailAddress(usr.getEmailAddress());
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
index 16d10272a5b925e46bcb396e61ccbb49b50e3241..33977c8b6868e2c0b76dc9c5f26351d2c1e6192a 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
@@ -165,7 +165,16 @@ public class UITruststoreService {
         return getCertificateData(buff, false);
     }
 
-    public CertificateRO getCertificateData(byte[] buff, boolean validate) throws CertificateException, IOException {
+    /**
+     * Validate certificate!
+     *
+     * @param buff - bytearray of the certificate (pem of or der)
+     * @param validate
+     * @return
+     * @throws CertificateException
+     * @throws IOException
+     */
+    public CertificateRO getCertificateData(byte[] buff, boolean validate) {
         X509Certificate cert = X509CertificateUtils.getX509Certificate(buff);
         CertificateRO cro = convertToRo(cert);
         if (validate) {
@@ -184,6 +193,8 @@ public class UITruststoreService {
                 cro.setInvalidReason("Certificate is revoked!");
             } catch (CertificateNotTrustedException ex) {
                 cro.setInvalidReason("Certificate is not trusted!");
+            } catch (CertificateException e) {
+                cro.setInvalidReason("Can not read the certificate!");
             }
         }
         return cro;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
index 8a7a792061bc17b1865b11dd9a1384982c3bfcf9..836a768a44f2f660b43163604693004537c31320 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
@@ -11,19 +11,31 @@ import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.services.ConfigurationService;
 import eu.europa.ec.edelivery.smp.utils.BCryptPasswordHash;
 import eu.europa.ec.edelivery.smp.utils.SecurityUtils;
+import eu.europa.ec.edelivery.smp.utils.X509CertificateUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.convert.ConversionService;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.crypto.bcrypt.BCrypt;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.io.IOException;
 import java.io.StringWriter;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
+import java.util.Base64;
 import java.util.List;
+import java.util.Optional;
+import java.util.regex.Pattern;
 
 @Service
 public class UIUserService extends UIServiceBase<DBUser, UserRO> {
@@ -33,6 +45,8 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
     @Autowired
     private UserDao userDao;
 
+    @Autowired
+    private ConfigurationService configurationService;
     @Autowired
     private ConversionService conversionService;
 
@@ -79,70 +93,155 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
     }
 
     /**
-     *  Method regenerate access token for user and returns access token
-     *  In the database the access token value is saved in format BCryptPasswordHash
+     * Method regenerate access token for user and returns access token
+     * In the database the access token value is saved in format BCryptPasswordHash
      *
-     * @param userRO
+     * @param userId
      * @return generated AccessToken.
      */
     @Transactional
-    public AccessTokenRO generateAccessTokenForUser(Long userId) {
+    public AccessTokenRO generateAccessTokenForUser(Long userId, String currentPassword) {
+
         DBUser dbUser = userDao.find(userId);
+        if (dbUser == null) {
+            LOG.error("Can not update user password because user for id [{}] does not exist!", userId);
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "UserId", "Can not find user id!");
+        }
+        if (!BCrypt.checkpw(currentPassword, dbUser.getPassword())) {
+            throw new BadCredentialsException("Password change failed; Invalid current password!");
+        }
+        // setup new daes
         AccessTokenRO token = SecurityUtils.generateAccessToken();
+        LocalDateTime generatedTime = token.getGeneratedOn();
+        token.setExpireOn(generatedTime.plusDays(configurationService.getAccessTokenPolicyValidDays()));
         dbUser.setAccessTokenIdentifier(token.getIdentifier());
         dbUser.setAccessToken(BCryptPasswordHash.hashPassword(token.getValue()));
-        dbUser.setAccessTokenGeneratedOn(token.getGeneratedOn());
-        userDao.update(dbUser);
+        dbUser.setAccessTokenGeneratedOn(generatedTime);
+        dbUser.setPasswordExpireOn(token.getExpireOn());
         return token;
     }
 
+    /**
+     * Method regenerate access token for user and returns access token
+     * In the database the access token value is saved in format BCryptPasswordHash
+     *
+     * @param userId
+     * @return generated AccessToken.
+     */
+    @Transactional
+    public boolean updateUserPassword(Long userId, String currentPassword, String newPassword) {
+
+        Pattern pattern = configurationService.getPasswordPolicyRexExp();
+        if (!pattern.matcher(newPassword).matches()) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "PasswordChange", configurationService.getPasswordPolicyValidationMessage());
+        }
+        DBUser dbUser = userDao.find(userId);
+        if (dbUser == null) {
+            LOG.error("Can not update user password because user for id [{}] does not exist!", userId);
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "UserId", "Can not find user id!");
+        }
+
+        if (!BCrypt.checkpw(currentPassword, dbUser.getPassword())) {
+            throw new BadCredentialsException("Password change failed; Invalid current password!");
+        }
+        dbUser.setPassword(BCryptPasswordHash.hashPassword(newPassword));
+        LocalDateTime currentTime = LocalDateTime.now();
+        dbUser.setPasswordChanged(currentTime);
+        dbUser.setPasswordExpireOn(currentTime.plusDays(configurationService.getPasswordPolicyValidDays()));
+        return true;
+    }
+
     @Transactional
     public void updateUserList(List<UserRO> lst, LocalDateTime passwordChange) {
         for (UserRO userRO : lst) {
-            if (userRO.getStatus() == EntityROStatus.NEW.getStatusNumber()) {
-                DBUser dbUser = convertFromRo(userRO);
-                if (!StringUtils.isBlank(userRO.getPassword())) {
-                    dbUser.setPassword(BCryptPasswordHash.hashPassword(userRO.getPassword()));
+            createOrUpdateUser(userRO, passwordChange);
+        }
+    }
+
+    @Transactional
+    public void updateUserdata(Long userId, UserRO user) {
+        DBUser dbUser = userDao.find(userId);
+        if (dbUser == null) {
+            LOG.error("Can not update user because user for id [{}] does not exist!", userId);
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "UserId", "Can not find user id!");
+        }
+
+        dbUser.setEmailAddress(user.getEmailAddress());
+        if (user.getCertificate() != null && (dbUser.getCertificate() == null
+                || !StringUtils.equals(dbUser.getCertificate().getCertificateId(), user.getCertificate().getCertificateId()))) {
+            CertificateRO certRo = user.getCertificate();
+            LOG.info(certRo.getEncodedValue() );
+            if (user.getCertificate().getEncodedValue()!=null ){
+                X509Certificate x509Certificate = X509CertificateUtils.getX509Certificate(Base64.getMimeDecoder().decode(certRo.getEncodedValue()));
+                String certificateAlias;
+                try {
+                    certificateAlias = truststoreService.addCertificate(certRo.getAlias(), x509Certificate);
+                } catch (NoSuchAlgorithmException | KeyStoreException | IOException | CertificateException e) {
+                    LOG.error("Error occurred while adding certificate to truststore.", e);
+                    throw new SMPRuntimeException(ErrorCode.INTERNAL_ERROR, "AddUserCertificate", ExceptionUtils.getRootCauseMessage(e));
                 }
-                userDao.persistFlushDetach(dbUser);
-            } else if (userRO.getStatus() == EntityROStatus.UPDATED.getStatusNumber()) {
-                DBUser dbUser = userDao.find(userRO.getId());
-                dbUser.setEmailAddress(userRO.getEmailAddress());
-                dbUser.setRole(userRO.getRole());
-                dbUser.setActive(userRO.isActive());
-                dbUser.setUsername(userRO.getUsername());
-                if (StringUtils.isBlank(userRO.getUsername())) {
-                    // if username is empty than clear the password
-                    dbUser.setPassword("");
-                } else if (!StringUtils.isBlank(userRO.getPassword())) {
-                    // check for new password
-                    dbUser.setPassword(BCryptPasswordHash.hashPassword(userRO.getPassword()));
-                    dbUser.setPasswordChanged(passwordChange);
+                certRo.setAlias(certificateAlias);
+            }
+            // first
+            DBCertificate certificate = conversionService.convert(user.getCertificate(), DBCertificate.class);
+            dbUser.setCertificate(certificate);
+        }
+    }
+
+    protected void createOrUpdateUser(UserRO userRO, LocalDateTime passwordChange) {
+        if (userRO.getStatus() == EntityROStatus.NEW.getStatusNumber()) {
+            DBUser dbUser = convertFromRo(userRO);
+            if (!StringUtils.isBlank(userRO.getPassword())) {
+                dbUser.setPassword(BCryptPasswordHash.hashPassword(userRO.getPassword()));
+            }
+            userDao.persistFlushDetach(dbUser);
+            return;
+        }
+        Optional<DBUser> optionalDBUser = userDao.findUserByUsername(userRO.getUsername());
+        if (!optionalDBUser.isPresent()) {
+            return;
+        }
+        DBUser dbUser = optionalDBUser.get();
+
+
+        if (userRO.getStatus() == EntityROStatus.UPDATED.getStatusNumber()) {
+
+            dbUser.setEmailAddress(userRO.getEmailAddress());
+            dbUser.setRole(userRO.getRole());
+            dbUser.setActive(userRO.isActive());
+            dbUser.setUsername(userRO.getUsername());
+            if (StringUtils.isBlank(userRO.getUsername())) {
+                // if username is empty than clear the password
+                dbUser.setPassword("");
+            } else if (!StringUtils.isBlank(userRO.getPassword())) {
+                // check for new password
+                dbUser.setPassword(BCryptPasswordHash.hashPassword(userRO.getPassword()));
+                dbUser.setPasswordChanged(passwordChange);
+            }
+            // update certificate data
+            if (userRO.getCertificate() == null || StringUtils.isBlank(userRO.getCertificate().getCertificateId())) {
+                dbUser.setCertificate(null);
+            } else {
+                CertificateRO certificateRO = userRO.getCertificate();
+                DBCertificate dbCertificate = dbUser.getCertificate() != null ? dbUser.getCertificate() : new DBCertificate();
+                dbUser.setCertificate(dbCertificate);
+                if (certificateRO.getValidFrom() != null) {
+                    dbCertificate.setValidFrom(LocalDateTime.ofInstant(certificateRO.getValidFrom().toInstant(), ZoneId.systemDefault()));
                 }
-                // update certificate data
-                if (userRO.getCertificate() == null || StringUtils.isBlank(userRO.getCertificate().getCertificateId())) {
-                    dbUser.setCertificate(null);
-                } else {
-                    CertificateRO certificateRO = userRO.getCertificate();
-                    DBCertificate dbCertificate = dbUser.getCertificate() != null ? dbUser.getCertificate() : new DBCertificate();
-                    dbUser.setCertificate(dbCertificate);
-                    if (certificateRO.getValidFrom() != null) {
-                        dbCertificate.setValidFrom(LocalDateTime.ofInstant(certificateRO.getValidFrom().toInstant(), ZoneId.systemDefault()));
-                    }
-                    if (certificateRO.getValidTo() != null) {
-                        dbCertificate.setValidTo(LocalDateTime.ofInstant(certificateRO.getValidTo().toInstant(), ZoneId.systemDefault()));
-                    }
-                    dbCertificate.setCertificateId(certificateRO.getCertificateId());
-                    dbCertificate.setSerialNumber(certificateRO.getSerialNumber());
-                    dbCertificate.setSubject(certificateRO.getSubject());
-                    dbCertificate.setIssuer(certificateRO.getIssuer());
+                if (certificateRO.getValidTo() != null) {
+                    dbCertificate.setValidTo(LocalDateTime.ofInstant(certificateRO.getValidTo().toInstant(), ZoneId.systemDefault()));
                 }
-                dbUser.setLastUpdatedOn(LocalDateTime.now());
-                userDao.update(dbUser);
-            } else if (userRO.getStatus() == EntityROStatus.REMOVE.getStatusNumber()) {
-                userDao.removeById(userRO.getId());
+                dbCertificate.setCertificateId(certificateRO.getCertificateId());
+                dbCertificate.setSerialNumber(certificateRO.getSerialNumber());
+                dbCertificate.setSubject(certificateRO.getSubject());
+                dbCertificate.setIssuer(certificateRO.getIssuer());
             }
+            dbUser.setLastUpdatedOn(LocalDateTime.now());
+            userDao.update(dbUser);
+        } else if (userRO.getStatus() == EntityROStatus.REMOVE.getStatusNumber()) {
+            userDao.removeById(dbUser.getId());
         }
+
     }
 
     /**
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPConstants.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..df009bc230cd94564b7dbae647bb2295af28b645
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SMPConstants.java
@@ -0,0 +1,6 @@
+package eu.europa.ec.edelivery.smp.utils;
+
+public class SMPConstants {
+    public static final String JSON_DATETIME_ISO="yyyy-MM-dd'T'HH:mm:ss";
+}
+
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java
index 7f975c18e099d1bca7efeb694c58fb987277a433..a69de10200025c8ac905abb15d51ff615e3a633a 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java
@@ -12,6 +12,7 @@ import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.nio.file.Files;
 import java.security.*;
 import java.security.cert.Certificate;
@@ -25,6 +26,33 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.INTERNAL_ERROR;
 
 public class SecurityUtils {
 
+    public static class Secret {
+        final byte[] vector;
+        final SecretKey key;
+        AlgorithmParameterSpec ivParameter = null;
+
+        public Secret(byte[] vector, SecretKey key) {
+            this.vector = vector;
+            this.key = key;
+
+        }
+
+        public byte[] getVector() {
+            return vector;
+        }
+
+        public AlgorithmParameterSpec getIVParameter() {
+            if (ivParameter == null && vector != null) {
+                this.ivParameter = new GCMParameterSpec(GCM_TAG_LENGTH_BIT, vector);
+            }
+            return ivParameter;
+        }
+
+        public SecretKey getKey() {
+            return key;
+        }
+    }
+
     private static final String VALID_PW_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+{}[]|:;<>?,./";
     private static final String VALID_USER_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
     private static final int DEFAULT_PASSWORD_LENGTH = 16;
@@ -123,35 +151,44 @@ public class SecurityUtils {
         return accessToken;
     }
 
-    public static void generatePrivateSymmetricKey(File path) {
-
+    public static Secret generatePrivateSymmetricKey() {
+        // Generates a random key
+        KeyGenerator keyGenerator = null;
         try {
-            // Generates a random key
-            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_KEY);
-            keyGenerator.init(KEY_SIZE);
-            SecretKey privateKey = keyGenerator.generateKey();
-
-            SecureRandom rnd = new SecureRandom();
-            // Using setSeed(byte[]) to reseed a Random object
-            byte[] seed = rnd.generateSeed(IV_GCM_SIZE);
-            rnd.setSeed(seed);
-
-            byte[] buffIV = new byte[IV_GCM_SIZE];
-            rnd.nextBytes(buffIV);
-
-            try (FileOutputStream out = new FileOutputStream(path)) {
-                // first write IV
-                out.write('#');
-                out.write(buffIV);
-                out.write('#');
-                out.write(privateKey.getEncoded());
-                out.flush();
-            }
-        } catch (Exception exc) {
+            keyGenerator = KeyGenerator.getInstance(ALGORITHM_KEY);
+        } catch (NoSuchAlgorithmException exc) {
+            throw new SMPRuntimeException(INTERNAL_ERROR, exc, "Error occurred while generating secret key for encryption", exc.getMessage());
+        }
+        keyGenerator.init(KEY_SIZE);
+        SecretKey privateKey = keyGenerator.generateKey();
+
+        SecureRandom rnd = new SecureRandom();
+        // Using setSeed(byte[]) to reseed a Random object
+        byte[] seed = rnd.generateSeed(IV_GCM_SIZE);
+        rnd.setSeed(seed);
+
+        byte[] buffIV = new byte[IV_GCM_SIZE];
+        rnd.nextBytes(buffIV);
+
+        return new Secret(buffIV, privateKey);
+    }
+
+    public static void generatePrivateSymmetricKey(File path) {
+        Secret secret = generatePrivateSymmetricKey();
+        try (FileOutputStream out = new FileOutputStream(path)) {
+            // first write IV
+            out.write('#');
+            out.write(secret.getVector());
+            out.write('#');
+            out.write(secret.getKey().getEncoded());
+            out.flush();
+
+        } catch (IOException exc) {
             throw new SMPRuntimeException(INTERNAL_ERROR, exc, "Error occurred while saving key for encryption", exc.getMessage());
         }
     }
 
+
     public static String encryptWrappedToken(File encKeyFile, String token) {
         if (!StringUtils.isBlank(token) && token.startsWith(SecurityUtils.DECRYPTED_TOKEN_PREFIX)) {
             String unWrapToken = getNonEncryptedValue(token);
@@ -160,38 +197,75 @@ public class SecurityUtils {
         return token;
     }
 
-    public static String encrypt(File path, String plainToken) {
-        try {
-            byte[] buff = Files.readAllBytes(path.toPath());
-            AlgorithmParameterSpec iv = getSaltParameter(buff);
-            SecretKey privateKey = getSecretKey(buff);
+    public static String encryptURLSafe(Secret secret, String plainToken) {
+        return encrypt(secret, plainToken, Base64.getUrlEncoder().withoutPadding());
+    }
+
+    public static String encrypt(Secret secret, String plainToken) {
+        return encrypt(secret.getKey(), secret.getIVParameter(), plainToken, Base64.getEncoder());
+    }
 
+    public static String encrypt(Secret secret, String plainToken, Base64.Encoder encoder) {
+        return encrypt(secret.getKey(), secret.getIVParameter(), plainToken, encoder);
+    }
+
+    public static String encrypt(SecretKey privateKey, AlgorithmParameterSpec iv, String plainToken, Base64.Encoder encoder) {
+        try {
             Cipher cipher = Cipher.getInstance(iv == NULL_IV ? ALGORITHM_ENCRYPTION_OBSOLETE : ALGORITHM_ENCRYPTION);
             cipher.init(Cipher.ENCRYPT_MODE, privateKey, iv);
             byte[] encryptedData = cipher.doFinal(plainToken.getBytes());
-            return new String(Base64.getEncoder().encode(encryptedData));
+            return new String(encoder.encode(encryptedData));
         } catch (Exception exc) {
             throw new SMPRuntimeException(INTERNAL_ERROR, exc, "Error occurred while encrypting the password", exc.getMessage());
         }
     }
 
-    public static String decrypt(File keyPath, String encryptedPassword) {
+    public static String encrypt(File path, String plainToken) {
+        byte[] buff;
         try {
-            byte[] buff = Files.readAllBytes(keyPath.toPath());
+            buff = Files.readAllBytes(path.toPath());
+        } catch (Exception exc) {
+            throw new SMPRuntimeException(INTERNAL_ERROR, exc, "Error occurred while reading encryption key [" + path.getAbsolutePath() + "]!  Root cause: " + ExceptionUtils.getRootCauseMessage(exc), exc.getMessage());
+        }
+        AlgorithmParameterSpec iv = getSaltParameter(buff);
+        SecretKey privateKey = getSecretKey(buff);
+        return encrypt(privateKey, iv, plainToken, Base64.getEncoder());
+    }
+
+    public static String decrypt(File keyPath, String encryptedToken) {
+
+        byte[] buff;
+        try {
+            buff = Files.readAllBytes(keyPath.toPath());
+        } catch (IOException exc) {
+            throw new SMPRuntimeException(INTERNAL_ERROR, exc, "Error occurred while reading the the key: '" + keyPath.getAbsolutePath() + "'! Root cause: " + ExceptionUtils.getRootCauseMessage(exc), exc.getMessage());
+        }
+        AlgorithmParameterSpec iv = getSaltParameter(buff);
+        SecretKey privateKey = getSecretKey(buff);
+        return decrypt(privateKey, iv, encryptedToken, Base64.getDecoder());
 
-            AlgorithmParameterSpec iv = getSaltParameter(buff);
-            SecretKey privateKey = getSecretKey(buff);
+    }
 
-            byte[] decodedEncryptedPassword = Base64.getDecoder().decode(encryptedPassword.getBytes());
+    public static String decrypt(Secret secret, String encryptedToken) {
+        return decrypt(secret.getKey(), secret.ivParameter, encryptedToken, Base64.getDecoder());
+    }
+
+    public static String decryptUrlSafe(Secret secret, String encryptedToken) {
+        return decrypt(secret.getKey(), secret.ivParameter, encryptedToken, Base64.getUrlDecoder());
+    }
+
+    public static String decrypt(SecretKey privateKey, AlgorithmParameterSpec iv, String encryptedToken, Base64.Decoder decoder) {
+        try {
+            byte[] decodedEncryptedPassword = decoder.decode(encryptedToken.getBytes());
             // this is for back-compatibility - if key parameter is IV than is CBC else ie GCM
             Cipher cipher = Cipher.getInstance(iv instanceof IvParameterSpec ? ALGORITHM_ENCRYPTION_OBSOLETE : ALGORITHM_ENCRYPTION);
             cipher.init(Cipher.DECRYPT_MODE, privateKey, iv);
             byte[] decrypted = cipher.doFinal(decodedEncryptedPassword);
             return new String(decrypted);
         } catch (BadPaddingException | IllegalBlockSizeException ibse) {
-            throw new SMPRuntimeException(INTERNAL_ERROR, ibse, "Either private key '" + keyPath.getAbsolutePath() + "' or encrypted password might not be correct. Please check both.  Root cause: " + ExceptionUtils.getRootCauseMessage(ibse), ibse.getMessage());
+            throw new SMPRuntimeException(INTERNAL_ERROR, ibse, "Either private key or encrypted password might not be correct. Please check both.  Root cause: " + ExceptionUtils.getRootCauseMessage(ibse), ibse.getMessage());
         } catch (Exception exc) {
-            throw new SMPRuntimeException(INTERNAL_ERROR, exc, "Error occurred while decrypting the password with the key: '" + keyPath.getAbsolutePath() + "'! Root cause: " + ExceptionUtils.getRootCauseMessage(exc), exc.getMessage());
+            throw new SMPRuntimeException(INTERNAL_ERROR, exc, "Error occurred while decrypting the password with the key! Root cause: " + ExceptionUtils.getRootCauseMessage(exc), exc.getMessage());
         }
     }
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..6628a098e57c0fe9c077a01b48342a219fcc4d2d
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java
@@ -0,0 +1,62 @@
+package eu.europa.ec.edelivery.smp.utils;
+
+import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationToken;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+
+public class SessionSecurityUtils {
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SessionSecurityUtils.class);
+
+    public static String encryptedEntityId(Long id) {
+        if (id == null) {
+            return null;
+        }
+        SecurityUtils.Secret secret = getAuthenticationSecret();
+        String idValue = id.toString();
+        return secret != null ? SecurityUtils.encryptURLSafe(secret, idValue) : idValue;
+    }
+
+
+    public static Long decryptEntityId(String id) {
+        if (id == null) {
+            return null;
+        }
+        SecurityUtils.Secret secret = getAuthenticationSecret();
+        String value = secret != null ? SecurityUtils.decryptUrlSafe(secret, id) : id;
+        return new Long(value);
+    }
+
+    public static SecurityUtils.Secret getAuthenticationSecret() {
+        if (SecurityContextHolder.getContext() == null) {
+            LOG.warn("No Security context!");
+            return null;
+        }
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (authentication == null) {
+            LOG.warn("No active Authentication!");
+            return null;
+        }
+        if (!(authentication instanceof SMPAuthenticationToken)) {
+            LOG.warn("Authentication is not class type: SMPAuthenticationToken!");
+            return null;
+        }
+        return ((SMPAuthenticationToken) authentication).getSecret();
+    }
+
+    public static String getAuthenticationName() {
+        if (SecurityContextHolder.getContext() == null) {
+            LOG.debug("No Security context!");
+            return null;
+        }
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (authentication == null) {
+            LOG.debug("No active Authentication!");
+            return null;
+        }
+        return authentication.getName();
+
+    }
+}
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java
index 5a92120381f46149f0ba66897a88d835c19a93a6..464fc0098f5a8898bebee4668319b7fd033866ee 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java
@@ -10,7 +10,6 @@ import eu.europa.ec.edelivery.smp.data.ui.UserRO;
 import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
 import eu.europa.ec.edelivery.smp.services.AbstractServiceIntegrationTest;
 import eu.europa.ec.edelivery.smp.testutil.TestDBUtils;
-import org.apache.commons.io.IOUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -18,8 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.crypto.bcrypt.BCrypt;
 import org.springframework.test.context.ContextConfiguration;
 
-import java.io.IOException;
-import java.security.cert.CertificateException;
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.Calendar;
@@ -91,34 +88,13 @@ public class UIUserServiceIntegrationTest extends AbstractServiceIntegrationTest
 
         // all table properties should not be null
         assertNotNull(res);
-        assertNotNull(res.getServiceEntities().get(0).getId());
+        assertNotNull(res.getServiceEntities().get(0).getUserId());
         assertNotNull(res.getServiceEntities().get(0).getUsername());
         assertNotNull(res.getServiceEntities().get(0).getEmailAddress());
         assertNull(res.getServiceEntities().get(0).getPassword()); // Service list must not return passwords
         assertNotNull(res.getServiceEntities().get(0).getRole());
     }
 
-    @Test
-    public void testUpdateUserPassword() {
-        // given
-        insertDataObjects(1);
-        String newPassword = "TestPasswd!@#" + Calendar.getInstance().getTime();
-        ServiceResult<UserRO> urTest  =  testInstance.getTableList(-1,-1,null, null, null);
-        assertEquals(1, urTest.getServiceEntities().size());
-
-        UserRO usr = urTest.getServiceEntities().get(0);
-
-        //when
-        usr.setPassword(newPassword);
-        usr.setStatus(EntityROStatus.UPDATED.getStatusNumber());
-        testInstance.updateUserList(Collections.singletonList(usr), null);
-
-        // then
-        DBUser dbuser = userDao.find(usr.getId());
-        assertTrue(BCrypt.checkpw(newPassword, dbuser.getPassword()));
-    }
-
-
     @Test
     public void testAddUserWithoutCertificate() {
         // given
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
index a3e3e6387b5a0162509eef4ff559e9ada046f1ff..81eb0fff2ad9fc0e931b7069bcf12572f50d9094 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
@@ -102,6 +102,7 @@ public class TestDBUtils {
     public static DBUser createDBUserByCertificate(String certId) {
         DBUser dbuser = new DBUser();
         dbuser.setRole("test");
+        dbuser.setUsername("test-"+certId);
 
         DBCertificate dbcert = new DBCertificate();
         dbcert.setCertificateId(certId);
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/X509CertificateUtilsTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/X509CertificateUtilsTest.java
index bff469f1d200cf6c15bf6eda28ee11deb616f49b..5166855b9bca663f0d44a7042b25e756c933b5a3 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/X509CertificateUtilsTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/X509CertificateUtilsTest.java
@@ -57,10 +57,10 @@ public class X509CertificateUtilsTest {
 
     private static final Object[] crlExtractHTTPSTestListCases() {
         return new Object[][]{
-                {"ldap://localhost/clr,https://localhost/clr,http://localhost/clr","https://localhost/clr"},
-                { "https://localhost/clr","https://localhost/clr"},
-                { "http://localhost/clr","http://localhost/clr"},
-                { "ldap://localhost/clr", null},
+                {"ldap://localhost/clr,https://localhost/clr,http://localhost/clr", "https://localhost/clr"},
+                {"https://localhost/clr", "https://localhost/clr"},
+                {"http://localhost/clr", "http://localhost/clr"},
+                {"ldap://localhost/clr", null},
                 {"", null},
         };
     }
@@ -103,10 +103,9 @@ public class X509CertificateUtilsTest {
     }
 
 
-
     @Test
     @Parameters(method = "crlExtractHTTPSTestListCases")
-    public void extractHttpCrlDistributionPoints(String clrLists, String value){
+    public void extractHttpCrlDistributionPoints(String clrLists, String value) {
         //given
         List<String> urlList = clrLists == null ? Collections.emptyList() : Arrays.asList(clrLists.split(","));
         // when
@@ -116,7 +115,6 @@ public class X509CertificateUtilsTest {
     }
 
 
-
     public static X509Certificate loadCertificate(String filename) throws CertificateException {
         CertificateFactory fact = CertificateFactory.getInstance("X.509");
 
@@ -130,5 +128,4 @@ public class X509CertificateUtilsTest {
     }
 
 
-
 }
diff --git a/smp-server-library/src/test/resources/logback-test.xml b/smp-server-library/src/test/resources/logback-test.xml
index 1abeeedf25fb4f60193e0877d6da2d37c88bf2b4..596f79545321b98cea6f6826743816622f3e9bc5 100644
--- a/smp-server-library/src/test/resources/logback-test.xml
+++ b/smp-server-library/src/test/resources/logback-test.xml
@@ -2,8 +2,8 @@
 
 <configuration>
     <!-- pattern definition -->
-    <property name="encoderPattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
-    <property name="consolePattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="encoderPattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="consolePattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
 
      <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <file>${project.build.directory}/logs/edelivery-smp.log</file>
diff --git a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
index 8a03a034262f28d3e5464b0bc00e869106f5e463..dca3e393779d3dd33791e19e01472a59b1a27667 100644
--- a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
+++ b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
@@ -10,7 +10,7 @@ insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROL
 
 
 insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (10, 'EHEALTH_SMP_EC', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW());
-insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (10, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', NOW()- 1000000,NOW() + 1000000, NOW(), NOW());
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (10, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', date_add(NOW(),interval -1 year), date_add(NOW(),interval 1 year), NOW(), NOW());
 
 insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (11, 'EHEALTH_ż_ẞ_Ẅ_,O', '', 'SMP_ADMIN', 1, NOW(), NOW());
 insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (11, 'CN=EHEALTH_z_ẞ_W_,O=European_z_ẞ_W_Commission,C=BE:f71ee8b11cb3b787', null,null, NOW(), NOW());
diff --git a/smp-soapui-tests/soapui/SMP4.0-Generic-soapui-project.xml b/smp-soapui-tests/soapui/SMP4.0-Generic-soapui-project.xml
index 862cf7cf479d01a77144a5ee89ac332480d65362..6b6124f46aef4e723abe337e9870d10ee60dc7a8 100644
--- a/smp-soapui-tests/soapui/SMP4.0-Generic-soapui-project.xml
+++ b/smp-soapui-tests/soapui/SMP4.0-Generic-soapui-project.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<con:soapui-project activeEnvironment="Default" name="SMP_TESTS" resourceRoot="" soapui-version="5.5.0" abortOnError="false" runType="SEQUENTIAL" id="8147b356-07e4-4ff9-ade6-4e92e0597a38" xmlns:con="http://eviware.com/soapui/config"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.actions.iface.tools.soapui.ProTestRunnerAction@values-local"><![CDATA[<xml-fragment xmlns:con="http://eviware.com/soapui/config">
+<con:soapui-project activeEnvironment="Default" name="SMP_TESTS" resourceRoot="" soapui-version="5.6.0" abortOnError="false" runType="SEQUENTIAL" id="8147b356-07e4-4ff9-ade6-4e92e0597a38" xmlns:con="http://eviware.com/soapui/config"><con:settings><con:setting id="com.eviware.soapui.impl.wsdl.actions.iface.tools.soapui.ProTestRunnerAction@values-local"><![CDATA[<xml-fragment xmlns:con="http://eviware.com/soapui/config">
   <con:entry key="Environment" value="Default"/>
   <con:entry key="Global Properties" value=""/>
   <con:entry key="TestSuite" value="&lt;all>"/>
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationEventListener.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationEventListener.java
index 51247078381a3b5701b48454dd011776c9b8ca15..c0864b2d04cc241debcc5141b7e270e140fb0885 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationEventListener.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationEventListener.java
@@ -14,6 +14,7 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
 import javax.servlet.http.HttpSession;
+import java.util.Arrays;
 import java.util.Collection;
 
 /**
@@ -50,7 +51,7 @@ public class SMPAuthenticationEventListener implements ApplicationListener<Authe
             Collection<? extends GrantedAuthority> authorities = event.getAuthentication().getAuthorities();
             HttpSession session = attr.getRequest().getSession();
             int idleTimeout = getSessionTimeoutForRoles(authorities);
-            LOG.debug("Set session idle timeout [{}] for user [{}] with roles [{}]", idleTimeout, event.getAuthentication().getName(), authorities);
+            LOG.debug("Set session idle timeout [{}] for user [{}] with roles [{}]", idleTimeout, event.getAuthentication().getName(), authorities.stream().map(auth->auth.getAuthority()).toArray());
             session.setMaxInactiveInterval(idleTimeout);
         } else {
             LOG.warn("Could not get ServletRequestAttributes attributes for authentication [{}]", event.getAuthentication());
@@ -60,8 +61,14 @@ public class SMPAuthenticationEventListener implements ApplicationListener<Authe
     public int getSessionTimeoutForRoles(Collection<? extends GrantedAuthority> authorities) {
         boolean hasAdminRole = authorities.stream().anyMatch(grantedAuthority ->
                 StringUtils.equalsIgnoreCase(grantedAuthority.getAuthority(), SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN.getAuthority())
-                        || StringUtils.equalsIgnoreCase(grantedAuthority.getAuthority(), SMPAuthority.S_AUTHORITY_SMP_ADMIN.getAuthority()));
+            || StringUtils.equalsIgnoreCase(grantedAuthority.getAuthority(), SMPAuthority.S_AUTHORITY_SMP_ADMIN.getAuthority())
+            || StringUtils.equalsIgnoreCase(grantedAuthority.getAuthority(), SMPAuthority.S_AUTHORITY_WS_SYSTEM_ADMIN.getAuthority())
+            || StringUtils.equalsIgnoreCase(grantedAuthority.getAuthority(), SMPAuthority.S_AUTHORITY_WS_SMP_ADMIN.getAuthority())
+        );
+        LOG.debug("has role [{}]", ((GrantedAuthority)Arrays.stream(authorities.toArray()).findFirst().get()).getAuthority());
         LOG.debug("has admin role [{}]", hasAdminRole);
-        return hasAdminRole ? configurationService.getSessionIdleTimeoutForAdmin() : configurationService.getSessionIdleTimeoutForUser();
+        LOG.debug("configurationService [{}]", configurationService);
+        return hasAdminRole ? configurationService.getSessionIdleTimeoutForAdmin() :
+                configurationService.getSessionIdleTimeoutForUser();
     }
 }
\ No newline at end of file
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java
index 2079a9b05789548c8ab8b28a918a9b0ddb4005f5..9f9f476fd197fa40f57a40866386a57161357ce8 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java
@@ -27,7 +27,7 @@ public class SMPAuthenticationService {
     public Authentication authenticate(String username, String password) {
         LOG.debug("Authenticate: [{}]", username);
         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
-        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) authenticationManager.authenticate(token);
+        SMPAuthenticationToken authentication = (SMPAuthenticationToken)authenticationManager.authenticate(token);
         SecurityContextHolder.getContext().setAuthentication(authentication);
         return authentication;
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java
index 3500fd0aae07726c6e6f9659472cf140b33378bb..0b009d46a0621853dd9c22e6b7a3045a74c03c25 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java
@@ -2,6 +2,11 @@ package eu.europa.ec.edelivery.smp.auth;
 
 import eu.europa.ec.edelivery.smp.data.ui.UserRO;
 import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
+import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Service;
@@ -15,6 +20,7 @@ import static eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority.S_AUTHORITY_T
  */
 @Service("smpAuthorizationService")
 public class SMPAuthorizationService {
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SMPAuthorizationService.class);
 
     public boolean isSystemAdministrator() {
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
@@ -22,11 +28,18 @@ public class SMPAuthorizationService {
                 && authentication.getAuthorities().stream().anyMatch(grantedAuthority -> S_AUTHORITY_TOKEN_SYSTEM_ADMIN.equals(grantedAuthority.getAuthority()));
     }
 
-    public boolean isCurrentlyLoggedIn(Long userId) {
+    public boolean isCurrentlyLoggedIn(String userId) {
+        Long entityId;
+        try {
+            entityId = SessionSecurityUtils.decryptEntityId(userId);
+        }catch (SMPRuntimeException | NumberFormatException ex){
+            LOG.error("Error occurred while decrypting user-id:["+userId+"]", ex);
+            throw new BadCredentialsException("Login failed; Invalid userID or password");
+        }
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
         if (authentication instanceof SMPAuthenticationToken) {
-            Long loggedInUserId = ((SMPAuthenticationToken) authentication).getUser().getId();
-            return loggedInUserId.equals(userId);
+            Long loggedUserId = ((SMPAuthenticationToken) authentication).getUser().getId();
+            return entityId.equals(loggedUserId);
         }
         return false;
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/MDCLogRequestFilter.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/MDCLogRequestFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf7a8805045b3f12aeca99415c84b004fca94bed
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/MDCLogRequestFilter.java
@@ -0,0 +1,55 @@
+package eu.europa.ec.edelivery.smp.config;
+
+
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
+import org.slf4j.MDC;
+import org.springframework.web.filter.GenericFilterBean;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.UUID;
+
+public class MDCLogRequestFilter extends GenericFilterBean {
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(MDCLogRequestFilter.class);
+/*
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+        String username = SessionSecurityUtils.getAuthenticationName();
+        String requestId = UUID.randomUUID().toString();
+        String sessionId =request.getSession() != null ? request.getSession().getId() : null;
+        LOG.debug("Set request MDC data: user: [{}], request: [{}], session: [{}]!", username,requestId,sessionId);
+
+        MDC.put(SMPLogger.MDC_USER, username);
+        MDC.put(SMPLogger.MDC_REQUEST_ID, UUID.randomUUID().toString());
+        MDC.put(SMPLogger.MDC_SESSION_ID, request.getSession() != null ? request.getSession().getId() : null);
+        //filterChain.doFilter(request, response);
+        //MDC.clear();
+    }
+*/
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        String username = SessionSecurityUtils.getAuthenticationName();
+        String requestId = UUID.randomUUID().toString();
+        String sessionId =null;
+        if (request instanceof  HttpServletRequest){
+            HttpServletRequest httpRequest = (HttpServletRequest) request;
+            sessionId =httpRequest.getSession() != null ? httpRequest.getSession().getId() : null;
+        }
+        MDC.put(SMPLogger.MDC_USER, username);
+        MDC.put(SMPLogger.MDC_REQUEST_ID, requestId);
+        MDC.put(SMPLogger.MDC_SESSION_ID, sessionId);
+        //doFilter
+        chain.doFilter(request, response);
+        MDC.clear();
+
+
+    }
+}
\ No newline at end of file
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPSecurityConstants.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPSecurityConstants.java
index 4f1c989e8b736424ae86e215016ce5de7fd42549..70d5c0029a50bcc0de7286898091ee6ee58c162c 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPSecurityConstants.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPSecurityConstants.java
@@ -1,6 +1,6 @@
 package eu.europa.ec.edelivery.smp.config;
 
-import java.util.UUID;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 
 /**
  * SMP security constants as secured endpoints, beans... etc
@@ -19,8 +19,7 @@ public class SMPSecurityConstants {
     public static final String SMP_CAS_KEY = "SMP_CAS_KEY_";
 
 
-
-    public static final String SMP_SECURITY_PATH = "/ui/rest/security";
-    public static final String SMP_SECURITY_PATH_AUTHENTICATE = SMP_SECURITY_PATH +"/authentication";
-    public static final String SMP_SECURITY_PATH_CAS_AUTHENTICATE = SMP_SECURITY_PATH +"/cas";
+    public static final String SMP_SECURITY_PATH = ResourceConstants.CONTEXT_PATH_PUBLIC + "security";
+    public static final String SMP_SECURITY_PATH_AUTHENTICATE = SMP_SECURITY_PATH + "/authentication";
+    public static final String SMP_SECURITY_PATH_CAS_AUTHENTICATE = SMP_SECURITY_PATH + "/cas";
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java
index adcc3c15ac2b8d7f463b6bd02be2836f267c376f..1c55d9516ed6708be4f03271334489d646d66113 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SmpWebAppConfig.java
@@ -13,13 +13,12 @@
 
 package eu.europa.ec.edelivery.smp.config;
 
-import eu.europa.ec.edelivery.smp.error.ErrorMappingControllerAdvice;
+import eu.europa.ec.edelivery.smp.error.ServiceErrorControllerAdvice;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
-import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
 import org.springframework.web.servlet.config.annotation.*;
 import org.springframework.web.util.UrlPathHelper;
 
@@ -36,7 +35,7 @@ import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
         "eu.europa.ec.edelivery.smp.conversion",
         "eu.europa.ec.edelivery.smp.monitor",
         "eu.europa.ec.edelivery.smp.ui"})
-@Import({GlobalMethodSecurityConfig.class, ErrorMappingControllerAdvice.class})
+@Import({GlobalMethodSecurityConfig.class, ServiceErrorControllerAdvice.class})
 public class SmpWebAppConfig implements WebMvcConfigurer {
     private static final Logger LOG = LoggerFactory.getLogger(SmpWebAppConfig.class);
 
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java
index 3618c140fa093570b93fc989384d518ba349669e..e412ff515606f830195868d13fb889215c3ea981 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SpringSecurityConfig.java
@@ -19,10 +19,10 @@ import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationProvider;
 import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationProviderForUI;
 import eu.europa.ec.edelivery.smp.auth.URLCsrfMatcher;
 import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
-import eu.europa.ec.edelivery.smp.error.SpringSecurityExceptionHandler;
+import eu.europa.ec.edelivery.smp.error.SMPSecurityExceptionHandler;
 import eu.europa.ec.edelivery.smp.services.ConfigurationService;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import eu.europa.ec.edelivery.smp.utils.SMPCookieWriter;
-import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,10 +57,12 @@ import org.springframework.web.server.adapter.ForwardedHeaderTransformer;
 
 import static eu.europa.ec.edelivery.smp.config.SMPSecurityConstants.*;
 
+
 /**
- * Created by gutowpa on 12/07/2017.
+ * SMP Security configuration
+ * @author gutowpa
+ * @since 3.0
  */
-
 @EnableWebSecurity
 @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
 @ComponentScan("eu.europa.ec.edelivery.smp.auth")
@@ -73,6 +75,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
     // Accounts supporting automated application functionalities
     ClientCertAuthenticationFilter clientCertAuthenticationFilter;
     EDeliveryX509AuthenticationFilter x509AuthenticationFilter;
+    MDCLogRequestFilter mdcLogRequestFilter;
     // User account
     CasAuthenticationFilter casAuthenticationFilter;
     CasAuthenticationEntryPoint casAuthenticationEntryPoint;
@@ -87,19 +90,13 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
     @Value("${encodedSlashesAllowedInUrl:true}")
     boolean encodedSlashesAllowedInUrl;
 
-    /**
-     * Initialize beans. Use lazy initialization for filter to avoid circular dependencies
-     *
-     * @param smpAuthenticationProvider
-     * @param clientCertAuthenticationFilter
-     * @param x509AuthenticationFilter
-     */
     @Autowired
     public SpringSecurityConfig(SMPAuthenticationProvider smpAuthenticationProvider,
                                 SMPAuthenticationProviderForUI smpAuthenticationProviderForUI,
                                 ConfigurationService configurationService,
                                 @Lazy ClientCertAuthenticationFilter clientCertAuthenticationFilter,
                                 @Lazy EDeliveryX509AuthenticationFilter x509AuthenticationFilter,
+                                @Lazy MDCLogRequestFilter mdcLogRequestFilter,
                                 @Lazy CsrfTokenRepository csrfTokenRepository,
                                 @Lazy RequestMatcher csrfURLMatcher,
                                 @Lazy HttpFirewall httpFirewall,
@@ -116,6 +113,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
         this.clientCertAuthenticationFilter = clientCertAuthenticationFilter;
         this.x509AuthenticationFilter = x509AuthenticationFilter;
         this.casAuthenticationFilter = casAuthenticationFilter;
+        this.mdcLogRequestFilter = mdcLogRequestFilter;
         this.casAuthenticationEntryPoint = casAuthenticationEntryPoint;
         this.csrfTokenRepository = csrfTokenRepository;
         this.csrfURLMatcher = csrfURLMatcher;
@@ -132,9 +130,13 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
             LOG.debug("The CAS authentication is enabled. Set casAuthenticationEntryPoint!");
             exceptionHandlingConfigurer = exceptionHandlingConfigurer.defaultAuthenticationEntryPointFor(casAuthenticationEntryPoint, new AntPathRequestMatcher(SMP_SECURITY_PATH_CAS_AUTHENTICATE));
         }
-        exceptionHandlingConfigurer.authenticationEntryPoint(new SpringSecurityExceptionHandler());
+
+        SMPSecurityExceptionHandler smpSecurityExceptionHandler = new SMPSecurityExceptionHandler();
+
+        exceptionHandlingConfigurer.authenticationEntryPoint(smpSecurityExceptionHandler);
         httpSecurity = exceptionHandlingConfigurer
-                .accessDeniedHandler(new SpringSecurityExceptionHandler())
+                .accessDeniedHandler(smpSecurityExceptionHandler)
+
                 .and()
                 .headers().frameOptions().deny()
                 .contentTypeOptions().and()
@@ -147,9 +149,11 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
         }
 
 
-        httpSecurity.addFilter(clientCertAuthenticationFilter)
+        httpSecurity
+                .addFilterAfter(mdcLogRequestFilter, EDeliveryX509AuthenticationFilter.class)
+                .addFilter(clientCertAuthenticationFilter)
                 .addFilter(x509AuthenticationFilter)
-                .httpBasic().authenticationEntryPoint(new SpringSecurityExceptionHandler()).and() // username
+                .httpBasic().authenticationEntryPoint(smpSecurityExceptionHandler).and() // username
                 .anonymous().authorities(SMPAuthority.S_AUTHORITY_ANONYMOUS.getAuthority()).and()
                 .authorizeRequests()
                 .antMatchers(HttpMethod.DELETE, SMP_SECURITY_PATH_AUTHENTICATE).permitAll()
@@ -211,11 +215,11 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
                     .maxAgeInSeconds(maxAge)
                     .requestMatcher(AnyRequestMatcher.INSTANCE).and().and();
         }
-
+/*
         String contentSecurityPolicy = configurationService.getHttpHeaderContentSecurityPolicy();
         if (StringUtils.isNotBlank(contentSecurityPolicy)) {
             httpSecurity = httpSecurity.headers().contentSecurityPolicy(contentSecurityPolicy).and().and();
-        }
+        }*/
     }
 
     @Override
@@ -260,6 +264,12 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
         return ClientCertAuthenticationFilter;
     }
 
+    @Bean
+    public MDCLogRequestFilter getMDCLogRequestFilter() {
+        MDCLogRequestFilter filter=  new MDCLogRequestFilter();
+        return filter;
+    }
+
     @Bean
     public EDeliveryX509AuthenticationFilter getEDeliveryX509AuthenticationFilter(@Qualifier(SMP_AUTHENTICATION_MANAGER_BEAN) AuthenticationManager authenticationManager) {
         EDeliveryX509AuthenticationFilter x509AuthenticationFilter = new EDeliveryX509AuthenticationFilter();
@@ -284,7 +294,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
         // Csrf ignore "SMP API 'stateless' calls! (each call is authenticated and session is not used!)"
         requestMatcher.addIgnoreUrl("/.*:+.*(/services/?.*)?", HttpMethod.GET, HttpMethod.DELETE, HttpMethod.POST, HttpMethod.PUT);
         // ignore for login and logout
-        requestMatcher.addIgnoreUrl("/ui/rest/security/authentication", HttpMethod.DELETE, HttpMethod.POST);
+        requestMatcher.addIgnoreUrl(ResourceConstants.CONTEXT_PATH_PUBLIC_SECURITY+"/authentication", HttpMethod.DELETE, HttpMethod.POST);
 
         requestMatcher.addIgnoreUrl(SMP_SECURITY_PATH_CAS_AUTHENTICATE, HttpMethod.GET);
         // allow all gets
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
new file mode 100644
index 0000000000000000000000000000000000000000..d786ca4ec01773d4ed4edd9124401dfa0a08ef71
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
@@ -0,0 +1,43 @@
+package eu.europa.ec.edelivery.smp.error;
+
+import ec.services.smp._1.ErrorResponse;
+import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
+import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.AuthenticationException;
+
+import static eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode.TECHNICAL;
+import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
+import static org.springframework.http.HttpStatus.UNAUTHORIZED;
+
+abstract class AbstractErrorControllerAdvice {
+
+    static final Logger LOG = LoggerFactory.getLogger(AbstractErrorControllerAdvice.class);
+
+    public ResponseEntity handleRuntimeException(RuntimeException runtimeException) {
+        ResponseEntity response;
+        if (runtimeException instanceof SMPRuntimeException) {
+            SMPRuntimeException ex = (SMPRuntimeException)runtimeException;
+            response = buildAndLog(HttpStatus.resolve(ex.getErrorCode().getHttpCode()), ex.getErrorCode().getErrorBusinessCode(), ex.getMessage(), ex);
+        } else if (runtimeException instanceof SMPResponseStatusException ){
+            SMPResponseStatusException ex = (SMPResponseStatusException)runtimeException;
+            response = buildAndLog(ex.getStatus(), ex.getErrorBusinessCode(), ex.getMessage(), ex);
+        } else if (runtimeException instanceof AuthenticationException ){
+            AuthenticationException ex = (AuthenticationException)runtimeException;
+            response = buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex);
+        }
+        else {
+            response = buildAndLog(INTERNAL_SERVER_ERROR, TECHNICAL, "Unexpected technical error occurred.", runtimeException);
+        }
+        String errorCodeId = response.getBody() instanceof  ErrorResponseRO?((ErrorResponseRO) response.getBody()).getErrorUniqueId():((ErrorResponse) response.getBody()).getErrorUniqueId();
+        LOG.error("Unhandled exception occurred, unique ID: [{}]", errorCodeId, runtimeException);
+        return response;
+    }
+
+    abstract ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception);
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java
index 3e9a9b965b4aa2be2204e72b61a5cac2456b9b1a..43b7655c617dcdaddee7f0afaca103bdb347940b 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java
@@ -14,6 +14,7 @@
 package eu.europa.ec.edelivery.smp.error;
 
 import ec.services.smp._1.ErrorResponse;
+import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -22,6 +23,8 @@ import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Date;
 import java.util.UUID;
 
@@ -33,17 +36,16 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
  */
 public class ErrorResponseBuilder {
 
-    private static final Logger log = LoggerFactory.getLogger(ErrorResponseBuilder.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ErrorResponseBuilder.class);
 
     public static final MediaType CONTENT_TYPE_TEXT_XML_UTF8 = MediaType.valueOf("text/xml; charset=UTF-8");
     private HttpStatus status = INTERNAL_SERVER_ERROR;
     private ErrorBusinessCode errorBusinessCode = TECHNICAL;
     private String strErrorDescription = "Unexpected technical error occurred.";
-    private static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSz";
 
     private static String getErrorUniqueId() {
         StringBuilder errId = new StringBuilder();
-        errId.append(new SimpleDateFormat(TIMESTAMP_FORMAT).format(new Date()))
+        errId.append(LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME))
                 .append(":")
                 .append(UUID.randomUUID());
         return String.valueOf(errId);
@@ -59,7 +61,7 @@ public class ErrorResponseBuilder {
         return new ErrorResponseBuilder(status);
     }
 
-    private ErrorResponse buildBody() {
+    public ErrorResponse buildBody() {
         ErrorResponse err = new ErrorResponse();
         err.setBusinessCode(errorBusinessCode.name());
         err.setErrorDescription(strErrorDescription);
@@ -68,6 +70,14 @@ public class ErrorResponseBuilder {
         return err;
     }
 
+    public ErrorResponseRO buildJSonBody() {
+        ErrorResponseRO err = new ErrorResponseRO();
+        err.setBusinessCode(errorBusinessCode.name());
+        err.setErrorDescription(strErrorDescription);
+        err.setErrorUniqueId(getErrorUniqueId());
+        return err;
+    }
+
     public ErrorResponseBuilder businessCode(ErrorBusinessCode newErrorBusinessCode) {
         this.errorBusinessCode = newErrorBusinessCode;
         return this;
@@ -84,4 +94,11 @@ public class ErrorResponseBuilder {
                 .body(this.buildBody());
     }
 
+    public ResponseEntity buildJSon() {
+        return ResponseEntity.status(this.status)
+                .contentType(MediaType.APPLICATION_JSON)
+                .body(this.buildJSonBody());
+    }
+
+
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SpringSecurityExceptionHandler.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SMPSecurityExceptionHandler.java
similarity index 56%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SpringSecurityExceptionHandler.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SMPSecurityExceptionHandler.java
index d9367721e284734681121b864ce6404e871d6b82..d2d31a48072e78079f203e6ebb74925d441ac9c2 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SpringSecurityExceptionHandler.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/SMPSecurityExceptionHandler.java
@@ -13,8 +13,12 @@
 
 package eu.europa.ec.edelivery.smp.error;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import ec.services.smp._1.ErrorResponse;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.ResponseEntity;
@@ -37,14 +41,17 @@ import static org.springframework.http.HttpStatus.UNAUTHORIZED;
 import static org.springframework.http.MediaType.TEXT_HTML_VALUE;
 
 /**
- * Created by gutowpa on 27/01/2017.
+ * SMPSecurityExceptionHandler
+ *
+ * @author gutowpa
+ * @author Joze Rihtarsic
+ * @since 3.0
  */
+public class SMPSecurityExceptionHandler extends BasicAuthenticationEntryPoint implements AccessDeniedHandler {
 
-public class SpringSecurityExceptionHandler extends BasicAuthenticationEntryPoint implements AccessDeniedHandler {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SpringSecurityExceptionHandler.class);
+    private static final Logger LOG = LoggerFactory.getLogger(SMPSecurityExceptionHandler.class);
 
-    public SpringSecurityExceptionHandler() {
+    public SMPSecurityExceptionHandler() {
         this.setRealmName("SMPSecurityRealm");
     }
 
@@ -55,22 +62,23 @@ public class SpringSecurityExceptionHandler extends BasicAuthenticationEntryPoin
         if (authException instanceof BadCredentialsException) {
             errorMsg += " - Provided username/password or client certificate are invalid";
         }
-        handle(response, authException, errorMsg);
+        handle(request, response, authException, errorMsg);
     }
 
     @Override
     public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
-        handle(response, accessDeniedException, accessDeniedException.getMessage());
+        handle(request, response, accessDeniedException, accessDeniedException.getMessage());
     }
 
-    private void handle(HttpServletResponse response, RuntimeException exception, String errorMsg) throws IOException {
+    private void handle(HttpServletRequest request, HttpServletResponse response, RuntimeException exception, String errorMsg) throws IOException {
         ResponseEntity respEntity = buildAndWarn(exception, errorMsg);
-        String errorBody = marshall((ErrorResponse) respEntity.getBody());
+        String errorBody = marshall((ErrorResponse) respEntity.getBody(), request);
         response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
         response.setContentType(TEXT_HTML_VALUE);
         response.getOutputStream().print(errorBody);
     }
 
+
     private ResponseEntity buildAndWarn(RuntimeException exception, String errorMsg) {
         ResponseEntity response = ErrorResponseBuilder.status(UNAUTHORIZED)
                 .businessCode(ErrorBusinessCode.UNAUTHORIZED)
@@ -84,7 +92,39 @@ public class SpringSecurityExceptionHandler extends BasicAuthenticationEntryPoin
         return response;
     }
 
-    private static String marshall(ErrorResponse errorResponse) {
+    /**
+     * Method marshals the response. If the request endpoint is UI it marshal it to JSON else to XML format
+
+     * @param errorResponse - the error to marshal
+     * @param request - The incoming HTTP request for the error
+     * @return string representation of the error
+     */
+    protected String marshall(ErrorResponse errorResponse, HttpServletRequest request) {
+        return isUITRestRequest(request)? marshallToJSon(errorResponse):marshallToXML(errorResponse);
+    }
+
+    /**
+     * Method validates if the request was submitted to UI or to "Oasis-SMP service" endpoint. If the endpoint is UI it returns
+     * true.
+     * @param request - HTTP request to SMP
+     * @return true if request targets the UI.
+     */
+    protected boolean isUITRestRequest(HttpServletRequest request){
+        String contextPath = request!=null?request.getRequestURI():null;
+        boolean result  = StringUtils.isNotBlank(contextPath)
+                && StringUtils.containsAny(contextPath, ResourceConstants.CONTEXT_PATH_PUBLIC,ResourceConstants.CONTEXT_PATH_INTERNAL);
+        LOG.debug("Context path: [{}] is UI rest request: [{}]", contextPath, result);
+        return result;
+    }
+
+    /**
+     * Marshal ErrorResponse to XML format
+     *
+     * @param errorResponse
+     * @return xml string representation of the Error
+     */
+    protected String marshallToXML(ErrorResponse errorResponse) {
+        LOG.debug("Marshal error [{}] to XML format", errorResponse);
         try {
             StringWriter sw = new StringWriter();
             JAXBContext jaxbContext = JAXBContext.newInstance(ErrorResponse.class);
@@ -97,4 +137,20 @@ public class SpringSecurityExceptionHandler extends BasicAuthenticationEntryPoin
         return null;
     }
 
+    /**
+     * Marshal ErrorResponse to JSON format
+     *
+     * @param errorResponse
+     * @return json string representation of the Error
+     */
+    protected String marshallToJSon(ErrorResponse errorResponse) {
+        LOG.debug("Marshal error [{}] to JSON format", errorResponse);
+        try {
+            return new ObjectMapper().writeValueAsString(errorResponse);
+        } catch (JsonProcessingException e) {
+            LOG.error("Error occurred while marshal the error [{}], code: [{}], desc [{}].", errorResponse.getBusinessCode(), errorResponse.getErrorUniqueId(), errorResponse.getErrorDescription());
+        }
+        return null;
+    }
+
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdvice.java
similarity index 57%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdvice.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdvice.java
index fceb733ba05f87f8ca6ef52d61247c07f5c18b2e..a8391b5a7c9ad677cca172ccf4364631e09ebfc7 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdvice.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdvice.java
@@ -14,12 +14,14 @@
 package eu.europa.ec.edelivery.smp.error;
 
 import ec.services.smp._1.ErrorResponse;
-import eu.europa.ec.edelivery.smp.exceptions.*;
 import eu.europa.ec.edelivery.smp.error.exceptions.BadRequestException;
+import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.InvalidOwnerException;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import eu.europa.ec.edelivery.smp.exceptions.WrongInputFieldException;
 import eu.europa.ec.smp.api.exceptions.MalformedIdentifierException;
 import eu.europa.ec.smp.api.exceptions.XmlInvalidAgainstSchemaException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.AccessDeniedException;
@@ -29,73 +31,55 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
 
 import static eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode.*;
 import static java.lang.String.format;
-import static org.springframework.http.HttpStatus.*;
-import static org.springframework.http.HttpStatus.NOT_FOUND;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
 import static org.springframework.http.HttpStatus.UNAUTHORIZED;
 
 
 /**
  * Created by gutowpa on 14/09/2017.
  */
-@RestControllerAdvice
-public class ErrorMappingControllerAdvice {
+@RestControllerAdvice({"eu.europa.ec.edelivery.smp.controllers", "eu.europa.ec.edelivery.smp.controllers"})
+public class ServiceErrorControllerAdvice extends AbstractErrorControllerAdvice {
 
-    private static final Logger log = LoggerFactory.getLogger(ErrorMappingControllerAdvice.class);
-
-    @ExceptionHandler(RuntimeException.class)
+    @ExceptionHandler({RuntimeException.class, SMPRuntimeException.class, SMPResponseStatusException.class, AuthenticationException.class,})
     public ResponseEntity handleRuntimeException(RuntimeException ex) {
-        ResponseEntity response = buildAndWarn(INTERNAL_SERVER_ERROR, TECHNICAL, "Unexpected technical error occurred.", ex);
-        log.error("Unhandled exception occurred, unique ID: "+((ErrorResponse) response.getBody()).getErrorUniqueId(), ex);
-        return response;
-    }
-
-    @ExceptionHandler(SMPRuntimeException.class)
-    public ResponseEntity handleSMPRuntimeException(SMPRuntimeException ex) {
-        ResponseEntity response = buildAndWarn(HttpStatus.resolve(ex.getErrorCode().getHttpCode()), ex.getErrorCode().getErrorBusinessCode(), ex.getMessage(), ex);
-        log.error( ex.getMessage() + ": "+((ErrorResponse) response.getBody()).getErrorUniqueId(), ex);
-        return response;
+        return super.handleRuntimeException(ex);
     }
 
     @ExceptionHandler(BadRequestException.class)
     public ResponseEntity handleBadRequestException(BadRequestException ex) {
-        return buildAndWarn(BAD_REQUEST, ex.getErrorBusinessCode(), ex.getMessage(), ex);
+        return buildAndLog(BAD_REQUEST, ex.getErrorBusinessCode(), ex.getMessage(), ex);
     }
 
     @ExceptionHandler(MalformedIdentifierException.class)
     public ResponseEntity handleMalformedIdentifierException(MalformedIdentifierException ex) {
-        return buildAndWarn(BAD_REQUEST, FORMAT_ERROR, ex.getMessage(), ex);
+        return buildAndLog(BAD_REQUEST, FORMAT_ERROR, ex.getMessage(), ex);
     }
 
     @ExceptionHandler(WrongInputFieldException.class)
     public ResponseEntity handleWrongInputFieldException(WrongInputFieldException ex) {
-        return buildAndWarn(BAD_REQUEST, WRONG_FIELD, ex.getMessage(), ex);
-    }
-
-
-    @ExceptionHandler(AuthenticationException.class)
-    public ResponseEntity handleAuthenticationException(AuthenticationException ex) {
-        return buildAndWarn(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex);
+        return buildAndLog(BAD_REQUEST, WRONG_FIELD, ex.getMessage(), ex);
     }
 
     @ExceptionHandler(AccessDeniedException.class)
     public ResponseEntity handleAccessDeniedException(AccessDeniedException ex) {
-        return buildAndWarn(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage() + " - Only SMP Admin or owner of given ServiceGroup is allowed to perform this action", ex);
+        return buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage() + " - Only SMP Admin or owner of given ServiceGroup is allowed to perform this action", ex);
     }
 
 
     @ExceptionHandler(InvalidOwnerException.class)
     public ResponseEntity handleUnknownUserException(InvalidOwnerException ex) {
-        return buildAndWarn(BAD_REQUEST, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex);
+        return buildAndLog(BAD_REQUEST, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex);
     }
 
 
     @ExceptionHandler(XmlInvalidAgainstSchemaException.class)
     public ResponseEntity handleXmlInvalidAgainstSchemaException(XmlInvalidAgainstSchemaException ex) {
-        return buildAndWarn(BAD_REQUEST, XSD_INVALID, ex.getMessage(), ex);
+        return buildAndLog(BAD_REQUEST, XSD_INVALID, ex.getMessage(), ex);
     }
 
 
-    private ResponseEntity buildAndWarn(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) {
+    ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) {
 
         ResponseEntity response = ErrorResponseBuilder.status(status)
                 .businessCode(businessCode)
@@ -105,8 +89,8 @@ public class ErrorMappingControllerAdvice {
         String errorUniqueId = ((ErrorResponse) response.getBody()).getErrorUniqueId();
         String logMsg = format("Error unique ID: %s", errorUniqueId);
 
-        log.warn(logMsg, exception);
+        LOG.warn(logMsg, exception);
         return response;
     }
-    
+
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e23a2330b1e9e6108604dfc5b1dc9e3a157c5d7
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 European Commission | CEF eDelivery
+ *
+ * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ *
+ * You may obtain a copy of the Licence attached in file: LICENCE-EUPL-v1.2.pdf
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and limitations under the Licence.
+ */
+
+package eu.europa.ec.edelivery.smp.error;
+
+import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
+import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import static java.lang.String.format;
+
+
+/**
+ * Exception Handler for the UI package. Method returns JSON response objects.
+ *
+ * @author gutowpa
+ * @author Joze Rihtarsic
+ * @since 4.2
+ */
+@RestControllerAdvice("eu.europa.ec.edelivery.smp.ui")
+public class UIErrorControllerAdvice extends AbstractErrorControllerAdvice {
+
+
+    @ExceptionHandler({BadCredentialsException.class, RuntimeException.class, SMPRuntimeException.class, SMPResponseStatusException.class, AuthenticationException.class,})
+    public ResponseEntity handleRuntimeException(RuntimeException ex) {
+        return super.handleRuntimeException(ex);
+    }
+
+    ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) {
+
+        ResponseEntity response = ErrorResponseBuilder.status(status)
+                .businessCode(businessCode)
+                .errorDescription(msg)
+                .buildJSon();
+
+        String errorUniqueId = ((ErrorResponseRO) response.getBody()).getErrorUniqueId();
+        String logMsg = format("Error unique ID: %s", errorUniqueId);
+
+        LOG.warn(logMsg, exception);
+        return response;
+    }
+
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/exceptions/SMPResponseStatusException.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/exceptions/SMPResponseStatusException.java
new file mode 100644
index 0000000000000000000000000000000000000000..37a25f35fe3eefb26ea032c586778af36d23ac71
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/exceptions/SMPResponseStatusException.java
@@ -0,0 +1,25 @@
+package eu.europa.ec.edelivery.smp.error.exceptions;
+
+import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.server.ResponseStatusException;
+
+/**
+ * Smp ResponseStatusException extension to hold also smp business error code. Exception is used for REST API "Fault" responses
+ *
+ * @author Joze Rihtarsic
+ * @since 4.2
+ */
+public class SMPResponseStatusException extends ResponseStatusException {
+    private ErrorBusinessCode errorBusinessCode;
+
+    public SMPResponseStatusException(ErrorBusinessCode errorBusinessCode, HttpStatus httpStatus, String sMsg) {
+        super(httpStatus, sMsg);
+        this.errorBusinessCode = errorBusinessCode;
+    }
+
+    public ErrorBusinessCode getErrorBusinessCode() {
+        return errorBusinessCode;
+    }
+
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java
index 5f9e3bb433640c8dc7b66460e95f9a1d1911c85e..c5b41f8122cecd6f7c34417bb4c5f10f54aad09c 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResource.java
@@ -41,7 +41,7 @@ import static eu.europa.ec.edelivery.smp.utils.SMPCookieWriter.SESSION_COOKIE_NA
  * @since 4.0
  */
 @RestController
-@RequestMapping(value = "/ui/rest/security")
+@RequestMapping(value = ResourceConstants.CONTEXT_PATH_PUBLIC_SECURITY)
 public class AuthenticationResource {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(AuthenticationResource.class);
@@ -77,13 +77,6 @@ public class AuthenticationResource {
         this.uiUserService = uiUserService;
     }
 
-    @ResponseStatus(value = HttpStatus.FORBIDDEN)
-    @ExceptionHandler({AuthenticationException.class})
-    public ErrorRO handleException(Exception ex) {
-        LOG.error(ex.getMessage(), ex);
-        return new ErrorRO(ex.getMessage());
-    }
-
     @PostMapping(value = "authentication")
     @Transactional(noRollbackFor = BadCredentialsException.class)
     public UserRO authenticate(@RequestBody LoginRO loginRO, HttpServletRequest request, HttpServletResponse response) {
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..f131e2eab6ae25c49e53be383af2e6a2235c8fff
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java
@@ -0,0 +1,48 @@
+package eu.europa.ec.edelivery.smp.ui;
+
+
+/**
+ * @author Joze Rihtarsic
+ * @since 4.2
+ */
+public class ResourceConstants {
+    // --------------------------------------
+    // context paths
+    public static final String CONTEXT_PATH_PUBLIC="/ui/public/rest/";
+    public static final String CONTEXT_PATH_INTERNAL ="/ui/internal/rest/";
+    // public
+    public static final String CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT = CONTEXT_PATH_PUBLIC + "search";
+    public static final String CONTEXT_PATH_PUBLIC_DOMAIN = CONTEXT_PATH_PUBLIC + "domain";
+    public static final String CONTEXT_PATH_PUBLIC_APPLICATION = CONTEXT_PATH_PUBLIC + "application";
+    public static final String CONTEXT_PATH_PUBLIC_USER = CONTEXT_PATH_PUBLIC + "user";
+    public static final String CONTEXT_PATH_PUBLIC_TRUSTSTORE = CONTEXT_PATH_PUBLIC + "truststore";
+
+    public static final String CONTEXT_PATH_PUBLIC_SERVICE_GROUP = CONTEXT_PATH_PUBLIC + "service-group";
+    public static final String CONTEXT_PATH_PUBLIC_SERVICE_METADATA = CONTEXT_PATH_PUBLIC + "service-metadata";
+
+
+    public static final String CONTEXT_PATH_PUBLIC_SECURITY = CONTEXT_PATH_PUBLIC + "security";
+
+
+    //internal
+    public static final String CONTEXT_PATH_INTERNAL_DOMAIN = CONTEXT_PATH_INTERNAL + "domain";
+    public static final String CONTEXT_PATH_INTERNAL_APPLICATION = CONTEXT_PATH_INTERNAL + "application";
+    public static final String CONTEXT_PATH_INTERNAL_USER = CONTEXT_PATH_INTERNAL + "user";
+    public static final String CONTEXT_PATH_INTERNAL_KEYSTORE = CONTEXT_PATH_INTERNAL + "keystore";
+    public static final String CONTEXT_PATH_INTERNAL_TRUSTSTORE = CONTEXT_PATH_INTERNAL + "truststore";
+
+
+    // --------------------------------------
+    // parameters
+    public static final String PARAM_PAGINATION_PAGE="page";
+    public static final String PARAM_PAGINATION_PAGE_SIZE="pageSize";
+    public static final String PARAM_PAGINATION_ORDER_BY="orderBy";
+    public static final String PARAM_PAGINATION_ORDER_TYPE="orderType";
+
+
+    public static final String PARAM_QUERY_PARTC_ID="participantIdentifier";
+    public static final String PARAM_QUERY_PARTC_SCHEME="participantScheme";
+    public static final String PARAM_QUERY_DOMAIN_CODE ="domainCode";
+    public static final String PARAM_QUERY_USER ="user";
+
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
index e49148be3be9a23b96e658abce76718d21e53605..423dad2cf40a72e8cbf693d6751c6e964e25174f 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResource.java
@@ -32,7 +32,7 @@ import java.util.Arrays;
  */
 
 @RestController
-@RequestMapping(value = "/ui/rest/servicegroup")
+@RequestMapping(value = ResourceConstants.CONTEXT_PATH_PUBLIC_SERVICE_GROUP)
 public class ServiceGroupResource {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ServiceGroupResource.class);
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceMetadataResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceMetadataResource.java
index 2c0a8671fe19eeabfa8e5756c821eedd6aa07425..1f7094b4a9914f07c862343992b765c61fdaa99d 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceMetadataResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ServiceMetadataResource.java
@@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*;
  */
 
 @RestController
-@RequestMapping(value = "/ui/rest/servicemetadata")
+@RequestMapping(value = ResourceConstants.CONTEXT_PATH_PUBLIC_SERVICE_METADATA)
 public class ServiceMetadataResource {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ServiceMetadataResource.class);
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/ApplicationResource.java
similarity index 58%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/ApplicationResource.java
index 61e4734b576a2c1ff0f3ec477da35b8bc5aed934..adc04acee7b735e4343176450022fdacae405592 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ApplicationResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/ApplicationResource.java
@@ -1,16 +1,14 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.external;
 
 
-import eu.europa.ec.edelivery.smp.data.ui.SmpConfigRO;
 import eu.europa.ec.edelivery.smp.data.ui.SmpInfoRO;
-import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.services.ConfigurationService;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.env.Environment;
-import org.springframework.security.access.annotation.Secured;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.TimeZone;
@@ -20,7 +18,7 @@ import java.util.TimeZone;
  * @since 4.1
  */
 @RestController
-@RequestMapping(value = "/ui/rest/application")
+@RequestMapping(value = ResourceConstants.CONTEXT_PATH_PUBLIC_APPLICATION)
 public class ApplicationResource {
 
     @Autowired
@@ -37,17 +35,17 @@ public class ApplicationResource {
     String buildTime;
 
 
-    @RequestMapping(method = RequestMethod.GET, path = "name")
+    @GetMapping(path = "name")
     public String getName() {
         return artifactName;
     }
 
-    @RequestMapping(method = RequestMethod.GET, path = "rootContext")
-    public String getRootContext() {
+
+    protected String getRootContext() {
         return env.getProperty("server.contextPath", "/");
     }
 
-    @RequestMapping(method = RequestMethod.GET, path = "info")
+    @GetMapping(path = "info")
     public SmpInfoRO getApplicationInfo() {
         SmpInfoRO info = new SmpInfoRO();
         info.setVersion(getDisplayVersion());
@@ -59,21 +57,7 @@ public class ApplicationResource {
         return info;
     }
 
-    @RequestMapping(method = RequestMethod.GET, path = "config")
-    @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SMP_ADMIN,
-            SMPAuthority.S_AUTHORITY_TOKEN_SERVICE_GROUP_ADMIN})
-    public SmpConfigRO getApplicationConfig() {
-        SmpConfigRO info = new SmpConfigRO();
-
-        info.setSmlIntegrationOn(configurationService.isSMLIntegrationEnabled());
-        info.setSmlParticipantMultiDomainOn(configurationService.isSMLMultiDomainEnabled());
-        info.setParticipantSchemaRegExp(configurationService.getParticipantIdentifierSchemeRexExpPattern());
-        info.setParticipantSchemaRegExpMessage(configurationService.getParticipantIdentifierSchemeRexExpMessage());
-
-        return info;
-    }
-
-    public String getDisplayVersion() {
+    protected String getDisplayVersion() {
         StringBuilder display = new StringBuilder();
         display.append(artifactName);
         display.append(" Version [");
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..5b8ab0514fee3d6c90e36b9a4f48c5726d79c5b0
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainResource.java
@@ -0,0 +1,48 @@
+package eu.europa.ec.edelivery.smp.ui.external;
+
+
+import eu.europa.ec.edelivery.smp.data.ui.DomainPublicRO;
+import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.services.ui.UIDomainPublicService;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.*;
+
+/**
+ * Purpose of the DomainResource is to provide search method to retrieve configured domains in SMP.
+ *
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+@RestController
+@RequestMapping(value = CONTEXT_PATH_PUBLIC_DOMAIN)
+public class DomainResource {
+
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainResource.class);
+
+    private UIDomainPublicService uiDomainService;
+
+    public DomainResource(UIDomainPublicService uiDomainService) {
+        this.uiDomainService = uiDomainService;
+    }
+
+    @GetMapping(produces = {MimeTypeUtils.APPLICATION_JSON_VALUE})
+    public ServiceResult<DomainPublicRO> geDomainList(
+            @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page,
+            @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize,
+            @RequestParam(value = PARAM_PAGINATION_ORDER_BY, required = false) String orderBy,
+            @RequestParam(value = PARAM_PAGINATION_ORDER_TYPE, defaultValue = "asc", required = false) String orderType,
+            @RequestParam(value = PARAM_QUERY_USER, required = false) String user) {
+
+        LOG.info("Search for page: {}, page size: {}, user: {}", page, pageSize, user);
+        ServiceResult<DomainPublicRO> result = uiDomainService.getTableList(page, pageSize, orderBy, orderType, null);
+        return result;
+    }
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/SearchResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java
similarity index 59%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/SearchResource.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java
index 0d80fca8816695a64d2293530d6101c868b57f26..16f89cc43db4b2599f1cebc53081f65766681aca 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/SearchResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java
@@ -1,4 +1,4 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.external;
 
 
 import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
@@ -9,41 +9,43 @@ import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UIServiceGroupSearchService;
 import eu.europa.ec.edelivery.smp.services.ui.filters.ServiceGroupFilter;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.MimeTypeUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
 
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.*;
+
 /**
+ * Purpose of the SearchResource is to provide search method public participant capabilities
+ *
  * @author Joze Rihtarsic
  * @since 4.1
  */
-
 @RestController
-@RequestMapping(value = "/ui/rest/search")
+@RequestMapping(value = CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT)
 public class SearchResource {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SearchResource.class);
 
-    @Autowired
-    private UIServiceGroupSearchService uiServiceGroupService;
-    @Autowired
-    private DomainDao domainDao;
+    final UIServiceGroupSearchService uiServiceGroupService;
+    final DomainDao domainDao;
 
+    public SearchResource(UIServiceGroupSearchService uiServiceGroupService, DomainDao domainDao) {
+        this.uiServiceGroupService = uiServiceGroupService;
+        this.domainDao = domainDao;
+    }
 
-    @PutMapping(produces = {"application/json"})
-    @ResponseBody
-    @RequestMapping(method = RequestMethod.GET)
+    @GetMapping(produces = {MimeTypeUtils.APPLICATION_JSON_VALUE})
     public ServiceResult<ServiceGroupSearchRO> getServiceGroupList(
-            @RequestParam(value = "page", defaultValue = "0") int page,
-            @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
-            @RequestParam(value = "orderBy", required = false) String orderBy,
-            @RequestParam(value = "orderType", defaultValue = "asc", required = false) String orderType,
-            @RequestParam(value = "participantIdentifier", required = false) String participantIdentifier,
-            @RequestParam(value = "participantScheme", required = false) String participantScheme,
-            @RequestParam(value = "domain", required = false) String domainCode
-    ) {
+            @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page,
+            @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize,
+            @RequestParam(value = PARAM_PAGINATION_ORDER_BY, required = false) String orderBy,
+            @RequestParam(value = PARAM_PAGINATION_ORDER_TYPE, defaultValue = "asc", required = false) String orderType,
+            @RequestParam(value = PARAM_QUERY_PARTC_ID, required = false) String participantIdentifier,
+            @RequestParam(value = PARAM_QUERY_PARTC_SCHEME, required = false) String participantScheme,
+            @RequestParam(value = PARAM_QUERY_DOMAIN_CODE, required = false) String domainCode) {
 
         String participantIdentifierDecoded = decodeUrlToUTF8(participantIdentifier);
         String participantSchemeDecoded = decodeUrlToUTF8(participantScheme);
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/TruststoreResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/TruststoreResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..f686adf919dbf9dab87dc0d765710b2d7dcac53a
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/TruststoreResource.java
@@ -0,0 +1,47 @@
+package eu.europa.ec.edelivery.smp.ui.external;
+
+import eu.europa.ec.edelivery.smp.data.ui.CertificateRO;
+import eu.europa.ec.edelivery.smp.data.ui.KeystoreImportResult;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.services.ui.UITruststoreService;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
+import eu.europa.ec.edelivery.smp.utils.X509CertificateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+/**
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+@RestController
+@RequestMapping(value = ResourceConstants.CONTEXT_PATH_PUBLIC_TRUSTSTORE)
+public class TruststoreResource {
+
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(TruststoreResource.class);
+
+    @Autowired
+    private UITruststoreService uiTruststoreService;
+
+
+    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
+    @PostMapping(path = "/{user-id}/validate-certificate", consumes = MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    public CertificateRO validateCertificate(@PathVariable("user-id") String userId, @RequestBody byte[] data) {
+        LOG.info("Got certificate data size: {}", data.length);
+        return uiTruststoreService.getCertificateData(data, true);
+    }
+
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/UserResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/UserResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..84e2dc74da9383df8de59c9c3325e9f813963e40
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/UserResource.java
@@ -0,0 +1,97 @@
+package eu.europa.ec.edelivery.smp.ui.external;
+
+import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationToken;
+import eu.europa.ec.edelivery.smp.auth.SMPAuthorizationService;
+import eu.europa.ec.edelivery.smp.data.model.DBUser;
+import eu.europa.ec.edelivery.smp.data.ui.AccessTokenRO;
+import eu.europa.ec.edelivery.smp.data.ui.CertificateRO;
+import eu.europa.ec.edelivery.smp.data.ui.PasswordChangeRO;
+import eu.europa.ec.edelivery.smp.data.ui.UserRO;
+import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.services.ui.UITruststoreService;
+import eu.europa.ec.edelivery.smp.services.ui.UIUserService;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.bcrypt.BCrypt;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLIC_USER;
+
+/**
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+@RestController
+@RequestMapping(value = CONTEXT_PATH_PUBLIC_USER)
+public class UserResource {
+
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UserResource.class);
+
+    @Autowired
+    private UIUserService uiUserService;
+    @Autowired
+    protected SMPAuthorizationService authorizationService;
+
+
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
+    @PostMapping(value = "/{user-id}/generate-access-token", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    public AccessTokenRO generateAccessToken(@PathVariable("user-id") String userId, @RequestBody String password) {
+        Long entityId = decryptEntityId(userId);
+        LOG.info("Generated access token for user:[{}] with id:[{}] ", userId, entityId);
+
+        return uiUserService.generateAccessTokenForUser(entityId, password);
+    }
+
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
+    @PutMapping(path = "/{user-id}/change-password", consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    public boolean changePassword(@PathVariable("user-id") String userId, @RequestBody PasswordChangeRO newPassword) {
+        Long entityId = decryptEntityId(userId);
+        LOG.info("Validating the password of the currently logged in user:[{}] with id:[{}] ", userId, entityId);
+        return uiUserService.updateUserPassword(entityId, newPassword.getCurrentPassword(), newPassword.getNewPassword());
+    }
+    /**
+     * Update the details of the currently logged in user (e.g. update the role, the credentials or add certificate details).
+     *
+     * @param userId   the identifier of the user being updated; it must match the currently logged in user's identifier
+     * @param user the updated details
+     * @throws org.springframework.security.access.AccessDeniedException when trying to update the details of another user, different than the one being currently logged in
+     */
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
+    @PutMapping(path = "/{user-id}")
+    public UserRO updateCurrentUser(@PathVariable("user-id") String userId, @RequestBody UserRO user) {
+        LOG.info("Update current user: {}", user);
+        Long entityId = decryptEntityId(userId);
+        // Update the user and mark the password as changed at this very instant of time
+        uiUserService.updateUserdata(entityId, user);
+
+        DBUser updatedUser = uiUserService.findUser(entityId);
+        UserRO userRO = uiUserService.convertToRo(updatedUser);
+
+        return authorizationService.sanitize(userRO);
+    }
+
+    public Long decryptEntityId(String userId){
+        try{
+            return SessionSecurityUtils.decryptEntityId(userId);
+        } catch (RuntimeException runtimeException) {
+            LOG.error("Error occurred while decryption entityId ["+userId+"]!", runtimeException );
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "UserId", "Invalid userId!");
+        }
+    }
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/ApplicationAdminResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/ApplicationAdminResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b11f9fe1a75e18bbed50eed77fa4b864a2081a1
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/ApplicationAdminResource.java
@@ -0,0 +1,48 @@
+package eu.europa.ec.edelivery.smp.ui.internal;
+
+
+import eu.europa.ec.edelivery.smp.data.ui.SmpConfigRO;
+import eu.europa.ec.edelivery.smp.data.ui.SmpInfoRO;
+import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.services.ConfigurationService;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.env.Environment;
+import org.springframework.security.access.annotation.Secured;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.TimeZone;
+
+/**
+ * @author Joze Rihtarsic
+ * @since 4.1
+ */
+@RestController
+@RequestMapping(value = ResourceConstants.CONTEXT_PATH_INTERNAL_APPLICATION)
+public class ApplicationAdminResource {
+
+    final ConfigurationService configurationService;
+
+    public ApplicationAdminResource(ConfigurationService configurationService) {
+        this.configurationService = configurationService;
+    }
+
+    @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_TOKEN_SMP_ADMIN,
+            SMPAuthority.S_AUTHORITY_TOKEN_SERVICE_GROUP_ADMIN})
+    @GetMapping(path = "config")
+    public SmpConfigRO getApplicationConfig() {
+        SmpConfigRO info = new SmpConfigRO();
+        info.setSmlIntegrationOn(configurationService.isSMLIntegrationEnabled());
+        info.setSmlParticipantMultiDomainOn(configurationService.isSMLMultiDomainEnabled());
+        info.setParticipantSchemaRegExp(configurationService.getParticipantIdentifierSchemeRexExpPattern());
+        info.setParticipantSchemaRegExpMessage(configurationService.getParticipantIdentifierSchemeRexExpMessage());
+
+        info.setPasswordValidationRegExp(configurationService.getPasswordPolicyRexExpPattern());
+        info.setPasswordValidationRegExpMessage(configurationService.getPasswordPolicyValidationMessage());
+        return info;
+    }
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResource.java
similarity index 51%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResource.java
index b81527f5443a1d497c4123291d224357de13e6e1..4c49c7a7e23469bfa6cd616baf5f4945270cb976 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/DomainResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResource.java
@@ -1,12 +1,12 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
 
-import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
 import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
 import eu.europa.ec.edelivery.smp.data.ui.SMLIntegrationResult;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
@@ -15,69 +15,85 @@ import eu.europa.ec.edelivery.smp.services.ui.UIDomainService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.annotation.Secured;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.MimeTypeUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Arrays;
 import java.util.List;
 
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.*;
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.PARAM_QUERY_USER;
+
 /**
+ * DomainAdminResource provides admin services for managing the domains configured in SMP. The services defined in path
+ * ResourceConstants.CONTEXT_PATH_INTERNAL should not be exposed to internet.
  * @author Joze Rihtarsic
  * @since 4.1
  */
 
 @RestController
-@RequestMapping(value = "/ui/rest/domain")
-public class DomainResource {
+@RequestMapping(value = CONTEXT_PATH_INTERNAL_DOMAIN)
+public class DomainAdminResource {
 
-    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainResource.class);
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainAdminResource.class);
 
-    @Autowired
-    private UIDomainService uiDomainService;
+    final UIDomainService uiDomainService;
+    final DomainService domainService;
 
-    @Autowired
-    private DomainService domainService;
+    public DomainAdminResource(UIDomainService uiDomainService, DomainService domainService) {
+        this.uiDomainService = uiDomainService;
+        this.domainService = domainService;
 
+    }
 
-    @PutMapping(produces = {"application/json"})
-    @ResponseBody
-    @RequestMapping(method = RequestMethod.GET)
+    @GetMapping(produces = {MimeTypeUtils.APPLICATION_JSON_VALUE})
     public ServiceResult<DomainRO> geDomainList(
-            @RequestParam(value = "page", defaultValue = "0") int page,
-            @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
-            @RequestParam(value = "orderBy", required = false) String orderBy,
-            @RequestParam(value = "orderType", defaultValue = "asc", required = false) String orderType,
-            @RequestParam(value = "user", required = false) String user
-    ) {
+            @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page,
+            @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize,
+            @RequestParam(value = PARAM_PAGINATION_ORDER_BY, required = false) String orderBy,
+            @RequestParam(value = PARAM_PAGINATION_ORDER_TYPE, defaultValue = "asc", required = false) String orderType,
+            @RequestParam(value = PARAM_QUERY_USER, required = false) String user) {
+
+        LOG.info("Search for page: {}, page size: {}, user: {}", page, pageSize, user);
         return uiDomainService.getTableList(page, pageSize, orderBy, orderType, null);
     }
 
-    @PutMapping(produces = {"application/json"})
-    @RequestMapping(method = RequestMethod.PUT)
+    /**
+     *  List of domains to be added or updated
+     *
+     * @param updateEntities
+     */
+    @PutMapping(produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN})
-    public void updateDomainList(@RequestBody(required = true) DomainRO[] updateEntities) {
+    public void updateDomainList(@RequestBody DomainRO[] updateEntities) {
         LOG.info("GOT LIST OF DomainRO to UPDATE: " + updateEntities.length);
         uiDomainService.updateDomainList(Arrays.asList(updateEntities));
     }
 
-    @PutMapping(produces = {"application/json"})
-    @RequestMapping(path = "validateDelete", method = RequestMethod.POST)
+    /**
+     * Validated if domains with provided IDs can be deleted and returns the result in DeleteEntityValidation.
+     * @param listOfDomainIds
+     * @return
+     */
+
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN})
-    public DeleteEntityValidation validateDeleteDomain(@RequestBody List<Long> query) {
+    @PutMapping(value = "validate-delete", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    public DeleteEntityValidation validateDeleteDomain(@RequestBody List<Long> listOfDomainIds) {
 
         DeleteEntityValidation dres = new DeleteEntityValidation();
-        dres.getListIds().addAll(query);
+        dres.getListIds().addAll(listOfDomainIds);
         return uiDomainService.validateDeleteRequest(dres);
     }
 
-    @PostMapping(value = "/{id}/smlregister/{domaincode}")
-    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public SMLIntegrationResult registerDomainAndParticipants(@PathVariable("id") Long id,
-                                                              @PathVariable("domaincode") String domaincode
+    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
+    @PutMapping(value = "/{user-id}/sml-register/{domain-code}")
+    public SMLIntegrationResult registerDomainAndParticipants(@PathVariable("user-id") Long userId,
+                                                              @PathVariable("domain-code") String domainCode
     ) {
-        LOG.info("SML register domain code: {}, user id {}", domaincode, id);
+        LOG.info("SML register domain code: {}, user user-id {}", domainCode, userId);
         SMLIntegrationResult result = new SMLIntegrationResult();
         try {
-            DBDomain dbDomain = domainService.getDomain(domaincode);
+            DBDomain dbDomain = domainService.getDomain(domainCode);
             domainService.registerDomainAndParticipants(dbDomain);
             result.setSuccess(true);
         } catch (SMPRuntimeException e) {
@@ -88,16 +104,15 @@ public class DomainResource {
     }
 
 
-    @PostMapping(value = "/{id}/smlunregister/{domaincode}")
-    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public SMLIntegrationResult unregisterDomainAndParticipants(@PathVariable("id") Long id,
-                                                                @PathVariable("domaincode") String domaincode
-    ) {
-        LOG.info("SML unregister domain code: {}, user id {}", domaincode, id);
+    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
+    @PutMapping(value = "/{user-id}/sml-unregister/{domain-code}")
+    public SMLIntegrationResult unregisterDomainAndParticipants(@PathVariable("user-id") Long userId,
+                                                                @PathVariable("domain-code") String domainCode) {
+        LOG.info("SML unregister domain code: {}, user id {}", domainCode, userId);
         // try to open keystore
         SMLIntegrationResult result = new SMLIntegrationResult();
         try {
-            DBDomain dbDomain = domainService.getDomain(domaincode);
+            DBDomain dbDomain = domainService.getDomain(domainCode);
             domainService.unregisterDomainAndParticipantsFromSml(dbDomain);
             result.setSuccess(true);
         } catch (SMPRuntimeException e) {
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/KeystoreResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/KeystoreResource.java
similarity index 77%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/KeystoreResource.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/KeystoreResource.java
index 0d2b097f002d2489967d0eb9f52972df457f707a..1958d1206f9ab2d433a648ecc181a794d94b6fa8 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/KeystoreResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/KeystoreResource.java
@@ -1,15 +1,16 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
-import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.data.ui.CertificateRO;
 import eu.europa.ec.edelivery.smp.data.ui.KeystoreImportResult;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UIKeystoreService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.annotation.Secured;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.MimeTypeUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.ByteArrayInputStream;
@@ -21,12 +22,16 @@ import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
 import java.util.List;
 
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_INTERNAL_KEYSTORE;
+import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;
+import static org.springframework.util.MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE;
+
 /**
  * @author Joze Rihtarsic
  * @since 4.1
  */
 @RestController
-@RequestMapping(value = "/ui/rest/keystore")
+@RequestMapping(value = CONTEXT_PATH_INTERNAL_KEYSTORE)
 public class KeystoreResource {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(KeystoreResource.class);
@@ -34,24 +39,22 @@ public class KeystoreResource {
     @Autowired
     private UIKeystoreService uiKeystoreService;
 
-    @PutMapping(produces = {"application/json"})
-    @RequestMapping(method = RequestMethod.GET)
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN})
+    @GetMapping(produces = {MimeTypeUtils.APPLICATION_JSON_VALUE})
     public ServiceResult<CertificateRO> getKeyCertificateList() {
         List<CertificateRO> lst = uiKeystoreService.getKeystoreEntriesList();
         // clear encoded value to reduce http traffic
         lst.stream().forEach(certificateRO -> {
             certificateRO.setEncodedValue(null);
         });
-
         ServiceResult<CertificateRO> sg = new ServiceResult<>();
         sg.getServiceEntities().addAll(lst);
         sg.setCount((long) lst.size());
         return sg;
     }
 
-    @PostMapping(value = "/{id}/upload/{keystoreType}/{password}", produces = {"application/json"}, consumes = {"application/octet-stream"})
     @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
+    @PostMapping(path = "/{id}/upload/{keystoreType}/{password}", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_OCTET_STREAM_VALUE)
     public KeystoreImportResult uploadKeystore(@PathVariable("id") Long id,
                                                @PathVariable("keystoreType") String keystoreType,
                                                @PathVariable("password") String password,
@@ -59,14 +62,14 @@ public class KeystoreResource {
         LOG.info("Got keystore data size: {}, type {}, password length {}", fileBytes.length, keystoreType, password.length());
         // try to open keystore
         KeystoreImportResult keystoreImportResult = new KeystoreImportResult();
-          KeyStore keyStore = null;
+        KeyStore keyStore = null;
         try {
             keyStore = KeyStore.getInstance(keystoreType);
             keyStore.load(new ByteArrayInputStream(fileBytes), password.toCharArray());
             LOG.debug(keyStore.aliases().nextElement());
             uiKeystoreService.importKeys(keyStore, password);
         } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableKeyException e) {
-            String msg = e.getClass().getName() +" occurred while reading the keystore: " + e.getMessage();
+            String msg = e.getClass().getName() + " occurred while reading the keystore: " + e.getMessage();
             LOG.error(msg, e);
             keystoreImportResult.setErrorMessage(msg);
         }
@@ -74,22 +77,19 @@ public class KeystoreResource {
         return keystoreImportResult;
     }
 
-
-    @DeleteMapping(value = "/{id}/delete/{alias}", produces = {"application/json"})
     @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
+    @DeleteMapping(value = "/{id}/delete/{alias}", produces = APPLICATION_JSON_VALUE)
     public KeystoreImportResult deleteCertificate(@PathVariable("id") Long id,
-                                               @PathVariable("alias") String alias) {
+                                                  @PathVariable("alias") String alias) {
         LOG.info("Remove alias by user id {}, alias {}.", id, alias);
         KeystoreImportResult keystoreImportResult = new KeystoreImportResult();
-
         try {
             uiKeystoreService.deleteKey(alias);
         } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
-            String msg = e.getClass().getName() +" occurred while reading the keystore: " + e.getMessage();
+            String msg = e.getClass().getName() + " occurred while reading the keystore: " + e.getMessage();
             LOG.error(msg, e);
             keystoreImportResult.setErrorMessage(msg);
         }
-
         return keystoreImportResult;
     }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/TruststoreResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/TruststoreAdminResource.java
similarity index 80%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/TruststoreResource.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/TruststoreAdminResource.java
index 07b9200f6d735ef5636ab0db6308b071967dcf91..09f0ec004a3626e84de441643c7fe0c1a2d9e62c 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/TruststoreResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/TruststoreAdminResource.java
@@ -1,4 +1,4 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
 import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.data.ui.CertificateRO;
@@ -8,10 +8,12 @@ import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UITruststoreService;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import eu.europa.ec.edelivery.smp.utils.X509CertificateUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.annotation.Secured;
 import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.MimeTypeUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
@@ -26,10 +28,10 @@ import java.util.List;
  * @since 4.1
  */
 @RestController
-@RequestMapping(value = "/ui/rest/truststore")
-public class TruststoreResource {
+@RequestMapping(value = ResourceConstants.CONTEXT_PATH_INTERNAL_TRUSTSTORE)
+public class TruststoreAdminResource {
 
-    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(TruststoreResource.class);
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(TruststoreAdminResource.class);
 
     @Autowired
     private UITruststoreService uiTruststoreService;
@@ -50,10 +52,11 @@ public class TruststoreResource {
         return sg;
     }
 
-    @PostMapping(value = "/{id}/certdata", produces = {"application/json"}, consumes = {"application/octet-stream"})
-    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public CertificateRO uploadCertificate(@PathVariable("id") Long id,
-                                               @RequestBody byte[] fileBytes) {
+
+    @PreAuthorize("@smpAuthorizationService.systemAdministrator")
+    @PostMapping(value = "/{user-id}/upload-certificate", consumes = MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    public CertificateRO uploadCertificate(@PathVariable("user-id") String userId,
+                                           @RequestBody byte[] fileBytes) {
         LOG.info("Got truststore cert size: {}", fileBytes.length);
 
         X509Certificate x509Certificate;
@@ -77,10 +80,10 @@ public class TruststoreResource {
 
 
     @DeleteMapping(value = "/{id}/delete/{alias}", produces = {"application/json"})
-    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public KeystoreImportResult deleteCertificate(@PathVariable("id") Long id,
+    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
+    public KeystoreImportResult deleteCertificate(@PathVariable("id") String userId,
                                                @PathVariable("alias") String alias) {
-        LOG.info("Remove alias by user id {}, alias {}.", id, alias);
+        LOG.info("Remove alias by user id {}, alias {}.", userId, alias);
         KeystoreImportResult keystoreImportResult = new KeystoreImportResult();
 
         try {
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/UserAdminResource.java
similarity index 51%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/UserAdminResource.java
index 8040dd2d3a87f77f658eba17020a7d41a5611535..791f86aed93c338e6e448428455730cfceda421d 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/UserAdminResource.java
@@ -1,38 +1,42 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
 import eu.europa.ec.edelivery.smp.auth.SMPAuthenticationToken;
-import eu.europa.ec.edelivery.smp.data.ui.*;
-import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.auth.SMPAuthorizationService;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
+import eu.europa.ec.edelivery.smp.data.ui.CertificateRO;
+import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.data.ui.UserRO;
+import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
+import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UITruststoreService;
 import eu.europa.ec.edelivery.smp.services.ui.UIUserService;
 import eu.europa.ec.edelivery.smp.services.ui.filters.UserFilter;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.annotation.Secured;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.crypto.bcrypt.BCrypt;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.IOException;
-import java.security.cert.CertificateException;
-import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.List;
 
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_INTERNAL_USER;
+
 /**
  * @author Joze Rihtarsic
  * @since 4.1
  */
 @RestController
-@RequestMapping(value = "/ui/rest/user")
-public class UserResource {
+@RequestMapping(value = CONTEXT_PATH_INTERNAL_USER)
+public class UserAdminResource {
 
-    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UserResource.class);
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UserAdminResource.class);
 
     @Autowired
     private UIUserService uiUserService;
@@ -52,82 +56,32 @@ public class UserResource {
             @RequestParam(value = "orderBy", required = false) String orderBy,
             @RequestParam(value = "orderType", defaultValue = "asc", required = false) String orderType,
             @RequestParam(value = "roles", required = false) String roleList
-            ) {
+    ) {
         UserFilter filter = null;
         if (roleList != null) {
             filter = new UserFilter();
             filter.setRoleList(Arrays.asList(roleList.split(",")));
         }
 
-        return  uiUserService.getTableList(page,pageSize, orderBy, orderType, filter);
+        return uiUserService.getTableList(page, pageSize, orderBy, orderType, filter);
     }
 
-    /**
-     * Update the details of the currently logged in user (e.g. update the role, the credentials or add certificate details).
-     *
-     * @param id the identifier of the user being updated; it must match the currently logged in user's identifier
-     * @param user the updated details
-     *
-     * @throws org.springframework.security.access.AccessDeniedException when trying to update the details of another user, different than the one being currently logged in
-     */
-    @PutMapping(path = "/{id}")
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public UserRO updateCurrentUser(@PathVariable("id") Long id, @RequestBody UserRO user) {
-        LOG.info("Update current user: {}", user);
-
-        // Update the user and mark the password as changed at this very instant of time
-        uiUserService.updateUserList(Arrays.asList(user), LocalDateTime.now());
-
-        DBUser updatedUser = uiUserService.findUser(id);
-        UserRO userRO = uiUserService.convertToRo(updatedUser);
-
-        return authorizationService.sanitize(userRO);
-    }
 
     @PutMapping(produces = {"application/json"})
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN})
-    public void updateUserList(@RequestBody UserRO[] updateEntities ){
+    public void updateUserList(@RequestBody UserRO[] updateEntities) {
         LOG.info("Update user list, count: {}", updateEntities.length);
         // Pass the users and mark the passwords of the ones being updated as expired by passing the passwordChange as null
         uiUserService.updateUserList(Arrays.asList(updateEntities), null);
     }
 
-    @PostMapping(value = "/{id}/certdata" ,produces = {"application/json"},consumes = {"application/octet-stream"})
-    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public CertificateRO uploadCertificate(@PathVariable("id") Long id, @RequestBody byte[] data) {
-        LOG.info("Got certificate data size: {}", data.length);
-        try {
-            return uiTruststoreService.getCertificateData(data, true);
-        } catch (IOException | CertificateException e) {
-            LOG.error("Error occurred while parsing certificate.", e);
-        }
-        return null;
-    }
-
-    @PostMapping(value = "/{userId}/generate-access-token" ,produces = {"application/json"})
-    @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
-    public AccessTokenRO generateAccessToken(@PathVariable("userId") Long userId,@RequestBody String password) {
-        AccessTokenRO accessToken = uiUserService.generateAccessTokenForUser(userId);
-        LOG.debug("Access token generated [{}]", accessToken.getIdentifier());
-        accessToken.setGeneratedOn(null);
-        return accessToken;
-    }
-
-    @PostMapping(path = "/{id}/samePreviousPasswordUsed", produces = {"application/json"})
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#id)")
-    public boolean samePreviousPasswordUsed(@PathVariable("id") Long id, @RequestBody String password) {
-        LOG.info("Validating the password of the currently logged in user: {} ", id);
-        DBUser user = uiUserService.findUser(getCurrentUser().getId());
-        return BCrypt.checkpw(password, user.getPassword());
-    }
-
     @PutMapping(produces = {"application/json"})
-    @RequestMapping(path = "validateDelete", method = RequestMethod.POST)
+    @RequestMapping(path = "validate-delete", method = RequestMethod.POST)
     @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN})
     public DeleteEntityValidation validateDeleteUsers(@RequestBody List<Long> query) {
         DBUser user = getCurrentUser();
         DeleteEntityValidation dres = new DeleteEntityValidation();
-        if (query.contains(user.getId())){
+        if (query.contains(user.getId())) {
             dres.setValidOperation(false);
             dres.setStringMessage("Could not delete logged user!");
             return dres;
@@ -141,4 +95,13 @@ public class UserResource {
         SMPAuthenticationToken authToken = (SMPAuthenticationToken) authentication;
         return authToken.getUser();
     }
+
+    public Long decryptEntityId(String userId) {
+        try {
+            return SessionSecurityUtils.decryptEntityId(userId);
+        } catch (RuntimeException runtimeException) {
+            LOG.error("Error occurred while decryption entityId [" + userId + "]!", runtimeException);
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "UserId", "Invalid userId!");
+        }
+    }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/validation/ServiceGroupValidator.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/validation/ServiceGroupValidator.java
index 226f94be6789d2d5053aca405f0d48ddd0000106..2e6c371ba890fdaae4c65dc19fa5c4380bba150c 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/validation/ServiceGroupValidator.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/validation/ServiceGroupValidator.java
@@ -50,6 +50,7 @@ public class ServiceGroupValidator {
 
         String scheme = serviceGroup.getParticipantIdentifier().getScheme();
         Pattern schemaPattern = configurationService.getParticipantIdentifierSchemeRexExp();
+
         if (!schemaPattern.matcher(scheme).matches()) {
             throw new BadRequestException(WRONG_FIELD, "Service Group scheme does not match allowed pattern: " + schemaPattern.pattern());
         }
diff --git a/smp-webapp/src/main/resources/logback.xml b/smp-webapp/src/main/resources/logback.xml
index 80975ef8062427a829306c8deee59a8739f47b24..e8c6bfdc10ee6c94c6f892b81122d2aed3f8dd2c 100644
--- a/smp-webapp/src/main/resources/logback.xml
+++ b/smp-webapp/src/main/resources/logback.xml
@@ -2,8 +2,8 @@
 
 <configuration>
     <!-- pattern definition -->
-    <property name="encoderPattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
-    <property name="consolePattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="encoderPattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="consolePattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
 
      <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <file>${log.folder:-logs}/edelivery-smp.log</file>
diff --git a/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl b/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl
index 714e760f9b473eb63a83ab111326ffd015503de1..dc0553b8ba3f8664eb109218f1a1c3c4079d3917 100644
--- a/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl
+++ b/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl
@@ -233,7 +233,8 @@
     create table SMP_USER (
        ID bigint not null comment 'Unique user id',
         ACCESS_TOKEN varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin comment 'BCrypted personal access token',
-        PAT_GENERATED datetime comment 'Date when personal access token was generated',
+        ACCESS_TOKEN_EXPIRE_ON datetime comment 'Date when personal access token will expire',
+        ACCESS_TOKEN_GENERATED_ON datetime comment 'Date when personal access token was generated',
         ACCESS_TOKEN_ID varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin comment 'Personal access token id',
         ACTIVE bit not null comment 'Is user active',
         CREATED_ON datetime not null,
@@ -241,8 +242,9 @@
         LAST_UPDATED_ON datetime not null,
         PASSWORD varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin comment 'BCrypted password for username/password login',
         PASSWORD_CHANGED datetime comment 'Last date when password was changed',
+        PASSWORD_EXPIRE_ON datetime comment 'Date when password will expire',
         ROLE varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin comment 'User role',
-        USERNAME varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin comment 'Login username',
+        USERNAME varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin not null comment 'Unique username identifier. The Username must not be null',
         primary key (ID)
     ) comment='SMP can handle multiple domains. This table contains domain specific data' ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
@@ -251,7 +253,8 @@
         REV bigint not null,
         REVTYPE tinyint,
         ACCESS_TOKEN varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin,
-        PAT_GENERATED datetime,
+        ACCESS_TOKEN_EXPIRE_ON datetime,
+        ACCESS_TOKEN_GENERATED_ON datetime,
         ACCESS_TOKEN_ID varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin,
         ACTIVE bit,
         CREATED_ON datetime,
@@ -259,6 +262,7 @@
         LAST_UPDATED_ON datetime,
         PASSWORD varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin,
         PASSWORD_CHANGED datetime,
+        PASSWORD_EXPIRE_ON datetime,
         ROLE varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin,
         USERNAME varchar(256)  CHARACTER SET utf8 COLLATE utf8_bin,
         primary key (ID, REV)
diff --git a/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl b/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl
index bc1fad113181797ff2f63ddfe6e0d0e3e2916b80..190d4ee1343e01b65e9d465229d957b551e8dca6 100644
--- a/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl
+++ b/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl
@@ -314,7 +314,8 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
     create table SMP_USER (
        ID number(19,0) not null,
         ACCESS_TOKEN varchar2(256 char),
-        PAT_GENERATED timestamp,
+        ACCESS_TOKEN_EXPIRE_ON timestamp,
+        ACCESS_TOKEN_GENERATED_ON timestamp,
         ACCESS_TOKEN_ID varchar2(256 char),
         ACTIVE number(1,0) not null,
         CREATED_ON timestamp not null,
@@ -322,8 +323,9 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
         LAST_UPDATED_ON timestamp not null,
         PASSWORD varchar2(256 char),
         PASSWORD_CHANGED timestamp,
+        PASSWORD_EXPIRE_ON timestamp,
         ROLE varchar2(256 char),
-        USERNAME varchar2(256 char),
+        USERNAME varchar2(256 char) not null,
         primary key (ID)
     );
 
@@ -336,7 +338,10 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
     comment on column SMP_USER.ACCESS_TOKEN is
         'BCrypted personal access token';
 
-    comment on column SMP_USER.PAT_GENERATED is
+    comment on column SMP_USER.ACCESS_TOKEN_EXPIRE_ON is
+        'Date when personal access token will expire';
+
+    comment on column SMP_USER.ACCESS_TOKEN_GENERATED_ON is
         'Date when personal access token was generated';
 
     comment on column SMP_USER.ACCESS_TOKEN_ID is
@@ -354,18 +359,22 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
     comment on column SMP_USER.PASSWORD_CHANGED is
         'Last date when password was changed';
 
+    comment on column SMP_USER.PASSWORD_EXPIRE_ON is
+        'Date when password will expire';
+
     comment on column SMP_USER.ROLE is
         'User role';
 
     comment on column SMP_USER.USERNAME is
-        'Login username';
+        'Unique username identifier. The Username must not be null';
 
     create table SMP_USER_AUD (
        ID number(19,0) not null,
         REV number(19,0) not null,
         REVTYPE number(3,0),
         ACCESS_TOKEN varchar2(256 char),
-        PAT_GENERATED timestamp,
+        ACCESS_TOKEN_EXPIRE_ON timestamp,
+        ACCESS_TOKEN_GENERATED_ON timestamp,
         ACCESS_TOKEN_ID varchar2(256 char),
         ACTIVE number(1,0),
         CREATED_ON timestamp,
@@ -373,6 +382,7 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
         LAST_UPDATED_ON timestamp,
         PASSWORD varchar2(256 char),
         PASSWORD_CHANGED timestamp,
+        PASSWORD_EXPIRE_ON timestamp,
         ROLE varchar2(256 char),
         USERNAME varchar2(256 char),
         primary key (ID, REV)
diff --git a/smp-webapp/src/main/smp-setup/logback.xml b/smp-webapp/src/main/smp-setup/logback.xml
index 10dd2cf59904b282efdc42c1ed8cd220c06f6e6d..41767c18636663607bc909d8f94d1cf538ef4fd1 100644
--- a/smp-webapp/src/main/smp-setup/logback.xml
+++ b/smp-webapp/src/main/smp-setup/logback.xml
@@ -2,8 +2,8 @@
 
 <configuration>
     <!-- pattern definition -->
-    <property name="encoderPattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
-    <property name="consolePattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="encoderPattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="consolePattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
 
      <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <file>${log.folder:-logs}/edelivery-smp.log</file>
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java
index 9f00528cc2a2a6340ba9be066bf5301eaa3b8322..8301ba2792886b6a4306fdceb64a586862904d4d 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java
@@ -2,8 +2,10 @@ package eu.europa.ec.edelivery.smp.auth;
 
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
 import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.junit.Before;
 import org.junit.Test;
+import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
@@ -16,17 +18,18 @@ import static org.junit.Assert.assertTrue;
 
 public class SMPAuthorizationServiceTest {
 
-    DBUser mockUser = null;
+    DBUser user = null;
     SecurityContext mockSecurityContextSystemAdmin = null;
 
     SecurityContext mockSecurityContextSGAdmin = null;
 
     SMPAuthorizationService testInstance = new SMPAuthorizationService();
 
+
     @Before
     public void setup() {
 
-        DBUser user = new DBUser();
+        user = new DBUser();
         user.setId((long) 10);
 
 
@@ -74,13 +77,13 @@ public class SMPAuthorizationServiceTest {
         assertTrue(bVal);
     }
 
-    @Test
+    @Test(expected = BadCredentialsException.class)
     public void isCurrentlyLoggedInNotLogedIn() {
         // given
         SecurityContextHolder.setContext(mockSecurityContextSystemAdmin);
 
-        boolean bVal = testInstance.isCurrentlyLoggedIn((long) 1);
-        assertFalse(bVal);
+        testInstance.isCurrentlyLoggedIn("Not logged In");
+
     }
 
     @Test
@@ -88,11 +91,7 @@ public class SMPAuthorizationServiceTest {
         // given
         SecurityContextHolder.setContext(mockSecurityContextSystemAdmin);
         // when then
-        boolean bVal = testInstance.isCurrentlyLoggedIn((long) 10);
+        boolean bVal = testInstance.isCurrentlyLoggedIn(SessionSecurityUtils.encryptedEntityId(10L));
         assertTrue(bVal);
     }
-
-    public void sanitize() {
-
-    }
 }
\ No newline at end of file
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/SMPSecurityExceptionHandlerTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/SMPSecurityExceptionHandlerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..65d893151d5567c2d07d8dc31fe5716c26db5b3a
--- /dev/null
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/SMPSecurityExceptionHandlerTest.java
@@ -0,0 +1,137 @@
+package eu.europa.ec.edelivery.smp.error;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import ec.services.smp._1.ErrorResponse;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+import java.io.StringReader;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.springframework.http.HttpStatus.UNAUTHORIZED;
+
+public class SMPSecurityExceptionHandlerTest {
+
+    SMPSecurityExceptionHandler testInstance = new SMPSecurityExceptionHandler();
+
+    @Test
+    public void isUITRestRequestPublic() {
+        // given
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        Mockito.doReturn(ResourceConstants.CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT).when(request).getRequestURI();
+        // when
+        boolean result = testInstance.isUITRestRequest(request);
+        // then
+        assertTrue(result);
+    }
+
+    @Test
+    public void isUITRestRequestInternal() {
+        // given
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        Mockito.doReturn("smp" + ResourceConstants.CONTEXT_PATH_INTERNAL_APPLICATION).when(request).getRequestURI();
+        // when
+        boolean result = testInstance.isUITRestRequest(request);
+        // then
+        assertTrue(result);
+    }
+
+    @Test
+    public void isUITRestRequestSMPServiceEndpoint() {
+        // given
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        Mockito.doReturn("/smp").when(request).getContextPath();
+        // when
+        boolean result = testInstance.isUITRestRequest(request);
+        // then
+        assertFalse(result);
+    }
+
+
+    @Test
+    public void marshallToXML() throws JAXBException {
+        ErrorResponse error = ErrorResponseBuilder.status(UNAUTHORIZED)
+                .businessCode(ErrorBusinessCode.UNAUTHORIZED)
+                .errorDescription("Test error Message")
+                .buildBody();
+        // when
+        String resultString = testInstance.marshallToXML(error);
+        // then
+        assertNotNull(resultString);
+        //calling the unmarshall method
+        ErrorResponse result = (ErrorResponse) JAXBContext.newInstance(ErrorResponse.class)
+                .createUnmarshaller()
+                .unmarshal(new StringReader(resultString));
+
+        assertEquals(error.getBusinessCode(), result.getBusinessCode());
+        assertEquals(error.getErrorDescription(), result.getErrorDescription());
+        assertEquals(error.getErrorUniqueId(), result.getErrorUniqueId());
+    }
+
+    @Test
+    public void marshallToJSon() throws IOException {
+        ErrorResponse error = ErrorResponseBuilder.status(UNAUTHORIZED)
+                .businessCode(ErrorBusinessCode.UNAUTHORIZED)
+                .errorDescription("Test json error Message")
+                .buildBody();
+        // when
+        String resultString = testInstance.marshallToJSon(error);
+        // then
+        assertNotNull(resultString);
+        //calling the unmarshall method
+        ErrorResponse result = (new ObjectMapper()).readValue(resultString, ErrorResponse.class);
+
+        assertEquals(error.getBusinessCode(), result.getBusinessCode());
+        assertEquals(error.getErrorDescription(), result.getErrorDescription());
+        assertEquals(error.getErrorUniqueId(), result.getErrorUniqueId());
+    }
+    @Test
+    public void marshallUIError() throws JsonProcessingException {
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        Mockito.doReturn(ResourceConstants.CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT).when(request).getRequestURI();
+        ErrorResponse error = ErrorResponseBuilder.status(UNAUTHORIZED)
+                .businessCode(ErrorBusinessCode.UNAUTHORIZED)
+                .errorDescription("Test error Message")
+                .buildBody();
+
+        String resultString = testInstance.marshall(error, request);
+        // then
+        assertNotNull(resultString);
+        //calling the unmarshall method for JSON
+        ErrorResponse result = (new ObjectMapper()).readValue(resultString, ErrorResponse.class);
+
+        assertEquals(error.getBusinessCode(), result.getBusinessCode());
+        assertEquals(error.getErrorDescription(), result.getErrorDescription());
+        assertEquals(error.getErrorUniqueId(), result.getErrorUniqueId());
+    }
+
+    @Test
+    public void marshallXMLError() throws  JAXBException {
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        Mockito.doReturn("/smp/test-test-test::0001:test").when(request).getRequestURI();
+        ErrorResponse error = ErrorResponseBuilder.status(UNAUTHORIZED)
+                .businessCode(ErrorBusinessCode.UNAUTHORIZED)
+                .errorDescription("Test error Message")
+                .buildBody();
+
+        String resultString = testInstance.marshall(error, request);
+        // then
+        assertNotNull(resultString);
+        //calling the unmarshall method for XML
+        ErrorResponse result = (ErrorResponse) JAXBContext.newInstance(ErrorResponse.class)
+                .createUnmarshaller()
+                .unmarshal(new StringReader(resultString));
+
+        assertEquals(error.getBusinessCode(), result.getBusinessCode());
+        assertEquals(error.getErrorDescription(), result.getErrorDescription());
+        assertEquals(error.getErrorUniqueId(), result.getErrorUniqueId());
+    }
+}
\ No newline at end of file
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdviceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdviceTest.java
similarity index 92%
rename from smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdviceTest.java
rename to smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdviceTest.java
index 2e5278c0f37b178b0669f5944bbe5d8f34cd540b..a97d1a6480e188a6cf6475583ae04fa0dec6c7ed 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/ErrorMappingControllerAdviceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdviceTest.java
@@ -13,9 +13,9 @@ import org.springframework.security.core.AuthenticationException;
 import static org.junit.Assert.*;
 import static org.springframework.http.HttpStatus.*;
 
-public class ErrorMappingControllerAdviceTest {
+public class ServiceErrorControllerAdviceTest {
 
-    ErrorMappingControllerAdvice testIntance = new ErrorMappingControllerAdvice();
+    ServiceErrorControllerAdvice testIntance = new ServiceErrorControllerAdvice();
 
     @Test
     public void handleRuntimeException() {
@@ -48,7 +48,7 @@ public class ErrorMappingControllerAdviceTest {
     @Test
     public void handleAuthenticationException() {
 
-        ResponseEntity re = testIntance.handleAuthenticationException(new AuthenticationException("AuthenticationException") {
+        ResponseEntity re = testIntance.handleRuntimeException(new AuthenticationException("AuthenticationException") {
             @Override
             public String getMessage() {
                 return super.getMessage();
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResourceTest.java
index 8679a2aeed44a296b34945414647cbadf66bde88..df1be54540ac154dd23dab5fd92147ad2fc12b3c 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/AuthenticationResourceTest.java
@@ -4,7 +4,10 @@ import eu.europa.ec.edelivery.smp.config.PropertiesTestConfig;
 import eu.europa.ec.edelivery.smp.config.SmpAppConfig;
 import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
 import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
+import eu.europa.ec.edelivery.smp.error.ServiceErrorControllerAdvice;
+import eu.europa.ec.edelivery.smp.error.UIErrorControllerAdvice;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -36,14 +39,17 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
         PropertiesTestConfig.class,
         SmpAppConfig.class,
         SmpWebAppConfig.class,
-        SpringSecurityConfig.class})
+        SpringSecurityConfig.class,
+        UIErrorControllerAdvice.class,
+        ServiceErrorControllerAdvice.class})
 @WebAppConfiguration
 @Sql("classpath:/cleanup-database.sql")
 @Sql("classpath:/webapp_integration_test_data.sql")
 @SqlConfig(encoding = "UTF-8")
 public class AuthenticationResourceTest {
 
-    private static final String PATH = "/ui/rest/security/authentication";
+
+    private static final String PATH = ResourceConstants.CONTEXT_PATH_PUBLIC_SECURITY+"/authentication";
 
     @Autowired
     private WebApplicationContext webAppContext;
@@ -84,6 +90,7 @@ public class AuthenticationResourceTest {
 
 
     @Test
+    @Ignore
     public void authenticateInvalidPasswordTest() throws Exception {
 
         // given when then
@@ -96,6 +103,7 @@ public class AuthenticationResourceTest {
     }
 
     @Test
+    @Ignore
     public void authenticateInvalidUsernameTest() throws Exception {
 
         // given when
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResourceTest.java
index eb764c375a184f775831c25a915b78fb80954a1c..d5e050cd61c9cf9e37df52182cb9cfd0f5bf1bb3 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ServiceGroupResourceTest.java
@@ -62,7 +62,7 @@ public class ServiceGroupResourceTest {
     @Autowired
     ServiceGroupDao serviceGroupDao;
 
-    private static final String PATH = "/ui/rest/servicegroup";
+    private static final String PATH_PUBLIC = ResourceConstants.CONTEXT_PATH_PUBLIC_SERVICE_GROUP;
 
     private static final String PARTICIPANT_IDENTIFIER = "urn:australia:ncpb";
     private static final String PARTICIPANT_SCHEME = "ehealth-actorid-qns";
@@ -95,7 +95,7 @@ public class ServiceGroupResourceTest {
     @Test
     public void getServiceGroupListForSMPAdmin() throws Exception {
         // given when
-        MvcResult result = mvc.perform(get(PATH)
+        MvcResult result = mvc.perform(get(PATH_PUBLIC)
                 .with(SMP_ADMIN_CREDENTIALS).with(csrf())
         ).andExpect(status().isOk()).andReturn();
 
@@ -119,7 +119,7 @@ public class ServiceGroupResourceTest {
     @Test
     public void getServiceGroupListForServiceGroupAdmin() throws Exception {
         // given when
-        MvcResult result = mvc.perform(get(PATH)
+        MvcResult result = mvc.perform(get(PATH_PUBLIC)
                 .with(SG_ADMIN_CREDENTIALS).with(csrf())
         ).andExpect(status().isOk()).andReturn();
 
@@ -143,7 +143,7 @@ public class ServiceGroupResourceTest {
     public void getServiceGroupById() throws Exception {
 
         // given when
-        MvcResult result = mvc.perform(get(PATH + "/100000")
+        MvcResult result = mvc.perform(get(PATH_PUBLIC + "/100000")
                 .with(SMP_ADMIN_CREDENTIALS).with(csrf())).
                 andExpect(status().isOk()).andReturn();
 
@@ -172,7 +172,7 @@ public class ServiceGroupResourceTest {
         serviceGroupDao.update(sg);
 
         // given when
-        MvcResult result = mvc.perform(get(PATH + "/extension/100000")
+        MvcResult result = mvc.perform(get(PATH_PUBLIC + "/extension/100000")
                 .with(SMP_ADMIN_CREDENTIALS).with(csrf()))
                 .andExpect(status().isOk()).andReturn();
 
@@ -194,7 +194,7 @@ public class ServiceGroupResourceTest {
         validate.setExtension(validExtension + "<ADFA>sdfadsf");
 
         // given when
-        MvcResult result = mvc.perform(post(PATH + "/extension/validate")
+        MvcResult result = mvc.perform(post(PATH_PUBLIC + "/extension/validate")
                 .with(SMP_ADMIN_CREDENTIALS)
                 .header("Content-Type","application/json")
                     .content(mapper.writeValueAsString(validate))
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/UserResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/UserResourceTest.java
index 0b2161a44e7506af30763f54295a9b25455532e2..7956ebbe95fe95db7dfc13f3b61dc0f62080ff2a 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/UserResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/UserResourceTest.java
@@ -13,9 +13,11 @@ import eu.europa.ec.edelivery.smp.testutils.X509CertificateTestUtils;
 import org.apache.commons.io.IOUtils;
 import org.hamcrest.CoreMatchers;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockHttpSession;
 import org.springframework.mock.web.MockServletContext;
 import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
 import org.springframework.test.context.ContextConfiguration;
@@ -32,6 +34,7 @@ import org.springframework.web.context.WebApplicationContext;
 
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
+import javax.servlet.http.HttpSession;
 import javax.ws.rs.core.MediaType;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
@@ -60,7 +63,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 @SqlConfig(encoding = "UTF-8")
 public class UserResourceTest {
 
-    private static final String PATH = "/ui/rest/user";
+    private static final String PATH_INTERNAL = ResourceConstants.CONTEXT_PATH_INTERNAL_USER;
+    private static final String PATH_PUBLIC = ResourceConstants.CONTEXT_PATH_PUBLIC_USER;
+    private static final String PATH_AUTHENTICATION = ResourceConstants.CONTEXT_PATH_PUBLIC_SECURITY+"/authentication";
+
 
     @Autowired
     private WebApplicationContext webAppContext;
@@ -88,7 +94,7 @@ public class UserResourceTest {
     @Test
     public void getUserList() throws Exception {
         // given when
-        MvcResult result = mvc.perform(get(PATH)
+        MvcResult result = mvc.perform(get(PATH_INTERNAL)
                 .with(ADMIN_CREDENTIALS)
                 .with(csrf()))
                 .andExpect(status().isOk()).andReturn();
@@ -102,17 +108,18 @@ public class UserResourceTest {
         assertEquals(10, res.getServiceEntities().size());
         res.getServiceEntities().forEach(sgMap -> {
             UserRO sgro = mapper.convertValue(sgMap, UserRO.class);
-            assertNotNull(sgro.getId());
+            assertNotNull(sgro.getUserId());
             assertNotNull(sgro.getUsername());
             assertNotNull(sgro.getRole());
         });
     }
 
     @Test
+    @Ignore
     public void testUpdateCurrentUserOK() throws Exception {
 
         // given when - log as SMP admin
-        MvcResult result = mvc.perform(post("/ui/rest/security/authentication")
+        MvcResult result = mvc.perform(post(PATH_AUTHENTICATION)
                 .header("Content-Type", "application/json")
                 .content("{\"username\":\"smp_admin\",\"password\":\"test123\"}"))
                 .andExpect(status().isOk()).andReturn();
@@ -120,6 +127,8 @@ public class UserResourceTest {
         UserRO userRO = mapper.readValue(result.getResponse().getContentAsString(), UserRO.class);
         assertNotNull(userRO);
 
+        MockHttpSession session = (MockHttpSession)result.getRequest().getSession();
+
         // when
         userRO.setActive(!userRO.isActive());
         userRO.setEmailAddress("test@mail.com");
@@ -129,9 +138,10 @@ public class UserResourceTest {
         }
         userRO.getCertificate().setCertificateId(UUID.randomUUID().toString());
 
-        mvc.perform(put(PATH + "/" + userRO.getId())
+        mvc.perform(put(PATH_PUBLIC + "/" + userRO.getUserId())
                 .with(ADMIN_CREDENTIALS)
                 .with(csrf())
+                .session(session)
                 .contentType(MediaType.APPLICATION_JSON)
                 .content(mapper.writeValueAsString(userRO))
         ).andExpect(status().isOk()).andReturn();
@@ -142,7 +152,7 @@ public class UserResourceTest {
 
         // given when - log as SMP admin
         // then change values and list uses for changed value
-        MvcResult result = mvc.perform(post("/ui/rest/security/authentication")
+        MvcResult result = mvc.perform(post(PATH_AUTHENTICATION)
                 .header("Content-Type", "application/json")
                 .content("{\"username\":\"smp_admin\",\"password\":\"test123\"}"))
                 .andExpect(status().isOk()).andReturn();
@@ -159,7 +169,7 @@ public class UserResourceTest {
         }
         userRO.getCertificate().setCertificateId(UUID.randomUUID().toString());
 
-        mvc.perform(put(PATH + "/" + userRO.getId())
+        mvc.perform(put(PATH_PUBLIC + "/" + userRO.getUserId())
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .contentType(MediaType.APPLICATION_JSON)
@@ -170,7 +180,7 @@ public class UserResourceTest {
     @Test
     public void testUpdateUserList() throws Exception {
         // given when
-        MvcResult result = mvc.perform(get(PATH)
+        MvcResult result = mvc.perform(get(PATH_INTERNAL)
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf()))
                 .andExpect(status().isOk()).andReturn();
@@ -188,7 +198,7 @@ public class UserResourceTest {
         }
         userRO.getCertificate().setCertificateId(UUID.randomUUID().toString());
 
-        mvc.perform(put(PATH)
+        mvc.perform(put(PATH_INTERNAL)
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .contentType(MediaType.APPLICATION_JSON)
@@ -199,7 +209,7 @@ public class UserResourceTest {
     @Test
     public void testUpdateUserListWrongAuthentication() throws Exception {
         // given when
-        MvcResult result = mvc.perform(get(PATH)
+        MvcResult result = mvc.perform(get(PATH_INTERNAL)
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf()))
                 .andExpect(status().isOk()).andReturn();
@@ -217,20 +227,20 @@ public class UserResourceTest {
         }
         userRO.getCertificate().setCertificateId(UUID.randomUUID().toString());
         // anonymous
-        mvc.perform(put(PATH)
+        mvc.perform(put(PATH_INTERNAL)
                 .with(csrf())
                 .contentType(MediaType.APPLICATION_JSON)
                 .content(mapper.writeValueAsString(Arrays.asList(userRO)))
         ).andExpect(status().isUnauthorized());
 
-        mvc.perform(put(PATH)
+        mvc.perform(put(PATH_INTERNAL)
                 .with(ADMIN_CREDENTIALS)
                 .with(csrf())
                 .contentType(MediaType.APPLICATION_JSON)
                 .content(mapper.writeValueAsString(Arrays.asList(userRO)))
         ).andExpect(status().isUnauthorized());
 
-        mvc.perform(put(PATH)
+        mvc.perform(put(PATH_INTERNAL)
                 .with(SG_ADMIN_CREDENTIALS)
                 .with(csrf())
                 .contentType(MediaType.APPLICATION_JSON)
@@ -238,114 +248,9 @@ public class UserResourceTest {
         ).andExpect(status().isUnauthorized());
     }
 
-    @Test
-    public void uploadCertificateSystemAdmin() throws Exception {
-        byte[] buff = IOUtils.toByteArray(UserResourceTest.class.getResourceAsStream("/SMPtest.crt"));
-
-        // given when
-        MvcResult result = mvc.perform(post(PATH + "/1098765430/certdata")
-                .with(SYSTEM_CREDENTIALS)
-                .with(csrf())
-                .content(buff))
-                .andExpect(status().isOk()).andReturn();
-
-        //then
-        ObjectMapper mapper = new ObjectMapper();
-        CertificateRO res = mapper.readValue(result.getResponse().getContentAsString(), CertificateRO.class);
-
-        assertNotNull(res);
-        assertEquals("CN=Intermediate CA,O=DIGIT,C=BE", res.getIssuer());
-        assertEquals("1.2.840.113549.1.9.1=#160c736d7040746573742e636f6d,CN=SMP test,O=DIGIT,C=BE", res.getSubject());
-        assertEquals("3", res.getSerialNumber());
-        assertEquals("CN=SMP test,O=DIGIT,C=BE:0000000000000003", res.getCertificateId());
-        assertEquals("sno=3&subject=1.2.840.113549.1.9.1%3D%23160c736d7040746573742e636f6d%2CCN%3DSMP+test%2CO%3DDIGIT%2CC%3DBE&validfrom=May+22+20%3A59%3A00+2018+GMT&validto=May+22+20%3A56%3A00+2019+GMT&issuer=CN%3DIntermediate+CA%2CO%3DDIGIT%2CC%3DBE", res.getBlueCoatHeader());
-    }
-
-    @Test
-    public void uploadInvalidCertificate() throws Exception {
-        byte[] buff = (new String("Not a certficate :) ")).getBytes();
-
-        // given when
-        mvc.perform(post(PATH + "/1098765430/certdata")
-                .with(SYSTEM_CREDENTIALS)
-                .with(csrf())
-                .content(buff))
-                .andExpect(status().is5xxServerError())
-                .andExpect(content().string(CoreMatchers.containsString(" The certificate is not valid")));
-
-    }
-
-    @Test
-    public void uploadCertificateIdWithEmailSerialNumberInSubjectCertIdTest() throws Exception {
-        String subject = "CN=common name,emailAddress=CEF-EDELIVERY-SUPPORT@ec.europa.eu,serialNumber=1,O=org,ST=My town,postalCode=2151, L=GreatTown,street=My Street. 20, C=BE";
-        String serialNumber = "1234321";
-        X509Certificate certificate = X509CertificateTestUtils.createX509CertificateForTest(serialNumber, subject);
-        byte[] buff = certificate.getEncoded();
-        // given when
-        MvcResult result = mvc.perform(post(PATH + "/1098765430/certdata")
-                .with(SYSTEM_CREDENTIALS)
-                .with(csrf())
-                .content(buff))
-                .andExpect(status().isOk()).andReturn();
-
-        //them
-        ObjectMapper mapper = new ObjectMapper();
-        CertificateRO res = mapper.readValue(result.getResponse().getContentAsString(), CertificateRO.class);
-
-        assertEquals("CN=common name,O=org,C=BE:0000000001234321", res.getCertificateId());
-    }
-
-    @Test
-    public void uploadCertificateInvalidUser() throws Exception {
-        byte[] buff = IOUtils.toByteArray(UserResourceTest.class.getResourceAsStream("/SMPtest.crt"));
-        // id and logged user not match
-        // given when
-        mvc.perform(post(PATH + "/34556655/certdata")
-                .with(ADMIN_CREDENTIALS)
-                .with(csrf())
-                .content(buff))
-                .andExpect(status().isUnauthorized()).andReturn();
-    }
-
-    @Test
-    public void samePreviousPasswordUsedTrue() throws Exception {
-        // 1 is id for smp_admin
-        MvcResult result = mvc.perform(post(PATH + "/1/samePreviousPasswordUsed")
-                .with(ADMIN_CREDENTIALS)
-                .with(csrf())
-                .content("test123"))
-                .andExpect(status().isOk()).andReturn();
-
-        assertNotNull(result);
-        assertEquals("true", result.getResponse().getContentAsString());
-    }
-
-    @Test
-    public void samePreviousPasswordUsedFalse() throws Exception {
-        // 1 is id for smp_admin
-        MvcResult result = mvc.perform(post(PATH + "/1/samePreviousPasswordUsed")
-                .with(ADMIN_CREDENTIALS)
-                .with(csrf())
-                .content("7777"))
-                .andExpect(status().isOk()).andReturn();
-
-        assertNotNull(result);
-        assertEquals("false", result.getResponse().getContentAsString());
-    }
-
-    @Test
-    public void samePreviousPasswordUsedUnauthorized() throws Exception {
-        // 1 is id for smp_admin so for 3 should be Unauthorized
-        MvcResult result = mvc.perform(post(PATH + "/3/samePreviousPasswordUsed")
-                .with(ADMIN_CREDENTIALS)
-                .with(csrf())
-                .content("test123"))
-                .andExpect(status().isUnauthorized()).andReturn();
-    }
-
     @Test
     public void testValidateDeleteUserOK() throws Exception {
-        MvcResult result = mvc.perform(post(PATH + "/validateDelete")
+        MvcResult result = mvc.perform(post(PATH_INTERNAL + "/validate-delete")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .contentType(org.springframework.http.MediaType.APPLICATION_JSON)
@@ -363,7 +268,7 @@ public class UserResourceTest {
     @Test
     public void testValidateDeleteUserNotOK() throws Exception {
         // note system credential has id 3!
-        MvcResult result = mvc.perform(post(PATH + "/validateDelete")
+        MvcResult result = mvc.perform(post(PATH_INTERNAL + "/validate-delete")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .contentType(org.springframework.http.MediaType.APPLICATION_JSON)
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/ApplicationResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/ApplicationResourceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a42b7d09297a1cc9690a27e7dc877425e8455e2e
--- /dev/null
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/ApplicationResourceTest.java
@@ -0,0 +1,108 @@
+package eu.europa.ec.edelivery.smp.ui.external;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import eu.europa.ec.edelivery.smp.config.PropertiesTestConfig;
+import eu.europa.ec.edelivery.smp.config.SmpAppConfig;
+import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
+import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
+import eu.europa.ec.edelivery.smp.data.ui.SmpInfoRO;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.jdbc.SqlConfig;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.ContextLoaderListener;
+import org.springframework.web.context.WebApplicationContext;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {
+        PropertiesTestConfig.class,
+        SmpAppConfig.class,
+        SmpWebAppConfig.class,
+        SpringSecurityConfig.class})
+@WebAppConfiguration
+@SqlConfig(encoding = "UTF-8")
+@Sql(scripts = {"classpath:cleanup-database.sql",
+        "classpath:webapp_integration_test_data.sql"
+}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
+@TestPropertySource(properties = {
+        "smp.artifact.name=TestApplicationSmpName",
+        "smp.artifact.version=TestApplicationVersion",
+        "smp.artifact.build.time=2018-11-27 00:00:00",
+})
+public class ApplicationResourceTest {
+    private static final String PATH = ResourceConstants.CONTEXT_PATH_PUBLIC_APPLICATION;
+
+    @Autowired
+    private WebApplicationContext webAppContext;
+
+    @Autowired
+    private ApplicationResource applicationResource;
+
+    private MockMvc mvc;
+
+    @Before
+    public void setup() {
+        mvc = MockMvcBuilders.webAppContextSetup(webAppContext)
+                .apply(SecurityMockMvcConfigurers.springSecurity())
+                .build();
+        initServletContext();
+    }
+
+    private void initServletContext() {
+        MockServletContext sc = new MockServletContext("");
+        ServletContextListener listener = new ContextLoaderListener(webAppContext);
+        ServletContextEvent event = new ServletContextEvent(sc);
+    }
+
+    @Test
+    public void testGetName() throws Exception {
+        String value = mvc.perform(get(PATH + "/name"))
+                .andExpect(status().isOk())
+                .andReturn()
+                .getResponse()
+                .getContentAsString();
+
+        assertEquals("TestApplicationSmpName", value);
+    }
+
+    @Test
+    public void getDisplayName() throws Exception {
+        String value = applicationResource.getDisplayVersion();
+        assertEquals("TestApplicationSmpName Version [TestApplicationVersion] Build-Time [2018-11-27 00:00:00|Central European Time]", value);
+    }
+
+    @Test
+    public void getApplicationInfoTest() throws Exception {
+        String value = mvc.perform(get(PATH + "/info"))
+                .andExpect(status().isOk())
+                .andReturn()
+                .getResponse()
+                .getContentAsString();
+        ObjectMapper mapper = new ObjectMapper();
+        SmpInfoRO info = mapper.readValue(value, SmpInfoRO.class);
+
+        assertEquals("TestApplicationSmpName Version [TestApplicationVersion] Build-Time [2018-11-27 00:00:00|Central European Time]", info.getVersion());
+        assertEquals(false, info.isSmlIntegrationOn());
+        assertEquals("/", info.getContextPath());
+    }
+}
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..61858cb3d11a9a4523efcf83c46ea2a3e8de1242
--- /dev/null
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceTest.java
@@ -0,0 +1,105 @@
+package eu.europa.ec.edelivery.smp.ui.external;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import eu.europa.ec.edelivery.smp.config.*;
+import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
+import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
+import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockServletContext;
+import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.jdbc.SqlConfig;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.request.RequestPostProcessor;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.ContextLoaderListener;
+import org.springframework.web.context.WebApplicationContext;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import static org.hamcrest.Matchers.stringContainsInOrder;
+import static org.junit.Assert.*;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {
+        PropertiesTestConfig.class,
+        SmpAppConfig.class,
+        SmpWebAppConfig.class,
+        SpringSecurityConfig.class})
+@WebAppConfiguration
+@Sql("classpath:/cleanup-database.sql")
+@Sql("classpath:/webapp_integration_test_data.sql")
+@SqlConfig(encoding = "UTF-8")
+public class DomainResourceTest {
+    private static final String PATH = ResourceConstants.CONTEXT_PATH_PUBLIC_DOMAIN;
+
+    @Autowired
+    private WebApplicationContext webAppContext;
+    @Autowired
+    DomainDao domainDao;
+
+    private MockMvc mvc;
+
+    @Before
+    public void setup() {
+        mvc = MockMvcBuilders.webAppContextSetup(webAppContext)
+                .apply(SecurityMockMvcConfigurers.springSecurity())
+                .build();
+
+        initServletContext();
+    }
+
+    private void initServletContext() {
+        MockServletContext sc = new MockServletContext("");
+        ServletContextListener listener = new ContextLoaderListener(webAppContext);
+        ServletContextEvent event = new ServletContextEvent(sc);
+    }
+
+
+    @Test
+    public void geDomainPublicList() throws Exception {
+
+        // given when
+        MvcResult result = mvc.perform(get(PATH)
+                .with(csrf()))
+                .andExpect(status().isOk()).andReturn();
+
+        //them
+        ObjectMapper mapper = new ObjectMapper();
+        ServiceResult res = mapper.readValue(result.getResponse().getContentAsString(), ServiceResult.class);
+
+
+        assertNotNull(res);
+        assertEquals(2, res.getServiceEntities().size());
+        res.getServiceEntities().forEach(sgMap -> {
+            DomainRO sgro = mapper.convertValue(sgMap, DomainRO.class);
+            assertNotNull(sgro.getDomainCode());
+            assertNotNull(sgro.getSmlSubdomain());
+            // for public endpot all other data must be null!
+            assertNull(sgro.getId());
+            assertNull(sgro.getSmlSmpId());
+            assertNull(sgro.getSignatureKeyAlias());
+            assertNull(sgro.getSmlParticipantIdentifierRegExp());
+        });
+    }
+}
\ No newline at end of file
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/SearchResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/SearchResourceTest.java
similarity index 91%
rename from smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/SearchResourceTest.java
rename to smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/SearchResourceTest.java
index d80da95a0c6d63c7f9766b98316912e4c17c288f..7997213e400270e3bc02c18fe27dcdf2ff0c8c57 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/SearchResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/SearchResourceTest.java
@@ -1,4 +1,4 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.external;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import eu.europa.ec.edelivery.smp.config.PropertiesTestConfig;
@@ -7,6 +7,7 @@ import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
 import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,6 +29,7 @@ import org.springframework.web.context.WebApplicationContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
 
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT;
 import static org.junit.Assert.*;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@@ -50,9 +52,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 @SqlConfig(encoding = "UTF-8")
 public class SearchResourceTest {
 
-    private static final String PATH="/ui/rest/search";
-
-
     @Autowired
     private WebApplicationContext webAppContext;
 
@@ -75,7 +74,7 @@ public class SearchResourceTest {
     @Test
     public void testSearchByAnonymous() throws Exception {
         // given when
-        MvcResult result = mvc.perform(get(PATH)
+        MvcResult result = mvc.perform(get(CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT)
         ).andExpect(status().isOk()).andReturn();
 
         //then
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ApplicationResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/ApplicationAdminResourceTest.java
similarity index 72%
rename from smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ApplicationResourceTest.java
rename to smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/ApplicationAdminResourceTest.java
index 3d4f71d27c6db37b01ba7facfb0e36a7d5df0a6a..fb067c09c5e73c45404554ab15a9b10769adad34 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/ApplicationResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/ApplicationAdminResourceTest.java
@@ -1,4 +1,4 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import eu.europa.ec.edelivery.smp.config.PropertiesTestConfig;
@@ -6,7 +6,7 @@ import eu.europa.ec.edelivery.smp.config.SmpAppConfig;
 import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
 import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
 import eu.europa.ec.edelivery.smp.data.ui.SmpConfigRO;
-import eu.europa.ec.edelivery.smp.data.ui.SmpInfoRO;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -51,31 +51,21 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
         "smp.artifact.version=TestApplicationVersion",
         "smp.artifact.build.time=2018-11-27 00:00:00",
 })
-
-public class ApplicationResourceTest {
-    private static final String PATH = "/ui/rest/application";
-
+public class ApplicationAdminResourceTest {
+    private static final String PATH = ResourceConstants.CONTEXT_PATH_INTERNAL_APPLICATION;
     private static final RequestPostProcessor SMP_ADMIN_CREDENTIALS = httpBasic("smp_admin", "test123");
     private static final RequestPostProcessor SG_ADMIN_CREDENTIALS = httpBasic("sg_admin", "test123");
     private static final RequestPostProcessor SYSTEM_CREDENTIALS = httpBasic("sys_admin", "test123");
 
     @Autowired
     private WebApplicationContext webAppContext;
-
-    @Autowired
-    private ApplicationResource applicationResource;
-
-
     private MockMvc mvc;
-    private static final RequestPostProcessor ADMIN_CREDENTIALS = httpBasic("smp_admin", "test123");
 
     @Before
     public void setup() {
         mvc = MockMvcBuilders.webAppContextSetup(webAppContext)
                 .apply(SecurityMockMvcConfigurers.springSecurity())
                 .build();
-
-
         initServletContext();
     }
 
@@ -85,38 +75,16 @@ public class ApplicationResourceTest {
         ServletContextEvent event = new ServletContextEvent(sc);
     }
 
-    @Test
-    public void testGetName() throws Exception {
-        String value = mvc.perform(get(PATH + "/name"))
-                .andExpect(status().isOk())
-                .andReturn()
-                .getResponse()
-                .getContentAsString();
-
-        assertEquals("TestApplicationSmpName", value);
-
-    }
-
-    @Test
-    public void testGetRootContext() throws Exception {
-        String value = mvc.perform(get(PATH + "/rootContext"))
-                .andExpect(status().isOk())
-                .andReturn()
-                .getResponse()
-                .getContentAsString();
-
-        assertEquals("/", value);
-    }
-
     @Test
     public void testGetApplicationConfigNotAuthorized() throws Exception {
         // when
-         mvc.perform(get(PATH + "/config")
-                 .with(csrf()))
+        mvc.perform(get(PATH + "/config")
+                .with(csrf()))
                 .andExpect(status().isUnauthorized())
                 .andReturn()
                 .getResponse();
     }
+
     @Test
     public void testGetApplicationConfigAuthorized() throws Exception {
         //  SMP admin
@@ -158,36 +126,14 @@ public class ApplicationResourceTest {
                 .getResponse()
                 .getContentAsString();
 
-       // then
+        // then
         ObjectMapper mapper = new ObjectMapper();
         SmpConfigRO res = mapper.readValue(value, SmpConfigRO.class);
 
-
         assertNotNull(res);
-        assertEquals("Participant scheme must start with:urn:oasis:names:tc:ebcore:partyid-type:(iso6523:|unregistered:) OR must be up to 25 characters long with form [domain]-[identifierArea]-[identifierType] (ex.: 'busdox-actorid-upis') and may only contain the following characters: [a-z0-9].",res.getParticipantSchemaRegExpMessage());
-        assertEquals("^((?!^.{26})([a-z0-9]+-[a-z0-9]+-[a-z0-9]+)|urn:oasis:names:tc:ebcore:partyid-type:(iso6523|unregistered)(:.+)?$)",res.getParticipantSchemaRegExp());
+        assertEquals("Participant scheme must start with:urn:oasis:names:tc:ebcore:partyid-type:(iso6523:|unregistered:) OR must be up to 25 characters long with form [domain]-[identifierArea]-[identifierType] (ex.: 'busdox-actorid-upis') and may only contain the following characters: [a-z0-9].", res.getParticipantSchemaRegExpMessage());
+        assertEquals("^((?!^.{26})([a-z0-9]+-[a-z0-9]+-[a-z0-9]+)|urn:oasis:names:tc:ebcore:partyid-type:(iso6523|unregistered)(:.+)?$)", res.getParticipantSchemaRegExp());
         assertFalse(res.isSmlIntegrationOn());
         assertFalse(res.isSmlParticipantMultiDomainOn());
     }
-
-    @Test
-    public void getDisplayName() throws Exception {
-        String value = applicationResource.getDisplayVersion();
-        assertEquals("TestApplicationSmpName Version [TestApplicationVersion] Build-Time [2018-11-27 00:00:00|Central European Time]", value);
-    }
-
-    @Test
-    public void getApplicationInfoTest() throws Exception {
-        String value = mvc.perform(get(PATH + "/info"))
-                .andExpect(status().isOk())
-                .andReturn()
-                .getResponse()
-                .getContentAsString();
-        ObjectMapper mapper = new ObjectMapper();
-        SmpInfoRO info = mapper.readValue(value, SmpInfoRO.class);
-
-        assertEquals("TestApplicationSmpName Version [TestApplicationVersion] Build-Time [2018-11-27 00:00:00|Central European Time]", info.getVersion());
-        assertEquals(false, info.isSmlIntegrationOn());
-        assertEquals("/", info.getContextPath());
-    }
 }
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/DomainResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResourceTest.java
similarity index 83%
rename from smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/DomainResourceTest.java
rename to smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResourceTest.java
index 12b12d7c60f7bd6a9c95ec0a96b6e6493118e37e..aa6de7444cca5751d4b214d444c292bc4df267b9 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/DomainResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/DomainAdminResourceTest.java
@@ -1,11 +1,15 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
-import eu.europa.ec.edelivery.smp.config.*;
+import eu.europa.ec.edelivery.smp.config.PropertiesTestConfig;
+import eu.europa.ec.edelivery.smp.config.SmpAppConfig;
+import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
+import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
 import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
 import eu.europa.ec.edelivery.smp.data.ui.DeleteEntityValidation;
 import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -32,9 +36,7 @@ import static org.hamcrest.Matchers.stringContainsInOrder;
 import static org.junit.Assert.*;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
@@ -49,18 +51,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 @Sql("classpath:/cleanup-database.sql")
 @Sql("classpath:/webapp_integration_test_data.sql")
 @SqlConfig(encoding = "UTF-8")
-@TestPropertySource(properties = {
-        "smp.artifact.name=TestApplicationSmpName",
-        "smp.artifact.version=TestApplicationVersion",
-        "smp.artifact.build.time=2018-11-27 00:00:00",
-        "bdmsl.integration.enabled=false"})
-public class DomainResourceTest {
-    private static final String PATH = "/ui/rest/domain";
+public class DomainAdminResourceTest {
+    private static final String PATH = ResourceConstants.CONTEXT_PATH_INTERNAL_DOMAIN;
 
     @Autowired
     private WebApplicationContext webAppContext;
 
-
     @Autowired
     DomainDao domainDao;
 
@@ -83,29 +79,6 @@ public class DomainResourceTest {
     }
 
 
-    @Test
-    public void geDomainList() throws Exception {
-
-        // given when
-        MvcResult result = mvc.perform(get(PATH)
-                .with(SYSTEM_CREDENTIALS)
-                .with(csrf()))
-                .andExpect(status().isOk()).andReturn();
-
-        //them
-        ObjectMapper mapper = new ObjectMapper();
-        ServiceResult res = mapper.readValue(result.getResponse().getContentAsString(), ServiceResult.class);
-
-
-        assertNotNull(res);
-        assertEquals(2, res.getServiceEntities().size());
-        res.getServiceEntities().forEach(sgMap -> {
-            DomainRO sgro = mapper.convertValue(sgMap, DomainRO.class);
-            assertNotNull(sgro.getId());
-            assertNotNull(sgro.getDomainCode());
-            assertNotNull(sgro.getSmlSmpId());
-        });
-    }
 
     @Test
     public void updateDomainListOkDelete() throws Exception {
@@ -138,7 +111,7 @@ public class DomainResourceTest {
     @Test
     public void validateDeleteDomainOK() throws Exception {
         // given when
-        MvcResult result = mvc.perform(post(PATH + "/validateDelete")
+        MvcResult result = mvc.perform(put(PATH + "/validate-delete")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .header("Content-Type", " application/json")
@@ -170,12 +143,11 @@ public class DomainResourceTest {
 
         // check if exists
         assertEquals("CEF-SMP-010", domainDao.getDomainByCode("domainTwo").get().getSmlSmpId());
-
     }
     @Test
     public void validateDeleteDomainFalse() throws Exception {
         // given when
-        MvcResult result = mvc.perform(post(PATH + "/validateDelete")
+        MvcResult result = mvc.perform(put(PATH + "/validate-delete")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .header("Content-Type", " application/json")
@@ -198,7 +170,7 @@ public class DomainResourceTest {
         // given when
         // 3- user id
         // domainTwo -  domain code
-        mvc.perform(post(PATH + "/3/smlregister/domainTwo")
+        mvc.perform(put(PATH + "/3/sml-register/domainTwo")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .header("Content-Type", " application/json"))
@@ -211,7 +183,7 @@ public class DomainResourceTest {
         // given when
         // 3- user id
         // domainTwo -  domain code
-        mvc.perform(post(PATH + "/3/smlunregister/domainTwo")
+        mvc.perform(put(PATH + "/3/sml-unregister/domainTwo")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .header("Content-Type", " application/json"))
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/KeystoreResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/KeystoreResourceTest.java
similarity index 97%
rename from smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/KeystoreResourceTest.java
rename to smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/KeystoreResourceTest.java
index e157dd6bbdb5aeeab4b1f3e49676804157dd9654..6f1d23f9eb47b6b450584f86f92122892d500add 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/KeystoreResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/KeystoreResourceTest.java
@@ -1,4 +1,4 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
 
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -39,6 +39,7 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
 
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_INTERNAL_KEYSTORE;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -62,11 +63,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
         "classpath:webapp_integration_test_data.sql"
 }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
 public class KeystoreResourceTest {
-    private static final String PATH = "/ui/rest/keystore";
-
+    private static final String PATH = CONTEXT_PATH_INTERNAL_KEYSTORE;
     Path keystore = Paths.get("src", "test", "resources",  "keystores", "smp-keystore.jks");
 
-
     @Autowired
     private WebApplicationContext webAppContext;
 
@@ -83,8 +82,6 @@ public class KeystoreResourceTest {
         mvc = MockMvcBuilders.webAppContextSetup(webAppContext)
                 .apply(SecurityMockMvcConfigurers.springSecurity())
                 .build();
-
-
         initServletContext();
         uiKeystoreService.refreshData();
     }
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/TruststoreResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/TruststoreAdminResourceTest.java
similarity index 69%
rename from smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/TruststoreResourceTest.java
rename to smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/TruststoreAdminResourceTest.java
index dd8f0c1c48156be4eacd1727f3cb034ccc6abc4a..2bc6e27fba62563868003d49e33cacbc0f41ebf4 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/TruststoreResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/internal/TruststoreAdminResourceTest.java
@@ -1,4 +1,4 @@
-package eu.europa.ec.edelivery.smp.ui;
+package eu.europa.ec.edelivery.smp.ui.internal;
 
 
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -7,12 +7,15 @@ import eu.europa.ec.edelivery.smp.config.SmpAppConfig;
 import eu.europa.ec.edelivery.smp.config.SmpWebAppConfig;
 import eu.europa.ec.edelivery.smp.config.SpringSecurityConfig;
 import eu.europa.ec.edelivery.smp.data.ui.CertificateRO;
-import eu.europa.ec.edelivery.smp.data.ui.KeystoreImportResult;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import eu.europa.ec.edelivery.smp.error.UIErrorControllerAdvice;
 import eu.europa.ec.edelivery.smp.services.ui.UITruststoreService;
 import eu.europa.ec.edelivery.smp.testutils.X509CertificateTestUtils;
+import eu.europa.ec.edelivery.smp.ui.UserResourceTest;
 import org.apache.commons.io.IOUtils;
+import org.hamcrest.CoreMatchers;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -33,16 +36,17 @@ import org.springframework.web.context.WebApplicationContext;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
 import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.List;
 
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_INTERNAL_TRUSTSTORE;
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLIC_TRUSTSTORE;
 import static org.junit.Assert.*;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 
@@ -51,17 +55,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
         PropertiesTestConfig.class,
         SmpAppConfig.class,
         SmpWebAppConfig.class,
-        SpringSecurityConfig.class})
+        SpringSecurityConfig.class,
+        UIErrorControllerAdvice.class})
 @WebAppConfiguration
 @SqlConfig(encoding = "UTF-8")
 @Sql(scripts = {"classpath:cleanup-database.sql",
         "classpath:webapp_integration_test_data.sql"
 }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
-public class TruststoreResourceTest {
-    private static final String PATH = "/ui/rest/truststore";
-
-    Path keystore = Paths.get("src", "test", "resources",  "keystores", "smp-keystore.jks");
-
+public class TruststoreAdminResourceTest {
+    private static final String PATH_INTERNAL = CONTEXT_PATH_INTERNAL_TRUSTSTORE;
+    private static final String PATH_PUBLIC = CONTEXT_PATH_PUBLIC_TRUSTSTORE;
 
     @Autowired
     private WebApplicationContext webAppContext;
@@ -71,6 +74,8 @@ public class TruststoreResourceTest {
 
     private MockMvc mvc;
     private static final RequestPostProcessor SYSTEM_CREDENTIALS = httpBasic("sys_admin", "test123");
+    private static final RequestPostProcessor ADMIN_CREDENTIALS = httpBasic("smp_admin", "test123");
+    private static final RequestPostProcessor SG_ADMIN_CREDENTIALS = httpBasic("sg_admin", "test123");
 
     @Before
     public void setup() throws IOException {
@@ -92,39 +97,24 @@ public class TruststoreResourceTest {
     }
 
     @Test
-    public void getCertificateList() throws Exception {
+    public void validateInvalidCertificate() throws Exception {
+        byte[] buff = (new String("Not a certficate :) ")).getBytes();
+
         // given when
-        int countStart = uiTruststoreService.getCertificateROEntriesList().size();
-        MvcResult result = mvc.perform(get(PATH)
+        mvc.perform(post(PATH_PUBLIC + "/1098765430/validate-certificate")
                 .with(SYSTEM_CREDENTIALS)
-                .with(csrf()))
-                .andExpect(status().isOk()).andReturn();
-
-        //them
-        ObjectMapper mapper = new ObjectMapper();
-        ServiceResult res = mapper.readValue(result.getResponse().getContentAsString(), ServiceResult.class);
-
-
-        assertNotNull(res);
-        assertEquals(countStart, res.getServiceEntities().size());
-        res.getServiceEntities().forEach(sgMap -> {
-            CertificateRO cert = mapper.convertValue(sgMap, CertificateRO.class);
-            assertNotNull(cert.getAlias());
-            assertNotNull(cert.getCertificateId());
-            assertNotNull(cert.getBlueCoatHeader());
-            assertNull(cert.getEncodedValue()); // submit only metadata
-        });
+                .with(csrf())
+                .content(buff))
+                .andExpect(status().is5xxServerError())
+                .andExpect(content().string(CoreMatchers.containsString(" The certificate is not valid")));
     }
 
-
-
     @Test
-    public void uploadCertificateSystemAdmin() throws Exception {
+    public void validateCertificateSystemAdmin() throws Exception {
         byte[] buff = IOUtils.toByteArray(UserResourceTest.class.getResourceAsStream("/SMPtest.crt"));
 
-        int countStart =   uiTruststoreService.getNormalizedTrustedList().size();
         // given when
-        MvcResult result = mvc.perform(post(PATH+"/3/certdata")
+        MvcResult result = mvc.perform(post(PATH_PUBLIC + "/1098765430/validate-certificate")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .content(buff))
@@ -133,7 +123,7 @@ public class TruststoreResourceTest {
         //then
         ObjectMapper mapper = new ObjectMapper();
         CertificateRO res = mapper.readValue(result.getResponse().getContentAsString(), CertificateRO.class);
-        assertEquals(countStart+1, uiTruststoreService.getNormalizedTrustedList().size());
+
         assertNotNull(res);
         assertEquals("CN=Intermediate CA,O=DIGIT,C=BE", res.getIssuer());
         assertEquals("1.2.840.113549.1.9.1=#160c736d7040746573742e636f6d,CN=SMP test,O=DIGIT,C=BE", res.getSubject());
@@ -142,12 +132,69 @@ public class TruststoreResourceTest {
         assertEquals("sno=3&subject=1.2.840.113549.1.9.1%3D%23160c736d7040746573742e636f6d%2CCN%3DSMP+test%2CO%3DDIGIT%2CC%3DBE&validfrom=May+22+20%3A59%3A00+2018+GMT&validto=May+22+20%3A56%3A00+2019+GMT&issuer=CN%3DIntermediate+CA%2CO%3DDIGIT%2CC%3DBE", res.getBlueCoatHeader());
     }
 
+    @Test
+    public void validateCertificateIdWithEmailSerialNumberInSubjectCertIdTest() throws Exception {
+        String subject = "CN=common name,emailAddress=CEF-EDELIVERY-SUPPORT@ec.europa.eu,serialNumber=1,O=org,ST=My town,postalCode=2151, L=GreatTown,street=My Street. 20, C=BE";
+        String serialNumber = "1234321";
+        X509Certificate certificate = X509CertificateTestUtils.createX509CertificateForTest(serialNumber, subject);
+        byte[] buff = certificate.getEncoded();
+        // given when
+        MvcResult result = mvc.perform(post(PATH_PUBLIC + "/1098765430/validate-certificate")
+                .with(SYSTEM_CREDENTIALS)
+                .with(csrf())
+                .content(buff))
+                .andExpect(status().isOk()).andReturn();
+
+        //them
+        ObjectMapper mapper = new ObjectMapper();
+        CertificateRO res = mapper.readValue(result.getResponse().getContentAsString(), CertificateRO.class);
+
+        assertEquals("CN=common name,O=org,C=BE:0000000001234321", res.getCertificateId());
+    }
+
+    @Test
+    public void uploadCertificateInvalidUser() throws Exception {
+        byte[] buff = IOUtils.toByteArray(UserResourceTest.class.getResourceAsStream("/SMPtest.crt"));
+        // id and logged user not match
+        // given when
+        mvc.perform(post(PATH_PUBLIC + "/34556655/validate-certificate")
+                .with(ADMIN_CREDENTIALS)
+                .with(csrf())
+                .content(buff))
+                .andExpect(status().isUnauthorized()).andReturn();
+    }
+
+    @Test
+    public void getCertificateList() throws Exception {
+        // given when
+        int countStart = uiTruststoreService.getCertificateROEntriesList().size();
+        MvcResult result = mvc.perform(get(PATH_INTERNAL)
+                .with(SYSTEM_CREDENTIALS)
+                .with(csrf()))
+                .andExpect(status().isOk()).andReturn();
+
+        //them
+        ObjectMapper mapper = new ObjectMapper();
+        ServiceResult res = mapper.readValue(result.getResponse().getContentAsString(), ServiceResult.class);
+
+
+        assertNotNull(res);
+        assertEquals(countStart, res.getServiceEntities().size());
+        res.getServiceEntities().forEach(sgMap -> {
+            CertificateRO cert = mapper.convertValue(sgMap, CertificateRO.class);
+            assertNotNull(cert.getAlias());
+            assertNotNull(cert.getCertificateId());
+            assertNotNull(cert.getBlueCoatHeader());
+            assertNull(cert.getEncodedValue()); // submit only metadata
+        });
+    }
+
     @Test
     public void deleteCertificateSystemAdmin() throws Exception {
         byte[] buff = IOUtils.toByteArray(UserResourceTest.class.getResourceAsStream("/SMPtest.crt"));
 
-        int countStart =   uiTruststoreService.getNormalizedTrustedList().size();
-        MvcResult prepRes = mvc.perform(post(PATH+"/3/certdata")
+        int countStart = uiTruststoreService.getNormalizedTrustedList().size();
+        MvcResult prepRes = mvc.perform(post(PATH_INTERNAL + "/3/upload-certificate")
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .content(buff))
@@ -158,10 +205,10 @@ public class TruststoreResourceTest {
         CertificateRO res = mapper.readValue(prepRes.getResponse().getContentAsString(), CertificateRO.class);
         assertNotNull(res);
         uiTruststoreService.refreshData();
-        assertEquals(countStart+1, uiTruststoreService.getNormalizedTrustedList().size());
+        assertEquals(countStart + 1, uiTruststoreService.getNormalizedTrustedList().size());
 
         // then
-        MvcResult result = mvc.perform(delete(PATH+"/3/delete/"+res.getAlias())
+        MvcResult result = mvc.perform(delete(PATH_INTERNAL + "/3/delete/" + res.getAlias())
                 .with(SYSTEM_CREDENTIALS)
                 .with(csrf())
                 .content(buff))
@@ -213,7 +260,7 @@ public class TruststoreResourceTest {
 
     public List<CertificateRO> getCertificateFromEndpointList() throws Exception {
         // given when
-        MvcResult result = mvc.perform(get(PATH).with(SYSTEM_CREDENTIALS)).
+        MvcResult result = mvc.perform(get(PATH_INTERNAL).with(SYSTEM_CREDENTIALS)).
                 andExpect(status().isOk()).andReturn();
 
         //them
diff --git a/smp-webapp/src/test/resources/logback-test.xml b/smp-webapp/src/test/resources/logback-test.xml
index 14096e01d343057269fd34ce2fc0ee1d7459e49f..5ea50260f8a7af2e57bf8cc216e9399af8018040 100644
--- a/smp-webapp/src/test/resources/logback-test.xml
+++ b/smp-webapp/src/test/resources/logback-test.xml
@@ -2,8 +2,8 @@
 
 <configuration>
     <!-- pattern definition -->
-    <property name="encoderPattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
-    <property name="consolePattern" value="%d{ISO8601} [%X{d_user}] [%X{d_domain}] [%X{d_messageId}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="encoderPattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
+    <property name="consolePattern" value="%d{ISO8601} [%X{smp_user}] [%X{smp_session_id}] [%X{smp_request_id}] [%thread] %5p %c{1}:%L - %m%n" scope="global"/>
 
      <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
         <file>${project.build.directory}/logs/edelivery-smp.log</file>
diff --git a/upgrade-info.txt b/upgrade-info.txt
index 1606ec37aee7be6cb7bd386bfc3a2e32755a80f0..54fa9ba11ce2b8fe8c5ef5b32011a7ca8ef6983f 100644
--- a/upgrade-info.txt
+++ b/upgrade-info.txt
@@ -1,2 +1,4 @@
 eDelivery SMP 4.2 from 4.1.1)
- - Set: smp.http.forwarded.headers.enabled to true if SMP is set behind RP/LoadBalancer
\ No newline at end of file
+ - Set: smp.http.forwarded.headers.enabled to true if SMP is set behind RP/LoadBalancer
+ - Make sure database user usernames are not null!
+ - Copy plugin users!
\ No newline at end of file