From 2b1bd95e754df058a05ec784a5d240fe6f47ae3e Mon Sep 17 00:00:00 2001
From: Joze RIHTARSIC <joze.rihtarsic@ext.ec.europa.eu>
Date: Thu, 11 Oct 2018 09:36:59 +0200
Subject: [PATCH] - update the authentication to fix the bamboo plans

---
 .../eu/europa/ec/edelivery/smp/SMPRole.java   | 26 ----------
 .../conversion/CaseSensitivityNormalizer.java |  6 ++-
 .../ec/edelivery/smp/data/dao/UserDao.java    | 21 --------
 .../data/dao/utils/SMPSchemaGenerator.java    |  4 +-
 .../smp/data/model/DBUserAuthority.java       | 41 ---------------
 .../smp/services/ServiceGroupService.java     | 14 ++++-
 .../edelivery/smp/testutil/SignatureUtil.java |  1 -
 .../mysql-4.1_integration_test_data.sql       | 51 +++++++++++++++++++
 .../SMPAuthenticationProvider.java            | 33 +++++-------
 .../ec/edelivery/smp/auth/SMPAuthority.java   | 24 +++++++++
 .../europa/ec/edelivery/smp/auth/SMPRole.java | 23 +++++++++
 .../controllers/ServiceGroupController.java   |  9 ++--
 .../ServiceMetadataController.java            | 12 +++--
 .../src/main/resources/spring-security.xml    | 17 +++++--
 .../security/SecurityConfigurationTest.java   |  7 ---
 .../smp/server/security/SignatureUtil.java    |  1 -
 .../security/SignatureValidatorTest.java      |  2 +-
 .../webapp_integration_test_data.sql          | 18 ++++---
 18 files changed, 169 insertions(+), 141 deletions(-)
 delete mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java
 delete mode 100644 smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java
 create mode 100644 smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
 rename smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/{config => auth}/SMPAuthenticationProvider.java (67%)
 create mode 100644 smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java
 create mode 100644 smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java

diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java
deleted file mode 100644
index 0323f1606..000000000
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/SMPRole.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package eu.europa.ec.edelivery.smp;
-
-public enum SMPRole {
-
-    SMP_ADMIN("ROLE_SMP_ADMIN"),
-    SERVICE_GROUP_ADMIN("ROLE_SERVICE_GROUP_ADMIN"),
-    SYSTEM_ADMIN("ROLE_SYSTEM_ADMIN");
-
-    // static constants for annotations!
-    public static final String S_ROLE_SYSTEM_ADMIN = "ROLE_SYSTEM_ADMIN";
-    public static final String S_ROLE_SMP_ADMIN = "ROLE_SMP_ADMIN";
-    public static final String S_ROLE_SERVICE_GROUP_ADMIN = "ROLE_SERVICE_GROUP_ADMIN";
-
-
-    String code;
-    SMPRole(String code){
-        this.code = code;
-    }
-
-    public String getCode() {
-        return code;
-    }
-
-
-
-}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java
index 9fa25c8e5..b66ba56f8 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/CaseSensitivityNormalizer.java
@@ -66,7 +66,11 @@ public class CaseSensitivityNormalizer {
     }
 
     public String normalizeParticipantId(String participantId) {
-        return asString(normalize(asParticipantId(participantId)));
+        return asString(normalizeParticipant(participantId));
+    }
+
+    public ParticipantIdentifierType normalizeParticipant(String participantId) {
+        return normalize(asParticipantId(participantId));
     }
 
     private static void toLowerCaseStringList(List<String> strings) {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
index 4c1857331..ac81494b6 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
@@ -14,18 +14,14 @@
 package eu.europa.ec.edelivery.smp.data.dao;
 
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
-import eu.europa.ec.edelivery.smp.data.model.DBUserAuthority;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.security.core.GrantedAuthority;
 import org.springframework.stereotype.Repository;
 import javax.persistence.NoResultException;
 import javax.persistence.NonUniqueResultException;
 import javax.persistence.TypedQuery;
 import javax.transaction.Transactional;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Optional;
 
 import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.ILLEGAL_STATE_CERT_ID_MULTIPLE_ENTRY;
@@ -38,23 +34,6 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.ILLEGAL_STATE_USER
 public class UserDao extends BaseDao<DBUser> {
 
 
-    public List<GrantedAuthority> getUserRoles(String username) {
-
-        List<GrantedAuthority> lstRes = new ArrayList<>();
-        // all users are  SERVICEGROUP_ADMIN
-        lstRes.add(DBUserAuthority.S_ROLE_SERVICEGROUP_ADMIN);
-
-        List<DBUserAuthority> lst = memEManager
-                .createNamedQuery("DBUserAuthority.getRolesForUsernameNativeQuery")
-                .setParameter( "username",username)
-                .getResultList();
-
-        if (!lst.isEmpty()){
-            lstRes.addAll(lst);
-        }
-        System.out.println("Got roles: " + lstRes.size() + " " + lstRes);
-        return lstRes;
-    }
 
     /**
      * Perstis user to database. Before that test if user has identifiers
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java
index fed2435ca..45cb6a335 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/utils/SMPSchemaGenerator.java
@@ -127,7 +127,6 @@ public class SMPSchemaGenerator {
             try {
                 directory = new File(Thread.currentThread().getContextClassLoader().getResource(pckgname.replace('.', '/')).getFile());
             } catch (NullPointerException x) {
-                System.out.println("Nullpointer");
                 throw new ClassNotFoundException(pckgname + " does not appear to be a valid package");
             }
             if (directory.exists()) {
@@ -139,8 +138,7 @@ public class SMPSchemaGenerator {
                         classes.add(Class.forName(pckgname + '.' + files[i].substring(0, files[i].length() - 6)));
                     }
                 }
-            } else {
-                System.out.println("Directory does not exist");
+            } else { ;
                 throw new ClassNotFoundException("Package: "+pckgname + " does not eixsts!");
             }
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java
deleted file mode 100644
index e87210342..000000000
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserAuthority.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package eu.europa.ec.edelivery.smp.data.model;
-
-import org.springframework.security.core.GrantedAuthority;
-
-import javax.persistence.*;
-
-@NamedNativeQueries({
-        @NamedNativeQuery(
-                name = "DBUserAuthority.getRolesForUsernameNativeQuery",
-                query = "SELECT 'SMP_ADMIN' AS AUTHORITY FROM smp_user WHERE isadmin = 1 and username=:username " +
-                        "UNION ALL " +
-                        "SELECT CONCAT(businessIdentifierScheme, CONCAT('::', businessIdentifier)) AS AUTHORITY FROM smp_ownership  WHERE username=:username",
-                resultSetMapping = "RoleDTO"
-        )})
-
-@SqlResultSetMapping(
-        name = "RoleDTO",
-        classes = @ConstructorResult
-                (
-                        targetClass = DBUserAuthority.class,
-                        columns = {
-                                @ColumnResult(name = "authority", type = String.class)
-                        }
-                )
-)
-public class DBUserAuthority implements GrantedAuthority {
-
-    public static DBUserAuthority S_ROLE_SERVICEGROUP_ADMIN = new DBUserAuthority("ROLE_SERVICEGROUP_ADMIN");
-
-
-    public DBUserAuthority(String authority) {
-        this.authority = authority;
-    }
-
-    String authority;
-
-    @Override
-    public String getAuthority() {
-        return authority;
-    }
-}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java
index e5be6f258..ca7ab211c 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ServiceGroupService.java
@@ -102,7 +102,6 @@ public class ServiceGroupService {
         LOG.businessDebug(SMPMessageCode.BUS_SAVE_SERVICE_GROUP,domain,normalizedParticipantId.getValue(), normalizedParticipantId.getScheme()  );
 
         String newOwnerName = defineGroupOwner(serviceGroupOwner, authenticatedUser);
-
         Optional<DBUser> newOwner = userDao.findUserByIdentifier(newOwnerName);
         if (!newOwner.isPresent()) {
             SMPRuntimeException ex = new SMPRuntimeException(USER_NOT_EXISTS);
@@ -193,6 +192,19 @@ public class ServiceGroupService {
         }
     }
 
+    /**
+     * Method validates if user owner with identifier is owner of servicegroup
+     * @param  ownerIdentifier
+     * @param dbsg
+     */
+    @Transactional
+    public boolean isServiceGroupOwner(String ownerIdentifier, String serviceGroupIdentifier ){
+        ParticipantIdentifierType pt = caseSensitivityNormalizer.normalizeParticipant(serviceGroupIdentifier);
+        Optional<DBServiceGroup> osg = serviceGroupDao.findServiceGroup(pt.getValue(), pt.getScheme());
+        Optional<DBUser> own = userDao.findUserByIdentifier(ownerIdentifier);
+        return osg.isPresent() && own.isPresent() && osg.get().getUsers().contains(own.get());
+    }
+
 
     @Transactional
     public void deleteServiceGroup(ParticipantIdentifierType serviceGroupId) {
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java
index ec64ae795..45021d040 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/SignatureUtil.java
@@ -177,7 +177,6 @@ public class SignatureUtil {
         // Marshalling and parsing the document - signature validation fails without this stinky "magic".
         // _Probably_ SUN's implementation doesn't import correctly signatures between two different documents.
         String strUnwrapped = marshall(docUnwrapped);
-        System.out.println(strUnwrapped);
         return parseDocument(strUnwrapped);
     }
 
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
new file mode 100644
index 000000000..5b6e51ab8
--- /dev/null
+++ b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql
@@ -0,0 +1,51 @@
+-- Copyright 2018 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.
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (1, 'peppol_user', '$2a$10$.pqNZZ4fRDdNbLhNlnEYg.1/d4yAGpLDgeXpJFI0sw7.WtyKphFzu', 'SMP_ADMIN', 1);
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (2, 'the_admin', '', 'SMP_ADMIN', 1);
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (3, 'AdminSMP1TEST', '$2a$06$u6Hym7Zrbsf4gEIeAsJRceK.Kg7tei3kDypwucQQdky0lXOLCkrCO', 'SMP_ADMIN', 1);
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (4, 'AdminSMP2TEST', '$2a$10$h8Q3Kjbs6ZrGkU6ditjNueINlJOMDJ/g/OKiqFZy32WmdhLjV5TAi', 'SMP_ADMIN', 1);
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (5, 'test', '', 'SMP_ADMIN', 1);
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (6, 'test1', '$2a$06$toKXJgjqQINZdjQqSao3NeWz2n1S64PFPhVU1e8gIHh4xdbwzy1Uy', 'SMP_ADMIN', 1);
+
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (10, 'EHEALTH_SMP_EC', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (10, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (11, 'EHEALTH_ż_ẞ_Ẅ_,O', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (11, 'CN=EHEALTH_ż_ẞ_Ẅ_,O=European_ż_ẞ_Ẅ_Commission,C=BE:f71ee8b11cb3b787', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (12, 'EHEALTH_SMP_1000000007', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (12, 'CN=EHEALTH_SMP_1000000007,O=DG-DIGIT,C=BE:000000000123ABCD', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (13, 'EHEALTH_SMP_EC1', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (13, 'CN=EHEALTH_SMP_EC/emailAddress\=CEF-EDELIVERY-SUPPORT@ec.europa.eu,O=European Commission,C=BE:f71ee8b11cb3b787', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (14, 'EHEALTH_SMP_1000000007', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (14, 'CN=EHEALTH_SMP_1000000007,O=DG-DIGIT,C=BE', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (15, 'EHEALTH&SMP_EC', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (15, 'CN=EHEALTH&SMP_EC,O=European&Commission,C=B&E:f71ee8b11cb3b787', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (16, 'EHEALTH_SMP_EC2', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (16, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:000000000000100f', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (17, 'SMP_1000000007', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (17, 'CN=SMP_1000000007,O=DG-DIGIT,C=BE', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (18, 'SMP_1000000007', '', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (18, 'CN=SMP_1000000007,O=DG-DIGIT,C=BE:000000000123ABCD', null,null);
+
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (19, 'SMP_1000000181,O=DIGIT,C=DK:123456789', '$2a$10$v2d/2E99dWHBM2ipTIip1enyaRKBTi.Xj/Iz0K8g0gjHBWdKRsHaC', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (19, 'CN=SMP_1000000181,O=DIGIT,C=DK:123456789', null,null);
+
+-- insert domain
+insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SIGNATURE_KEY_ALIAS) values (1, 'domain','subdomain','sig-key');
+
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPAuthenticationProvider.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java
similarity index 67%
rename from smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPAuthenticationProvider.java
rename to smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java
index f752e546f..dda846c4a 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPAuthenticationProvider.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationProvider.java
@@ -1,4 +1,4 @@
-package eu.europa.ec.edelivery.smp.config;
+package eu.europa.ec.edelivery.smp.auth;
 
 import eu.europa.ec.edelivery.smp.data.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.model.DBUser;
@@ -8,12 +8,10 @@ import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.security.crypto.bcrypt.BCrypt;
 
 import java.util.Collections;
-import java.util.List;
+import java.util.Optional;
 
 public class SMPAuthenticationProvider implements AuthenticationProvider {
 
@@ -30,29 +28,22 @@ public class SMPAuthenticationProvider implements AuthenticationProvider {
         String username = auth.getName();
         String password = auth.getCredentials().toString();
 
-        DBUser usr = mUserDao.find(username);
-        System.out.println("GOT user " +username + " username " + usr );
-        if (usr == null){
+        Optional<DBUser> oUsr = mUserDao.findUserByIdentifier(username);
+        if (!oUsr.isPresent()){
             //https://www.owasp.org/index.php/Authentication_Cheat_Sheet
             // Do not reveal the status of an existing account. Not to use UsernameNotFoundException
             throw new BadCredentialsException("Login failed; Invalid userID or password");
         }
-        System.out.println("Check print");
-        if (!BCrypt.checkpw(password,  usr.getPassword())) {
-            throw new BadCredentialsException("Login failed; Invalid userID or password");
-        }
-        System.out.println("get roles");
-        List<GrantedAuthority> roles ;
+        DBUser usr = oUsr.get();
         try {
-            roles = mUserDao.getUserRoles(username);
-
-        }catch (Exception ex) {
-            ex.printStackTrace(System.out);
-            return null;
+            if (!BCrypt.checkpw(password, usr.getPassword())) {
+                throw new BadCredentialsException("Login failed; Invalid userID or password");
+            }
+        }catch (java.lang.IllegalArgumentException ex){
+            // password is not hashed
+            throw new BadCredentialsException("Login failed; Invalid userID or password");
         }
-
-        System.out.println("Got roles: " + roles.size() + " " + roles);
-        return new UsernamePasswordAuthenticationToken(username, password,roles);
+        return new UsernamePasswordAuthenticationToken(username, password,Collections.singletonList(new SMPAuthority(usr.getRole())));
 
     }
 
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java
new file mode 100644
index 000000000..8a64b60ec
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthority.java
@@ -0,0 +1,24 @@
+package eu.europa.ec.edelivery.smp.auth;
+
+import org.springframework.security.core.GrantedAuthority;
+
+
+public class SMPAuthority implements GrantedAuthority {
+
+    // static constants for annotations!
+    public static final String S_AUTHORITY_SYSTEM_ADMIN = "ROLE_SYSTEM_ADMIN";
+    public static final String S_AUTHORITY_SMP_ADMIN = "ROLE_SMP_ADMIN";
+    public static final String S_AUTHORITY_SERVICE_GROUP_ADMIN = "ROLE_SERVICE_GROUP_ADMIN";
+
+
+    String role;
+
+    public SMPAuthority(String role) {
+        this.role = role;
+    }
+
+    @Override
+    public String getAuthority() {
+        return "ROLE_"+role;
+    }
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java
new file mode 100644
index 000000000..12d1d4e27
--- /dev/null
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPRole.java
@@ -0,0 +1,23 @@
+package eu.europa.ec.edelivery.smp.auth;
+
+public enum SMPRole {
+
+    SMP_ADMIN("SMP_ADMIN"),
+    SERVICE_GROUP_ADMIN("SERVICE_GROUP_ADMIN"),
+    SYSTEM_ADMIN("SYSTEM_ADMIN");
+
+
+
+
+    String code;
+    SMPRole(String code){
+        this.code = code;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+
+
+}
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
index 191d410b6..0d114eabd 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceGroupController.java
@@ -13,7 +13,7 @@
 
 package eu.europa.ec.edelivery.smp.controllers;
 
-import eu.europa.ec.edelivery.smp.SMPRole;
+import eu.europa.ec.edelivery.smp.auth.SMPAuthority;
 import eu.europa.ec.edelivery.smp.conversion.ServiceGroupConverter;
 import eu.europa.ec.edelivery.smp.services.ServiceGroupService;
 import eu.europa.ec.edelivery.smp.services.ServiceMetadataService;
@@ -34,7 +34,6 @@ import org.springframework.security.access.annotation.Secured;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.UnsupportedEncodingException;
 import java.util.List;
 
 import static eu.europa.ec.smp.api.Identifiers.asParticipantId;
@@ -78,14 +77,14 @@ public class ServiceGroupController {
 
 
     @PutMapping
-   // @Secured({SMPRole.S_ROLE_SMP_ADMIN, SMPRole.S_ROLE_SYSTEM_ADMIN})
+    @Secured({SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_SMP_ADMIN})
     public ResponseEntity saveServiceGroup(
             @PathVariable String serviceGroupId,
             @RequestHeader(name = "ServiceGroup-Owner", required = false) String serviceGroupOwner,
             @RequestHeader(name = "Domain", required = false) String domain,
             @RequestBody byte[] body) throws XmlInvalidAgainstSchemaException {
 
-        log.info("PUT ServiceGroup: {} domain {} owner {} \n{}", serviceGroupId,domain, serviceGroupOwner, body);
+        log.info("PUT ServiceGroup: {} domain {} owner {} \n{}", serviceGroupId,domain, serviceGroupOwner, new String(body));
 
         // Validations
         BdxSmpOasisValidator.validateXSD(body);
@@ -101,7 +100,7 @@ public class ServiceGroupController {
     }
 
     @DeleteMapping
-    @Secured({SMPRole.S_ROLE_SYSTEM_ADMIN, SMPRole.S_ROLE_SMP_ADMIN})
+    @Secured({SMPAuthority.S_AUTHORITY_SYSTEM_ADMIN, SMPAuthority.S_AUTHORITY_SMP_ADMIN})
     public void deleteServiceGroup(@PathVariable String serviceGroupId) {
 
         log.info("DELETE ServiceGroup: {}", serviceGroupId);
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java
index 7e3320773..be71c1191 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ServiceMetadataController.java
@@ -14,6 +14,7 @@
 package eu.europa.ec.edelivery.smp.controllers;
 
 import eu.europa.ec.edelivery.smp.conversion.ServiceMetadataConverter;
+import eu.europa.ec.edelivery.smp.services.ServiceGroupService;
 import eu.europa.ec.edelivery.smp.services.ServiceMetadataService;
 import eu.europa.ec.edelivery.smp.validation.ServiceMetadataValidator;
 import eu.europa.ec.smp.api.exceptions.XmlInvalidAgainstSchemaException;
@@ -48,6 +49,9 @@ public class ServiceMetadataController {
     @Autowired
     private ServiceMetadataService serviceMetadataService;
 
+    @Autowired
+    private ServiceGroupService serviceGroupService;
+
     @Autowired
     private ServiceMetadataPathBuilder pathBuilder;
 
@@ -64,14 +68,15 @@ public class ServiceMetadataController {
     }
 
     @PutMapping
-    @PreAuthorize("hasAnyAuthority('ROLE_SMP_ADMIN', @caseSensitivityNormalizer.normalizeParticipantId(#serviceGroupId))")
+    @PreAuthorize("hasAnyAuthority(T(eu.europa.ec.edelivery.smp.auth.SMPAuthority).S_AUTHORITY_SMP_ADMIN) OR" +
+            " @serviceGroupService.isServiceGroupOwner(authentication.name, #serviceGroupId)")
     public ResponseEntity saveServiceMetadata(
             @PathVariable String serviceGroupId,
             @PathVariable String serviceMetadataId,
             @RequestHeader(name = "Domain", required = false) String domain,
             @RequestBody byte[] body) throws XmlInvalidAgainstSchemaException {
 
-        log.info("PUT ServiceMetadata: {} - {}\n{}", serviceGroupId, serviceMetadataId, body);
+        log.info("PUT ServiceMetadata: {} - {}\n{}", serviceGroupId, serviceMetadataId, new String(body));
 
         serviceMetadataValidator.validate(serviceGroupId, serviceMetadataId, body);
 
@@ -83,7 +88,8 @@ public class ServiceMetadataController {
     }
 
     @DeleteMapping
-    @PreAuthorize("hasAnyAuthority('ROLE_SMP_ADMIN', @caseSensitivityNormalizer.normalizeParticipantId(#serviceGroupId))")
+     @PreAuthorize("hasAnyAuthority(T(eu.europa.ec.edelivery.smp.auth.SMPAuthority).S_AUTHORITY_SMP_ADMIN) OR" +
+              " @serviceGroupService.isServiceGroupOwner(authentication.name, #serviceGroupId)")
     public ResponseEntity deleteServiceMetadata(@PathVariable String serviceGroupId,
                                                 @PathVariable String serviceMetadataId,
                                                 @RequestHeader(name = "Domain", required = false) String domain ) {
diff --git a/smp-webapp/src/main/resources/spring-security.xml b/smp-webapp/src/main/resources/spring-security.xml
index 1c1797de5..9060d3bf6 100644
--- a/smp-webapp/src/main/resources/spring-security.xml
+++ b/smp-webapp/src/main/resources/spring-security.xml
@@ -36,18 +36,24 @@
 
 
     <authentication-manager alias="smpAuthenticationManager">
-        <authentication-provider>
+        <!-- authentication-provider>
             <password-encoder hash="bcrypt"/>
             <jdbc-user-service id="smpJdbcUserDetailsService"
                                data-source-ref="dataSource"
                                    users-by-username-query="SELECT username, COALESCE(PASSWORD, 'dummy'), ACTIVE FROM SMP_USER WHERE USERNAME = ?"
                                authorities-by-username-query="select username, ROLE  FROM SMP_USER where USERNAME = ?"/>
-        </authentication-provider>
-
+        </authentication-provider -->
+        <authentication-provider ref="smpAuthProvider"/>
         <authentication-provider ref="preauthAuthProvider"/>
 
     </authentication-manager>
 
+    <!-- user detail service is used only in preAhtProviders for cert authentication that is why search is only on cert table-->
+    <jdbc-user-service id="smpJdbcUserDetailsService"
+                       data-source-ref="dataSource"
+                       users-by-username-query="SELECT c.CERTIFICATE_ID AS USERNAME, 'dummy' AS PASWORD, u.ACTIVE FROM SMP_CERTIFICATE c INNER JOIN SMP_USER u ON (u.id = c.id) WHERE c.CERTIFICATE_ID = ?"
+                       authorities-by-username-query="SELECT c.CERTIFICATE_ID AS USERNAME, u.ROLE FROM SMP_CERTIFICATE c INNER JOIN SMP_USER u ON (u.id = c.id) WHERE c.CERTIFICATE_ID = ?"/>
+
     <b:bean id="preauthAuthProvider"
             class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
         <b:property name="preAuthenticatedUserDetailsService">
@@ -75,4 +81,9 @@
         <b:property name="allowUrlEncodedSlash" value="${encodedSlashesAllowedInUrl}"/>
     </b:bean>
 
+    <b:bean id="smpAuthProvider" class="eu.europa.ec.edelivery.smp.auth.SMPAuthenticationProvider">
+    </b:bean>
+
+
+
 </b:beans>
diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java
index 89edba85f..866b17ef5 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SecurityConfigurationTest.java
@@ -60,13 +60,6 @@ public class SecurityConfigurationTest {
     public static final String BLUE_COAT_VALID_HEADER = "sno=66&subject=C=BE,O=org,CN=comon name&validfrom=Dec 6 17:41:42 2016 GMT&validto=Jul 9 23:59:00 2050 GMT&issuer=C=x,O=y,CN=z";
     public static final String TEST_USERNAME_BLUE_COAT = "CN=comon name,O=org,C=BE:0000000000000066";
 
-    //both passwords represent the same value - clear and hashed
-    /*
-    private DBUser userHashedPass = createUser(TEST_USERNAME_HASHED_PASS, "$2a$06$k.Q/6anG4Eq/nNTZ0C1UIuAKxpr6ra5oaMkMSrlESIyA5jKEsUdyS");
-    private DBUser userClearPass = createUser(TEST_USERNAME_CLEAR_PASS, PASSWORD);
-    private DBUser userBlueCoat = createUser(TEST_USERNAME_BLUE_COAT, null);
-    */
-
     @Autowired
     private WebApplicationContext context;
 
diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java
index 5abf7ac88..f5a91eba1 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureUtil.java
@@ -122,7 +122,6 @@ public class SignatureUtil {
             InputStream is = ((Reference) i.next()).getDigestInputStream();
             // Display the data.
             byte[] a = IOUtils.readFully(is, 0, true);
-            System.out.println(new String(a));
         }
 
         // Check core validation status.
diff --git a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java
index 798157fb9..1d5c4a2e3 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/cipa/smp/server/security/SignatureValidatorTest.java
@@ -74,7 +74,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 @Transactional
 @Rollback(true)
 @Sql("classpath:/webapp_integration_test_data.sql")
-public class SignatureValidatorTest/* extends AbstractTest*/ {
+public class SignatureValidatorTest {
 
     private static final String C14N_METHOD = CanonicalizationMethod.INCLUSIVE;
     private static final String PARSER_DISALLOW_DTD_PARSING_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
diff --git a/smp-webapp/src/test/resources/webapp_integration_test_data.sql b/smp-webapp/src/test/resources/webapp_integration_test_data.sql
index 9db7a51a9..49116f27d 100644
--- a/smp-webapp/src/test/resources/webapp_integration_test_data.sql
+++ b/smp-webapp/src/test/resources/webapp_integration_test_data.sql
@@ -8,12 +8,18 @@
 -- 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.
 
-insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (1, 'test_admin', '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'ROLE_SMP_ADMIN', 1);
-insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (2, 'test_user_hashed_pass',                     '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'ROLE_SMP_ADMIN',1);
-insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (3, 'test_user_clear_pass',                      'test123',                                                     'ROLE_SMP_ADMIN',1);
-insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (4, 'CN=comon name,O=org,C=BE:0000000000000066', '',                                                             'ROLE_SMP_ADMIN', 1);
-insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (5, 'CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', 'ROLE_SMP_ADMIN', 1);
-insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (6, 'CN=utf-8_ż_SMP,O=EC,C=BE:0000000000000666', 'ROLE_SMP_ADMIN', 1);
+insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (1, 'test_admin', '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'SMP_ADMIN', 1);
+insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (2, 'test_user_hashed_pass',                     '$2a$06$AXSSUDJlpzzq/gPZb7eIBeb8Mi0.PTKqDjzujZH.bWPwj5.ePEInW', 'SMP_ADMIN',1);
+insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (3, 'test_user_clear_pass',                      'test123',                                                     'SMP_ADMIN',1);
+insert into SMP_USER(ID, USERNAME, PASSWORD, ROLE, ACTIVE) values (4, 'cert1', '',                                                             'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (4, 'CN=comon name,O=org,C=BE:0000000000000066', null,null);
+
+insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (5, 'cert2', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (5, 'CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08', null,null);
+
+insert into SMP_USER(ID, USERNAME, ROLE, ACTIVE) values (6, 'Cert2', 'SMP_ADMIN', 1);
+insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO) values (6, 'CN=utf-8_ż_SMP,O=EC,C=BE:0000000000000666', null,null);
+
 
 insert into SMP_SERVICE_GROUP(ID, PARTICIPANT_IDENTIFIER, PARTICIPANT_SCHEME,SML_REGISTRED) values (1, 'urn:australia:ncpb', 'ehealth-actorid-qns', 1);
 insert into SMP_SERVICE_GROUP(ID, PARTICIPANT_IDENTIFIER, PARTICIPANT_SCHEME,SML_REGISTRED) values (2, 'urn:brazil:ncpb', 'ehealth-actorid-qns', 1);
-- 
GitLab