diff --git a/README.md b/README.md
index 43e8756f0f35b338d33c337fcffba4459b662815..f24392c925fd5d02f20bcdc7954c692b97853328 100644
--- a/README.md
+++ b/README.md
@@ -93,5 +93,5 @@ Afin d'essayer l'application, il faut pouvoir se connecter. Il faut pour cela cr
 INSERT INTO OreSiUser (id, login, password) values ('5a4dbd41-3fc9-4b3e-b593-a46bc888a7f9'::uuid, 'poussin', '$2a$12$4gAH34ZwgvgQNS0pbR5dGem1Nle0AT/.UwrZWfqtqMiJ0hXeYMvUG');
 DROP ROLE IF EXISTS "5a4dbd41-3fc9-4b3e-b593-a46bc888a7f9";
 CREATE ROLE "5a4dbd41-3fc9-4b3e-b593-a46bc888a7f9";
-GRANT "applicationCreator" TO "5a4dbd41-3fc9-4b3e-b593-a46bc888a7f9";
+GRANT "superadmin" TO "5a4dbd41-3fc9-4b3e-b593-a46bc888a7f9";
 ```
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/model/OreSiRoleForUser.java b/src/main/java/fr/inra/oresing/model/OreSiRoleForUser.java
new file mode 100644
index 0000000000000000000000000000000000000000..82052b2704131a889d877f9aa99ef4d6796ed644
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/model/OreSiRoleForUser.java
@@ -0,0 +1,10 @@
+package fr.inra.oresing.model;
+
+import lombok.Value;
+
+@Value
+public class OreSiRoleForUser {
+    private String userId;
+    private String role;
+    private String applicationPattern;
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/model/OreSiUser.java b/src/main/java/fr/inra/oresing/model/OreSiUser.java
index a62fdc075214a31bcdea759b6f000b781f3d57c9..4227a92c241da62a5600f5e29dbddf306f225560 100644
--- a/src/main/java/fr/inra/oresing/model/OreSiUser.java
+++ b/src/main/java/fr/inra/oresing/model/OreSiUser.java
@@ -3,9 +3,13 @@ package fr.inra.oresing.model;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.util.LinkedList;
+import java.util.List;
+
 @Getter
 @Setter
 public class OreSiUser extends OreSiEntity {
     private String login;
     private String password;
-}
+    private List<String> authorizations= new LinkedList<>();
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/persistence/AuthenticationService.java b/src/main/java/fr/inra/oresing/persistence/AuthenticationService.java
index b7290852426351b1e6b30cfdcb4fc388b0bf04a7..8b2bbf38a621632e679b2bbee4727bb5c212e9ab 100644
--- a/src/main/java/fr/inra/oresing/persistence/AuthenticationService.java
+++ b/src/main/java/fr/inra/oresing/persistence/AuthenticationService.java
@@ -2,11 +2,9 @@ package fr.inra.oresing.persistence;
 
 import at.favre.lib.crypto.bcrypt.BCrypt;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import fr.inra.oresing.model.OreSiUser;
-import fr.inra.oresing.persistence.roles.OreSiApplicationCreatorRole;
-import fr.inra.oresing.persistence.roles.OreSiRole;
-import fr.inra.oresing.persistence.roles.OreSiRoleToAccessDatabase;
-import fr.inra.oresing.persistence.roles.OreSiUserRole;
+import fr.inra.oresing.persistence.roles.*;
 import fr.inra.oresing.rest.CreateUserResult;
 import fr.inra.oresing.rest.LoginResult;
 import fr.inra.oresing.rest.OreSiApiRequestContext;
@@ -17,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.util.UUID;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 @Component
 @Transactional
@@ -110,10 +109,102 @@ public class AuthenticationService {
         return new CreateUserResult(result.getId());
     }
 
-    public void addUserRightCreateApplication(UUID userId) {
+    public OreSiUser deleteUserRightSuperadmin(UUID userId) {
+        resetRole();
+        final OreSiUser oreSiUser = getOreSiUser(userId);
         OreSiUserRole roleToModify = getUserRole(userId);
+        OreSiSuperAdminRole roleToRevoke = OreSiRole.superAdmin();
+        db.removeUserInRole(roleToModify, new OreSiRoleToBeGranted() {
+            @Override
+            public String getAsSqlRole() {
+                return OreSiSuperAdminRole.SUPER_ADMIN.getAsSqlRole();
+            }
+        });
+        return userRepository.findById(userId);
+    }
+    public OreSiUser addUserRightSuperadmin(UUID userId) {
+        resetRole();
+        final OreSiUser oreSiUser = getOreSiUser(userId);
+        OreSiUserRole roleToModify = getUserRole(userId);
+        OreSiSuperAdminRole roleToAdd = OreSiRole.superAdmin();
+        db.addUserInRole(roleToModify, new OreSiRoleToBeGranted() {
+            @Override
+            public String getAsSqlRole() {
+                return OreSiSuperAdminRole.SUPER_ADMIN.getAsSqlRole();
+            }
+        });
+        return userRepository.findById(userId);
+    }
+
+    public OreSiUser deleteUserRightCreateApplication(UUID userId, String applicationPattern) {
+        resetRole();
+        final OreSiUser oreSiUser = getOreSiUser(userId);
+        OreSiUserRole roleToModify = getUserRole(userId);
+        oreSiUser.getAuthorizations().remove(applicationPattern);
+        OreSiApplicationCreatorRole roleToAdd = OreSiRole.applicationCreator();
+        db.removeUserInRole(roleToModify, roleToAdd);
+        final String expression = oreSiUser.getAuthorizations().stream()
+                .map(s -> String.format("%s", s))
+                .collect(Collectors.joining("|", "name ~ '(", ")'"));
+        final SqlPolicy sqlPolicy = new SqlPolicy(
+                String.join("_", OreSiRole.applicationCreator().getAsSqlRole(), userId.toString()),
+                SqlSchema.main().application(),
+                SqlPolicy.PermissiveOrRestrictive.RESTRICTIVE,
+                SqlPolicy.Statement.ALL,
+                new OreSiRole() {
+                    @Override
+                    public String getAsSqlRole() {
+                        return userId.toString();
+                    }
+                },
+                expression
+        );
+        if(oreSiUser.getAuthorizations().isEmpty()){
+            db.dropPolicy(sqlPolicy);
+        }else{
+            db.createPolicy(sqlPolicy);
+        }
+
+        setRoleForClient();
+        if(!Strings.isNullOrEmpty(applicationPattern)){
+            userRepository.updateAuthorizations(userId, oreSiUser.getAuthorizations());
+            userRepository.flush();
+        }
+        resetRole();
+        return userRepository.findById(userId);
+    }
+
+    public OreSiUser addUserRightCreateApplication(UUID userId, String applicationPattern) {
+        resetRole();
+        final OreSiUser oreSiUser = getOreSiUser(userId);
+        OreSiUserRole roleToModify = getUserRole(userId);
+        oreSiUser.getAuthorizations().add(applicationPattern);
         OreSiApplicationCreatorRole roleToAdd = OreSiRole.applicationCreator();
         db.addUserInRole(roleToModify, roleToAdd);
+        final String expression = oreSiUser.getAuthorizations().stream()
+                .map(s -> String.format("%s", s))
+                .collect(Collectors.joining("|", "name ~ '(", ")'"));
+        final SqlPolicy sqlPolicy = new SqlPolicy(
+                String.join("_", OreSiRole.applicationCreator().getAsSqlRole(), userId.toString()),
+                SqlSchema.main().application(),
+                SqlPolicy.PermissiveOrRestrictive.RESTRICTIVE,
+                SqlPolicy.Statement.ALL,
+                new OreSiRole() {
+                    @Override
+                    public String getAsSqlRole() {
+                        return userId.toString();
+                    }
+                },
+                expression
+        );
+        db.createPolicy(sqlPolicy);
+        setRoleForClient();
+        if(!Strings.isNullOrEmpty(applicationPattern)){
+            userRepository.updateAuthorizations(userId, oreSiUser.getAuthorizations());
+            userRepository.flush();
+        }
+        resetRole();
+        return userRepository.findById(userId);
     }
 
     public void removeUser(UUID userId) {
@@ -135,6 +226,19 @@ public class AuthenticationService {
         return getUserRole(user);
     }
 
+    public boolean hasRole(OreSiRole role) {
+        setRoleForClient();
+        final CurrentUserRoles currentUserRoles = userRepository.getRolesForCurrentUser();
+        setRoleAdmin();
+        return currentUserRoles.isSuper() ||
+                currentUserRoles.getCurrentUser().equals(role.getAsSqlRole()) ||
+                currentUserRoles.getMemberOf().contains(role.getAsSqlRole());
+    }
+
+    public boolean isSuperAdmin() {
+        return hasRole(OreSiRole.superAdmin());
+    }
+
     public OreSiUserRole getUserRole(OreSiUser user) {
         return OreSiUserRole.forUser(user);
     }
diff --git a/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java b/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java
index c48c72975479d035f037e760c947a05acfc6e8a0..4c3572c7f87ae1ea575aa03eeb123d2f0ce06f6d 100644
--- a/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java
+++ b/src/main/java/fr/inra/oresing/persistence/JsonTableRepositoryTemplate.java
@@ -43,15 +43,18 @@ abstract class JsonTableRepositoryTemplate<T extends OreSiEntity> implements Ini
         // 5min48 pour 100
         // 5min50 pour 500
         // 6min21 pour 1000
+        final String s = namedParameterJdbcTemplate.queryForObject("select CURRENT_USER::TEXT;", Map.of(), String.class);
         return Iterators.partition(stream.iterator(), 50);
     }
 
     public List<UUID> storeAll(Stream<T> stream) {
+        final String s = namedParameterJdbcTemplate.queryForObject("select CURRENT_USER::TEXT;", Map.of(), String.class);
         String query = getUpsertQuery();
         List<UUID> uuids = new LinkedList<>();
         partition(stream).forEachRemaining(entities -> {
             entities.forEach(e -> {
                 if (e.getId() == null) {
+                    final String a = namedParameterJdbcTemplate.queryForObject("select login from oresiuser where id::TEXT=CURRENT_USER::TEXT;", Map.of(), String.class);
                     e.setId(UUID.randomUUID());
                 }
             });
diff --git a/src/main/java/fr/inra/oresing/persistence/SqlService.java b/src/main/java/fr/inra/oresing/persistence/SqlService.java
index 6bddf622013e4fed989bc1cb02ea6240e0cd22b8..c4b02d756039e8d3ca0201a3183e322082d51da3 100644
--- a/src/main/java/fr/inra/oresing/persistence/SqlService.java
+++ b/src/main/java/fr/inra/oresing/persistence/SqlService.java
@@ -64,7 +64,7 @@ public class SqlService {
 
     public void createPolicy(SqlPolicy sqlPolicy) {
         String createPolicySql = String.format(
-                "CREATE POLICY %s ON %s AS %s FOR %s TO %s USING (%s)",
+                "DROP POLICY IF EXISTS %1$s ON %2$s;CREATE POLICY %1$s ON %2$s AS %3$s FOR %4$s TO %5$s USING (%6$s);",
                 sqlPolicy.getSqlIdentifier(),
                 sqlPolicy.getTable().getSqlIdentifier(),
                 sqlPolicy.getPermissiveOrRestrictive().name(),
@@ -77,7 +77,7 @@ public class SqlService {
 
     public void dropPolicy(SqlPolicy sqlPolicy) {
         String createPolicySql = String.format(
-                "DROP POLICY %s ON %s",
+                "DROP POLICY IF EXISTS %s ON %s",
                 sqlPolicy.getSqlIdentifier(),
                 sqlPolicy.getTable().getSqlIdentifier()
         );
diff --git a/src/main/java/fr/inra/oresing/persistence/UserRepository.java b/src/main/java/fr/inra/oresing/persistence/UserRepository.java
index dfdf47c77b353eb9fcf3ea142dbe81ec31f7ae52..aaae393b8aff9e0335db779ad50ad636cafe827e 100644
--- a/src/main/java/fr/inra/oresing/persistence/UserRepository.java
+++ b/src/main/java/fr/inra/oresing/persistence/UserRepository.java
@@ -2,18 +2,23 @@ package fr.inra.oresing.persistence;
 
 import com.google.common.collect.MoreCollectors;
 import fr.inra.oresing.model.OreSiUser;
+import fr.inra.oresing.persistence.roles.CurrentUserRoles;
+import org.springframework.jdbc.core.RowMapper;
 import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
 import org.springframework.stereotype.Component;
 
-import java.util.Optional;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.stream.Collectors;
 
 @Component
 public class UserRepository extends JsonTableRepositoryTemplate<OreSiUser> {
 
     @Override
     protected String getUpsertQuery() {
-        return "INSERT INTO " + getTable().getSqlIdentifier() + " (id, login, password) SELECT id, login, password FROM json_populate_recordset(NULL::" + getTable().getSqlIdentifier() + ", :json::json)"
-                + " ON CONFLICT (id) DO UPDATE SET updateDate=current_timestamp, login=EXCLUDED.login, password=EXCLUDED.password"
+        return "INSERT INTO " + getTable().getSqlIdentifier() + " (id, login, password, authorizations) SELECT id, login, password, authorizations FROM json_populate_recordset(NULL::" + getTable().getSqlIdentifier() + ", :json::json)"
+                + " ON CONFLICT (id) DO UPDATE SET updateDate=current_timestamp, login=EXCLUDED.login, password=EXCLUDED.password, authorizations=EXCLUDED.authorizations"
                 + " RETURNING id";
     }
     
@@ -33,4 +38,54 @@ public class UserRepository extends JsonTableRepositoryTemplate<OreSiUser> {
                 new MapSqlParameterSource("login", login), getJsonRowMapper()).stream().collect(MoreCollectors.toOptional());
         return result;
     }
-}
+
+    public CurrentUserRoles getRolesForRole(String role) {
+        String roleParam = role==null?"\"current_user\"()":String.format("\"%s\"", role);
+        final RowMapper<CurrentUserRoles> rowMapper = new RowMapper<>() {
+
+            @Override
+            public CurrentUserRoles mapRow(ResultSet rs, int rowNum) throws SQLException {
+                String currentUser = rs.getString("currentUser");
+                List<String> memberOf = Arrays.stream((String[])rs.getArray("memberOf").getArray())
+                        .collect(Collectors.toList());
+                Boolean isSuper = rs.getBoolean("isSuper");
+                return new CurrentUserRoles(currentUser, memberOf, isSuper);
+            }
+        };
+        String query = "WITH RECURSIVE membership_tree(grpid, userid, isSuper) AS (\n" +
+                "    SELECT r.oid, r.oid, r.rolsuper isSuper\n" +
+                "    FROM pg_roles r\n" +
+                "    UNION ALL\n" +
+                "    SELECT m_1.roleid, t_1.userid, t_1.isSuper\n" +
+                "    FROM pg_auth_members m_1, membership_tree t_1\n" +
+                "    WHERE m_1.member = t_1.grpid\n" +
+                ")\n" +
+                "SELECT COALESCE(:roleName, CURRENT_USER) \"currentUser\",r.rolname AS usrname,t.isSuper \"isSuper\",\n" +
+                "       array_agg(m.rolname) memberOf\n" +
+                "FROM membership_tree t, pg_roles r, pg_roles m\n" +
+                "WHERE t.grpid = m.oid AND t.userid = r.oid\n" +
+                "and COALESCE(:roleName, CURRENT_USER)=r.rolname\n" +
+                "group by userid, r.rolname,t.isSuper;";
+        final Map<String, String> parameters =new HashMap<>();
+        parameters.put("roleName", role);
+        return  getNamedParameterJdbcTemplate().queryForObject(
+                query,
+                parameters, rowMapper);
+
+
+    }
+    public CurrentUserRoles getRolesForCurrentUser(){
+        return getRolesForRole(null);
+    }
+
+    public int updateAuthorizations(UUID userId, List<String> authorizations) {
+        String query = "update "+getTable().getSqlIdentifier()+" o\n" +
+                "set authorizations = :authorizations\n" +
+                "where id = :uuid::uuid\n";
+        return getNamedParameterJdbcTemplate().update(
+                query,
+                new MapSqlParameterSource("authorizations", authorizations.toArray(String[]::new))
+                        .addValue("uuid",userId )
+        );
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/persistence/roles/CurrentUserRoles.java b/src/main/java/fr/inra/oresing/persistence/roles/CurrentUserRoles.java
new file mode 100644
index 0000000000000000000000000000000000000000..46ceefdf3df5f4d0c46b0a48e4999bd3fba4e25b
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/persistence/roles/CurrentUserRoles.java
@@ -0,0 +1,19 @@
+package fr.inra.oresing.persistence.roles;
+
+import lombok.Getter;
+
+import java.util.List;
+
+@Getter
+public class CurrentUserRoles {
+    String currentUser;
+    List<String> memberOf;
+
+    boolean isSuper;
+
+    public CurrentUserRoles(String currentUser, List<String> memberOf, boolean isSuper) {
+        this.currentUser = currentUser;
+        this.memberOf = memberOf;
+        this.isSuper = isSuper;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/persistence/roles/OreSiRole.java b/src/main/java/fr/inra/oresing/persistence/roles/OreSiRole.java
index c955582fa892fb104ca40eaf6c9e11d7a0782fe0..20fce679088e3dd26aacbfb9c229cf54529a7f50 100644
--- a/src/main/java/fr/inra/oresing/persistence/roles/OreSiRole.java
+++ b/src/main/java/fr/inra/oresing/persistence/roles/OreSiRole.java
@@ -2,7 +2,9 @@ package fr.inra.oresing.persistence.roles;
 
 import fr.inra.oresing.persistence.WithSqlIdentifier;
 
-public interface OreSiRole extends WithSqlIdentifier {
+@FunctionalInterface
+public interface
+OreSiRole extends WithSqlIdentifier {
 
     static OreSiAnonymousRole anonymous() {
         return OreSiAnonymousRole.ANONYMOUS;
@@ -22,4 +24,4 @@ public interface OreSiRole extends WithSqlIdentifier {
     default String getSqlIdentifier() {
         return "\"" + getAsSqlRole() + "\"";
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/AuthorizationRequest.java b/src/main/java/fr/inra/oresing/rest/AuthorizationRequest.java
index b33be67ac449159a221ba68cdca3c27d408f4333..3e0a8d20ced9561e19731e19ea6a0d441983bc9b 100644
--- a/src/main/java/fr/inra/oresing/rest/AuthorizationRequest.java
+++ b/src/main/java/fr/inra/oresing/rest/AuthorizationRequest.java
@@ -9,5 +9,7 @@ public class AuthorizationRequest {
 
     String applicationNameOrId;
 
+    String dataType;
+
     UUID authorizationId;
-}
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/AuthorizationResources.java b/src/main/java/fr/inra/oresing/rest/AuthorizationResources.java
index 374ea71e5803327e9f6dca60734e9a8cac5baa5d..9f345d462844825b5a9cdd7c494038cbc2f4ced1 100644
--- a/src/main/java/fr/inra/oresing/rest/AuthorizationResources.java
+++ b/src/main/java/fr/inra/oresing/rest/AuthorizationResources.java
@@ -2,6 +2,8 @@ package fr.inra.oresing.rest;
 
 import com.google.common.collect.ImmutableSet;
 import fr.inra.oresing.model.OreSiAuthorization;
+import fr.inra.oresing.model.OreSiRoleForUser;
+import fr.inra.oresing.model.OreSiUser;
 import fr.inra.oresing.persistence.roles.OreSiRightOnApplicationRole;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
@@ -28,22 +30,40 @@ public class AuthorizationResources {
         Set<UUID> previousUsers = authorization.getUuid()==null?new HashSet<>():authorization.getUsersId();
         OreSiAuthorization oreSiAuthorization = authorizationService.addAuthorization(authorization);
         UUID authId = oreSiAuthorization.getId();
-            OreSiRightOnApplicationRole roleForAuthorization = null;
-        if(authorization.getUuid()==null){
-             roleForAuthorization = authorizationService.createRoleForAuthorization(authorization, oreSiAuthorization);
-        }
-
+        OreSiRightOnApplicationRole roleForAuthorization =  authorizationService.createRoleForAuthorization(authorization, oreSiAuthorization);
         authorizationService.updateRoleForManagement(previousUsers, oreSiAuthorization);
         String uri = UriUtils.encodePath("/applications/" + authorization.getApplicationNameOrId() + "/dataType/" + authorization.getDataType() + "/authorization/" + authId.toString(), Charset.defaultCharset());
         return ResponseEntity.created(URI.create(uri)).body(Map.of("authorizationId", authId.toString()));
     }
 
     @GetMapping(value = "/applications/{nameOrId}/dataType/{dataType}/authorization/{authorizationId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<GetAuthorizationResult> getAuthorization(@PathVariable("nameOrId") String applicationNameOrId, @PathVariable("authorizationId") UUID authorizationId) {
-        GetAuthorizationResult getAuthorizationResult = authorizationService.getAuthorization(new AuthorizationRequest(applicationNameOrId, authorizationId));
+    public ResponseEntity<GetAuthorizationResult> getAuthorization(@PathVariable("nameOrId") String applicationNameOrId,@PathVariable("dataType") String dataType, @PathVariable("authorizationId") UUID authorizationId) {
+        GetAuthorizationResult getAuthorizationResult = authorizationService.getAuthorization(new AuthorizationRequest(applicationNameOrId,dataType,  authorizationId));
         return ResponseEntity.ok(getAuthorizationResult);
     }
 
+    @DeleteMapping(value = "/authorization/{role}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<OreSiUser> deleteAuthorization(
+            @PathVariable(name = "role", required = true)String role,
+            @RequestParam(name = "userId", required = true)String userId,
+            @RequestParam(name = "applicationPattern", required = false)String applicationPattern)
+            throws NotSuperAdminException, NotApplicationCreatorRightsException {
+        final OreSiRoleForUser roleForUser = new OreSiRoleForUser(userId, role, applicationPattern);
+        OreSiUser user = authorizationService.deleteRoleUser(roleForUser);
+        return ResponseEntity.ok(user);
+    }
+
+    @PutMapping(value = "/authorization/{role}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<OreSiUser> addAuthorization(
+            @PathVariable(name = "role", required = true)String role,
+            @RequestParam(name = "userId", required = true)String userId,
+            @RequestParam(name = "applicationPattern", required = false)String applicationPattern)
+            throws NotSuperAdminException, NotApplicationCreatorRightsException {
+        final OreSiRoleForUser roleForUser = new OreSiRoleForUser(userId, role, applicationPattern);
+        OreSiUser user = authorizationService.addRoleUser(roleForUser);
+        return ResponseEntity.ok(user);
+    }
+
     @GetMapping(value = "/applications/{nameOrId}/dataType/{dataType}/authorization", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<ImmutableSet<GetAuthorizationResult>> getAuthorizations(@PathVariable("nameOrId") String applicationNameOrId, @PathVariable("dataType") String dataType) {
         ImmutableSet<GetAuthorizationResult> getAuthorizationResults = authorizationService.getAuthorizations(applicationNameOrId, dataType);
@@ -57,8 +77,8 @@ public class AuthorizationResources {
     }
 
     @DeleteMapping(value = "/applications/{nameOrId}/dataType/{dataType}/authorization/{authorizationId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<?> revokeAuthorization(@PathVariable("nameOrId") String applicationNameOrId, @PathVariable("authorizationId") UUID authorizationId) {
-        authorizationService.revoke(new AuthorizationRequest(applicationNameOrId, authorizationId));
+    public ResponseEntity<?> revokeAuthorization(@PathVariable("nameOrId") String applicationNameOrId, @PathVariable("dataType") String dataType,  @PathVariable("authorizationId") UUID authorizationId) {
+        authorizationService.revoke(new AuthorizationRequest(applicationNameOrId, dataType,  authorizationId));
         return ResponseEntity.noContent().build();
     }
 }
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/AuthorizationService.java b/src/main/java/fr/inra/oresing/rest/AuthorizationService.java
index 9e3ebe6e26f1e803d56c2fdc9b84ae26b476c284..f13f3a7fd6e407f23c710cda8c76668afa0d323a 100644
--- a/src/main/java/fr/inra/oresing/rest/AuthorizationService.java
+++ b/src/main/java/fr/inra/oresing/rest/AuthorizationService.java
@@ -6,6 +6,7 @@ import fr.inra.oresing.checker.ReferenceLineChecker;
 import fr.inra.oresing.model.*;
 import fr.inra.oresing.persistence.*;
 import fr.inra.oresing.persistence.roles.OreSiRightOnApplicationRole;
+import fr.inra.oresing.persistence.roles.OreSiRole;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -47,6 +48,17 @@ public class AuthorizationService {
         OreSiRightOnApplicationRole oreSiRightOnApplicationRole = OreSiRightOnApplicationRole.managementRole(application, modifiedAuthorization.getId());
         db.addUserInRole(oreSiRightOnApplicationRole, OreSiRightOnApplicationRole.readerOn(application));
         addOrRemoveAuthorizationForUsers(previousUsers, newUsers, oreSiRightOnApplicationRole);
+
+        final String expression = String.format("name = '%s'",application.getName());
+        final SqlPolicy sqlPolicy = new SqlPolicy(
+                String.join("_", "application","reader", oreSiRightOnApplicationRole.getAsSqlRole()),
+                SqlSchema.main().application(),
+                SqlPolicy.PermissiveOrRestrictive.PERMISSIVE,
+                SqlPolicy.Statement.SELECT,
+                oreSiRightOnApplicationRole,
+                expression
+        );
+        db.createPolicy(sqlPolicy);
         if (modifiedAuthorization.getAuthorizations().containsKey(OperationType.publication)) {
             db.addUserInRole(oreSiRightOnApplicationRole, OreSiRightOnApplicationRole.writerOn(application));
             SqlPolicy publishPolicy = toDatatypePolicy(modifiedAuthorization, oreSiRightOnApplicationRole, OperationType.publication, SqlPolicy.Statement.INSERT);
@@ -91,7 +103,7 @@ public class AuthorizationService {
                     authByType.forEach(authorization -> {
                         authorization.getDataGroup()
                                 .forEach(datagroup -> Preconditions.checkArgument(authorizationDescription.getDataGroups().containsKey(datagroup)));
-                        Set<String> labels =Optional.ofNullable( authorizationDescription)
+                        Set<String> labels = Optional.ofNullable(authorizationDescription)
                                 .map(Configuration.AuthorizationDescription::getAuthorizationScopes)
                                 .map(Map::keySet)
                                 .orElseGet(Set::of);
@@ -170,6 +182,15 @@ public class AuthorizationService {
         UUID authorizationId = revokeAuthorizationRequest.getAuthorizationId();
         OreSiAuthorization oreSiAuthorization = authorizationRepository.findById(authorizationId);
         OreSiRightOnApplicationRole oreSiRightOnApplicationRole = OreSiRightOnApplicationRole.managementRole(application, authorizationId);
+        final SqlPolicy sqlPolicy = new SqlPolicy(
+                String.join("_", "application","reader", oreSiRightOnApplicationRole.getAsSqlRole()),
+                SqlSchema.main().application(),
+                null,
+                null,
+                null,
+                null
+        );
+        db.dropPolicy(sqlPolicy);
         if (oreSiAuthorization.getAuthorizations().containsKey(OperationType.publication)) {
             db.addUserInRole(oreSiRightOnApplicationRole, OreSiRightOnApplicationRole.writerOn(application));
             SqlPolicy publishPolicy = toDatatypePolicy(oreSiAuthorization, oreSiRightOnApplicationRole, OperationType.publication, SqlPolicy.Statement.INSERT);
@@ -260,14 +281,14 @@ public class AuthorizationService {
 
     private ImmutableSortedSet<GetGrantableResult.DataGroup> getDataGroups(Application application, String dataType) {
         ImmutableSortedSet<GetGrantableResult.DataGroup> dataGroups =
-        Optional.of(application.getConfiguration().getDataTypes().get(dataType))
-                .map(Configuration.DataTypeDescription::getAuthorization)
-                .map(Configuration.AuthorizationDescription::getDataGroups)
-                .map(dg -> dg.entrySet().stream()
-                    .map(dataGroupEntry -> new GetGrantableResult.DataGroup(dataGroupEntry.getKey(), dataGroupEntry.getValue().getLabel()))
-                    .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.DataGroup::getId)) )
-                )
-                .orElseGet(ImmutableSortedSet::of);
+                Optional.of(application.getConfiguration().getDataTypes().get(dataType))
+                        .map(Configuration.DataTypeDescription::getAuthorization)
+                        .map(Configuration.AuthorizationDescription::getDataGroups)
+                        .map(dg -> dg.entrySet().stream()
+                                .map(dataGroupEntry -> new GetGrantableResult.DataGroup(dataGroupEntry.getKey(), dataGroupEntry.getValue().getLabel()))
+                                .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.DataGroup::getId)))
+                        )
+                        .orElseGet(ImmutableSortedSet::of);
         return dataGroups;
     }
 
@@ -284,22 +305,22 @@ public class AuthorizationService {
         return Optional.of(application.getConfiguration().getDataTypes().get(dataType))
                 .map(Configuration.DataTypeDescription::getAuthorization)
                 .map(Configuration.AuthorizationDescription::getAuthorizationScopes)
-                .map(authorizationScopes-> authorizationScopes.entrySet().stream()
+                .map(authorizationScopes -> authorizationScopes.entrySet().stream()
                         .map(
-                        authorizationScopeEntry -> {
-                    String variable = authorizationScopeEntry.getValue().getVariable();
-                    String component = authorizationScopeEntry.getValue().getComponent();
-                    VariableComponentKey variableComponentKey = new VariableComponentKey(variable, component);
-                    ReferenceLineChecker referenceLineChecker = referenceLineCheckers.get(variableComponentKey);
-                    String lowestLevelReference = referenceLineChecker.getRefType();
-                    HierarchicalReferenceAsTree hierarchicalReferenceAsTree = oreSiService.getHierarchicalReferenceAsTree(application, lowestLevelReference);
-                    ImmutableSortedSet<GetGrantableResult.AuthorizationScope.Option> rootOptions = hierarchicalReferenceAsTree.getRoots().stream()
-                            .map(rootReferenceValue -> toOption(hierarchicalReferenceAsTree, rootReferenceValue))
-                            .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.AuthorizationScope.Option::getId)));
-                    String authorizationScopeId = authorizationScopeEntry.getKey();
-                    return new GetGrantableResult.AuthorizationScope(authorizationScopeId, authorizationScopeId, rootOptions);
-                    })
-                .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.AuthorizationScope::getId)))
+                                authorizationScopeEntry -> {
+                                    String variable = authorizationScopeEntry.getValue().getVariable();
+                                    String component = authorizationScopeEntry.getValue().getComponent();
+                                    VariableComponentKey variableComponentKey = new VariableComponentKey(variable, component);
+                                    ReferenceLineChecker referenceLineChecker = referenceLineCheckers.get(variableComponentKey);
+                                    String lowestLevelReference = referenceLineChecker.getRefType();
+                                    HierarchicalReferenceAsTree hierarchicalReferenceAsTree = oreSiService.getHierarchicalReferenceAsTree(application, lowestLevelReference);
+                                    ImmutableSortedSet<GetGrantableResult.AuthorizationScope.Option> rootOptions = hierarchicalReferenceAsTree.getRoots().stream()
+                                            .map(rootReferenceValue -> toOption(hierarchicalReferenceAsTree, rootReferenceValue))
+                                            .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.AuthorizationScope.Option::getId)));
+                                    String authorizationScopeId = authorizationScopeEntry.getKey();
+                                    return new GetGrantableResult.AuthorizationScope(authorizationScopeId, authorizationScopeId, rootOptions);
+                                })
+                        .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.AuthorizationScope::getId)))
                 )
                 .orElseGet(ImmutableSortedSet::of);
     }
@@ -310,4 +331,74 @@ public class AuthorizationService {
                 .collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparing(GetGrantableResult.AuthorizationScope.Option::getId)));
         return new GetGrantableResult.AuthorizationScope.Option(referenceValue.getHierarchicalKey().getSql(), referenceValue.getHierarchicalKey().getSql(), options);
     }
+
+    public OreSiUserResult deleteRoleUser(OreSiRoleForUser roleForUser) {
+        if (OreSiRole.superAdmin().getAsSqlRole().equals(roleForUser.getRole())) {
+            return deleteAdminRoleUser(roleForUser);
+        } else if (OreSiRole.applicationCreator().getAsSqlRole().equals(roleForUser.getRole())) {
+            return deleteApplicationCreatorRoleUser(roleForUser);
+        }
+        throw new BadRoleException("cantDeleteRole", roleForUser.getRole());
+    }
+
+    private OreSiUserResult deleteApplicationCreatorRoleUser(OreSiRoleForUser oreSiUserRoleApplicationCreator) {
+        boolean canAddApplicationCreatorRole = canAddApplicationCreatorRole(oreSiUserRoleApplicationCreator);
+        if (canAddApplicationCreatorRole) {
+            final OreSiUser user = authenticationService.deleteUserRightCreateApplication(UUID.fromString(oreSiUserRoleApplicationCreator.getUserId()), oreSiUserRoleApplicationCreator.getApplicationPattern());
+            return new OreSiUserResult(user, userRepository.getRolesForRole(oreSiUserRoleApplicationCreator.getUserId()));
+        }
+        throw new NotSuperAdminException();
+    }
+
+    private boolean canAddApplicationCreatorRole(OreSiRoleForUser oreSiUserRoleApplicationCreator) {
+        boolean canAddApplicationCreatorRole = false;
+        if (authenticationService.hasRole(OreSiRole.superAdmin())) {
+            canAddApplicationCreatorRole = true;
+        } else if (authenticationService.hasRole(OreSiRole.applicationCreator())) {
+            final OreSiUser user = userRepository.findById(UUID.fromString(oreSiUserRoleApplicationCreator.getUserId()));
+            if (user.getAuthorizations().contains(oreSiUserRoleApplicationCreator.getApplicationPattern())) {
+                canAddApplicationCreatorRole = true;
+            } else {
+                throw new NotApplicationCreatorRightsException(oreSiUserRoleApplicationCreator.getApplicationPattern(), user.getAuthorizations());
+            }
+
+        }
+        return canAddApplicationCreatorRole;
+    }
+
+    private OreSiUserResult deleteAdminRoleUser(OreSiRoleForUser oreSiRoleForUserAdmin) {
+        boolean canAddsupeadmin = false;
+        if (authenticationService.hasRole(OreSiRole.superAdmin())) {
+            OreSiUser user = authenticationService.deleteUserRightSuperadmin(UUID.fromString(oreSiRoleForUserAdmin.getUserId()));
+            return new OreSiUserResult(user, userRepository.getRolesForRole(oreSiRoleForUserAdmin.getUserId()));
+        }
+        throw new NotSuperAdminException();
+    }
+
+    public OreSiUserResult addRoleUser(OreSiRoleForUser roleForUser) {
+        if (OreSiRole.superAdmin().getAsSqlRole().equals(roleForUser.getRole())) {
+            return addAdminRoleUser(roleForUser);
+        } else if (OreSiRole.applicationCreator().getAsSqlRole().equals(roleForUser.getRole())) {
+            return addApplicationCreatorRoleUser(roleForUser);
+        }
+        throw new BadRoleException("cantSetRole", roleForUser.getRole());
+    }
+
+    private OreSiUserResult addApplicationCreatorRoleUser(OreSiRoleForUser oreSiUserRoleApplicationCreator) {
+        boolean canAddApplicationCreatorRole = canAddApplicationCreatorRole(oreSiUserRoleApplicationCreator);
+        if (canAddApplicationCreatorRole) {
+            final OreSiUser user = authenticationService.addUserRightCreateApplication(UUID.fromString(oreSiUserRoleApplicationCreator.getUserId()), oreSiUserRoleApplicationCreator.getApplicationPattern());
+            return new OreSiUserResult(user, userRepository.getRolesForRole(oreSiUserRoleApplicationCreator.getUserId()));
+        }
+        throw new NotSuperAdminException();
+    }
+
+    private OreSiUserResult addAdminRoleUser(OreSiRoleForUser oreSiRoleForUserAdmin) {
+        boolean canAddsupeadmin = false;
+        if (authenticationService.hasRole(OreSiRole.superAdmin())) {
+            OreSiUser user = authenticationService.addUserRightSuperadmin(UUID.fromString(oreSiRoleForUserAdmin.getUserId()));
+            return new OreSiUserResult(user, userRepository.getRolesForRole(oreSiRoleForUserAdmin.getUserId()));
+        }
+        throw new NotSuperAdminException();
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/BadRoleException.java b/src/main/java/fr/inra/oresing/rest/BadRoleException.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f818b7528650f7f45b475a2d634f7fe22fba0cf
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/rest/BadRoleException.java
@@ -0,0 +1,19 @@
+package fr.inra.oresing.rest;
+
+import fr.inra.oresing.OreSiTechnicalException;
+import lombok.Getter;
+
+@Getter
+public class BadRoleException  extends OreSiTechnicalException {
+    String role;
+
+    public BadRoleException(String message, String role, Throwable cause) {
+        super(message, cause);
+        this.role = role;
+    }
+
+    public BadRoleException(String message, String role) {
+        super(message);
+        this.role = role;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/NotApplicationCreatorRightsException.java b/src/main/java/fr/inra/oresing/rest/NotApplicationCreatorRightsException.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f679dfab760f64d1307d216313812e45460be02
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/rest/NotApplicationCreatorRightsException.java
@@ -0,0 +1,27 @@
+package fr.inra.oresing.rest;
+
+import fr.inra.oresing.OreSiTechnicalException;
+
+import java.util.List;
+
+public class NotApplicationCreatorRightsException extends OreSiTechnicalException {
+    public final static String NO_RIGHT_FOR_APPLICATION_CREATION = "NO_RIGHT_FOR_APPLICATION_CREATION";
+    String applicationName;
+    List<String> applicationRestrictions;
+    public NotApplicationCreatorRightsException(String applicationName) {
+        super(NO_RIGHT_FOR_APPLICATION_CREATION);
+        this.applicationName = applicationName;
+        this.applicationRestrictions = List.of();
+    }
+    public NotApplicationCreatorRightsException(String applicationName, List<String> applicationRestrictions) {
+        super(NO_RIGHT_FOR_APPLICATION_CREATION);
+        this.applicationName = applicationName;
+        this.applicationRestrictions = applicationRestrictions;
+    }
+
+    public NotApplicationCreatorRightsException(Throwable cause) {
+        super(NO_RIGHT_FOR_APPLICATION_CREATION, cause);
+        this.applicationName = applicationName;
+        this.applicationRestrictions = List.of();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/NotSuperAdminException.java b/src/main/java/fr/inra/oresing/rest/NotSuperAdminException.java
new file mode 100644
index 0000000000000000000000000000000000000000..cbe5d9015f4053dc7d7d0ee9d1e03a5894d12cfd
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/rest/NotSuperAdminException.java
@@ -0,0 +1,14 @@
+package fr.inra.oresing.rest;
+
+import fr.inra.oresing.OreSiTechnicalException;
+
+public class NotSuperAdminException extends OreSiTechnicalException {
+    public final static String SUPER_ADMIN_REQUIRED_FOR_OPERATION = "SUPER_ADMIN_REQUIRED_FOR_OPERATION";
+    public NotSuperAdminException() {
+        super(SUPER_ADMIN_REQUIRED_FOR_OPERATION);
+    }
+
+    public NotSuperAdminException(Throwable cause) {
+        super(SUPER_ADMIN_REQUIRED_FOR_OPERATION, cause);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/OreExceptionHandler.java b/src/main/java/fr/inra/oresing/rest/OreExceptionHandler.java
index 2e1413f5324a527cb56d8cb2ef0e4426603c03d6..8a9fec6a3cc9a89521d77041384e84e9f836c96d 100644
--- a/src/main/java/fr/inra/oresing/rest/OreExceptionHandler.java
+++ b/src/main/java/fr/inra/oresing/rest/OreExceptionHandler.java
@@ -9,8 +9,13 @@ import org.postgresql.util.PSQLException;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.jdbc.BadSqlGrammarException;
+import org.springframework.validation.ObjectError;
 import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.bind.support.WebExchangeBindException;
+
+import java.util.List;
 
 import java.util.List;
 
@@ -22,6 +27,12 @@ public class OreExceptionHandler {
     public ResponseEntity<String> handle(AuthenticationFailure eee) {
         return ResponseEntity.status(HttpStatus.FORBIDDEN).body(eee.getMessage());
     }
+    @ExceptionHandler
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public List<ObjectError> exception(WebExchangeBindException ex) {
+        log.error("{}", ex.getLocalizedMessage(), ex);
+        return ex.getAllErrors();
+    }
 
     @ExceptionHandler(value = BadSqlGrammarException.class)
     public ResponseEntity<String> handle(BadSqlGrammarException badSqlGrammarException) {
diff --git a/src/main/java/fr/inra/oresing/rest/OreSiService.java b/src/main/java/fr/inra/oresing/rest/OreSiService.java
index 3f6272b8620b8e8cc6ee6f96451531e294a64d81..124097dd4f76f5bbae158aee8d6e6478de2b584d 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiService.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiService.java
@@ -14,8 +14,7 @@ import fr.inra.oresing.groovy.StringGroovyExpression;
 import fr.inra.oresing.model.*;
 import fr.inra.oresing.model.chart.OreSiSynthesis;
 import fr.inra.oresing.persistence.*;
-import fr.inra.oresing.persistence.roles.OreSiRightOnApplicationRole;
-import fr.inra.oresing.persistence.roles.OreSiUserRole;
+import fr.inra.oresing.persistence.roles.*;
 import fr.inra.oresing.rest.validationcheckresults.DateValidationCheckResult;
 import fr.inra.oresing.rest.validationcheckresults.DefaultValidationCheckResult;
 import fr.inra.oresing.rest.validationcheckresults.ReferenceValidationCheckResult;
@@ -31,6 +30,7 @@ import org.flywaydb.core.Flyway;
 import org.flywaydb.core.api.Location;
 import org.flywaydb.core.api.configuration.ClassicConfiguration;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.BadSqlGrammarException;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
@@ -70,6 +70,13 @@ public class OreSiService {
     @Autowired
     private AuthenticationService authenticationService;
 
+
+    @Autowired
+    private AuthorizationService authorizationService;
+
+    @Autowired
+    private UserRepository userRepository;
+
     @Autowired
     private CheckerFactory checkerFactory;
 
@@ -120,6 +127,9 @@ public class OreSiService {
     }
 
     public UUID createApplication(String name, MultipartFile configurationFile, String comment) throws IOException, BadApplicationConfigurationException {
+        final OreSiUser currentUser = userRepository.findById(request.getRequestClient().getId());
+        final boolean canCreateApplication = currentUser.getAuthorizations().stream()
+                .anyMatch(s -> name.matches(s));
         Application app = new Application();
         app.setName(name);
         app.setComment(comment);
@@ -289,7 +299,20 @@ public class OreSiService {
     }
 
     private UUID changeApplicationConfiguration(Application app, MultipartFile configurationFile, Function<Application, Application> initApplication) throws IOException, BadApplicationConfigurationException {
-
+        final String applicationName = app.getName();
+        final OreSiUser currentUser = userRepository.findById(request.getRequestClient().getId());
+        authenticationService.setRoleForClient();
+        final boolean canCreateApplication = authenticationService.hasRole(OreSiRole.applicationCreator()) && currentUser.getAuthorizations().stream()
+                .anyMatch(s -> applicationName.matches(s));
+        final boolean isSuperAdmin = authenticationService.isSuperAdmin();
+        if (!(isSuperAdmin || canCreateApplication)) {
+            throw new NotApplicationCreatorRightsException(applicationName, currentUser.getAuthorizations());
+        } else if (!isSuperAdmin) {
+            currentUser.getAuthorizations().stream()
+                    .filter(s -> isSuperAdmin || applicationName.matches(s))
+                    .findAny()
+                    .orElseThrow(() -> new NotApplicationCreatorRightsException(applicationName));
+        }
         ConfigurationParsingResult configurationParsingResult;
         if (configurationFile.getOriginalFilename().matches(".*\\.zip")) {
             final byte[] bytes = new MultiYaml().parseConfigurationBytes(configurationFile);
@@ -302,11 +325,15 @@ public class OreSiService {
         app.setReferenceType(new ArrayList<>(configuration.getReferences().keySet()));
         app.setDataType(new ArrayList<>(configuration.getDataTypes().keySet()));
         app.setConfiguration(configuration);
-        app = initApplication.apply(app);
-        UUID confId = storeFile(app, configurationFile, app.getComment());
-        app.setConfigFile(confId);
-        UUID appId = repo.application().store(app);
-        return appId;
+        try {
+            app = initApplication.apply(app);
+            UUID confId = storeFile(app, configurationFile, app.getComment());
+            app.setConfigFile(confId);
+            UUID appId = repo.application().store(app);
+            return appId;
+        } catch (BadSqlGrammarException bsge) {
+            throw new NotApplicationCreatorRightsException(applicationName, currentUser.getAuthorizations());
+        }
     }
 
     public UUID addReference(Application app, String refType, MultipartFile file) throws IOException {
@@ -569,13 +596,13 @@ public class OreSiService {
         final Configuration.AuthorizationDescription authorization = dataTypeDescription.getAuthorization();
         final boolean haveAuthorizations = authorization != null;
 
-        final DateLineChecker timeScopeDateLineChecker = haveAuthorizations && authorization.getTimeScope()!=null?
+        final DateLineChecker timeScopeDateLineChecker = haveAuthorizations && authorization.getTimeScope() != null ?
                 lineCheckers.stream()
-                    .filter(lineChecker -> lineChecker instanceof DateLineChecker)
-                    .map(lineChecker -> (DateLineChecker) lineChecker)
-                    .filter(dateLineChecker -> dateLineChecker.getTarget().equals(authorization.getTimeScope()))
-                    .collect(MoreCollectors.onlyElement())
-                :null;
+                        .filter(lineChecker -> lineChecker instanceof DateLineChecker)
+                        .map(lineChecker -> (DateLineChecker) lineChecker)
+                        .filter(dateLineChecker -> dateLineChecker.getTarget().equals(authorization.getTimeScope()))
+                        .collect(MoreCollectors.onlyElement())
+                : null;
 
         return rowWithData -> {
             Datum datum = Datum.copyOf(rowWithData.getDatum());
@@ -611,7 +638,7 @@ public class OreSiService {
                 return Stream.empty();
             }
             LocalDateTimeRange timeScope;
-            if (timeScopeDateLineChecker!=null) {
+            if (timeScopeDateLineChecker != null) {
                 String timeScopeValue = datum.get(authorization.getTimeScope());
                 timeScope = LocalDateTimeRange.parse(timeScopeValue, timeScopeDateLineChecker);
             } else {
@@ -619,12 +646,12 @@ public class OreSiService {
             }
 
             Map<String, Ltree> requiredAuthorizations = new LinkedHashMap<>();
-            if(haveAuthorizations) {
+            if (haveAuthorizations) {
                 authorization.getAuthorizationScopes().forEach((authorizationScope, authorizationScopeDescription) -> {
                     VariableComponentKey variableComponentKey = authorizationScopeDescription.getVariableComponentKey();
                     String requiredAuthorization = datum.get(variableComponentKey);
                     Ltree.checkSyntax(requiredAuthorization);
-                requiredAuthorizations.put(authorizationScope, Ltree.fromSql(requiredAuthorization));
+                    requiredAuthorizations.put(authorizationScope, Ltree.fromSql(requiredAuthorization));
                 });
             }
             checkTimescopRangeInDatasetRange(timeScope, errors, binaryFileDataset, rowWithData.getLineNumber());
@@ -636,13 +663,13 @@ public class OreSiService {
                 return Stream.of((Data) null);
             }
             LinkedHashMap<String, Configuration.DataGroupDescription> dataGroups;
-            if(!haveAuthorizations){
-                dataGroups=new LinkedHashMap<>();
+            if (!haveAuthorizations) {
+                dataGroups = new LinkedHashMap<>();
                 final Configuration.DataGroupDescription dataGroupDescription = new Configuration.DataGroupDescription();
                 dataGroupDescription.setData(dataTypeDescription.getData().keySet());
                 dataGroups.put("_default_", dataGroupDescription);
-            }else{
-                dataGroups= authorization.getDataGroups();
+            } else {
+                dataGroups = authorization.getDataGroups();
             }
             Stream<Data> dataStream = dataGroups.entrySet().stream().map(entry -> {
                 String dataGroup = entry.getKey();
diff --git a/src/main/java/fr/inra/oresing/rest/OreSiUserResult.java b/src/main/java/fr/inra/oresing/rest/OreSiUserResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..4581252c2d12d267853c6b3a100492a1df39d8eb
--- /dev/null
+++ b/src/main/java/fr/inra/oresing/rest/OreSiUserResult.java
@@ -0,0 +1,21 @@
+package fr.inra.oresing.rest;
+
+import fr.inra.oresing.model.OreSiUser;
+import fr.inra.oresing.persistence.roles.CurrentUserRoles;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class
+OreSiUserResult extends OreSiUser {
+    private CurrentUserRoles roles;
+
+    public OreSiUserResult(OreSiUser user, CurrentUserRoles userRoles) {
+        super();
+        setLogin(user.getLogin());
+        setAuthorizations(user.getAuthorizations());
+        setId(user.getId());
+        setRoles(userRoles);
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/migration/main/V1__init_schema.sql b/src/main/resources/migration/main/V1__init_schema.sql
index 0fc93b18c000b1cb714c4dcb06d1c3324fbe504e..550c3ee46fcad30765c8e38382348806fee894d4 100644
--- a/src/main/resources/migration/main/V1__init_schema.sql
+++ b/src/main/resources/migration/main/V1__init_schema.sql
@@ -2,7 +2,8 @@ CREATE EXTENSION IF NOT EXISTS "pgcrypto";
 CREATE EXTENSION IF NOT EXISTS "ltree";
 
 CREATE OR REPLACE FUNCTION fk_check(targetTable TEXT, uid UUID)
-RETURNS BOOLEAN AS $$
+    RETURNS BOOLEAN AS
+$$
 DECLARE
     result TEXT;
 BEGIN
@@ -21,10 +22,11 @@ CREATE OR REPLACE FUNCTION public.jsonb_count_items(IN json jsonb)
     VOLATILE
     PARALLEL UNSAFE
     COST 100
-
-AS $BODY$
-with elements as (select json->jsonb_object_keys(json) element)
-select sum(jsonb_array_length(element)) from elements
+AS
+$BODY$
+with elements as (select json -> jsonb_object_keys(json) element)
+select sum(jsonb_array_length(element))
+from elements
 $BODY$;
 
 /*-- check les foreign key pour le colonne references de la table data
@@ -41,23 +43,26 @@ $$ language 'plpgsql';*/
 
 --check if all elements of oreSiUser array are users
 CREATE OR REPLACE FUNCTION checks_users(users uuid[])
-    RETURNS BOOLEAN AS $$
+    RETURNS BOOLEAN AS
+$$
 DECLARE
     checked BOOLEAN;
 BEGIN
     select users <@ array_agg(id)::uuid[] into checked from OreSiUser OSU group by users;
     return checked;
 END;
-$$  LANGUAGE plpgsql;
+$$ LANGUAGE plpgsql;
 
 
 
 CREATE OR REPLACE FUNCTION name_check(application UUID, targetColumn TEXT, val TEXT)
-RETURNS BOOLEAN AS $$
+    RETURNS BOOLEAN AS
+$$
 DECLARE
     result TEXT;
 BEGIN
-    EXECUTE format('select count(id) > 0 from Application where id=$1 AND $2 = ANY (%s);', targetColumn) INTO result USING application, val;
+    EXECUTE format('select count(id) > 0 from Application where id=$1 AND $2 = ANY (%s);',
+                   targetColumn) INTO result USING application, val;
     RETURN result;
 END;
 $$ language 'plpgsql';
@@ -67,24 +72,28 @@ create domain EntityRef as uuid NOT NULL;
 create domain ListEntityRef as uuid[] NOT NULL;
 create domain DateOrNow as timestamp DEFAULT current_timestamp;
 
-create table OreSiUser (
-    id EntityId PRIMARY KEY,
-    creationDate DateOrNow,
-    updateDate DateOrNow,
-    login Text UNIQUE NOT NULL,
-    password text NOT NULL
+create table OreSiUser
+(
+    id             EntityId PRIMARY KEY,
+    creationDate   DateOrNow,
+    updateDate     DateOrNow,
+    login          Text UNIQUE NOT NULL,
+    password       text        NOT NULL,-- can be null
+    authorizations TEXT[]
 );
 
-create table Application (
-    id EntityId PRIMARY KEY,
-    creationDate DateOrNow,
-    updateDate DateOrNow,
-    name Text,
-    comment TEXT NOT NULL,
+create table Application
+(
+    id            EntityId PRIMARY KEY,
+    creator       name default current_user,
+    creationDate  DateOrNow,
+    updateDate    DateOrNow,
+    name          Text,
+    comment       TEXT NOT NULL,
     referenceType TEXT[], -- liste des types de references existantes
-    dataType TEXT[],      -- liste des types de data existants
+    dataType      TEXT[], -- liste des types de data existants
     configuration jsonb,  -- le fichier de configuration sous forme json
-    configFile uuid CHECK(fk_check(name || '.BinaryFile', configFile))-- can be null
+    configFile    uuid CHECK (fk_check(name || '.BinaryFile', configFile))
 );
 
 CREATE INDEX application_referenceType_gin_idx ON application USING gin (referenceType);
@@ -102,41 +111,46 @@ CREATE ROLE "applicationCreator";
 
 GRANT INSERT, UPDATE ON Application TO "applicationCreator";
 
-GRANT SELECT, UPDATE, DELETE, REFERENCES ON Application TO public;
+GRANT SELECT  ON Application  TO public ;
 
-ALTER TABLE Application ENABLE ROW LEVEL SECURITY;
+GRANT SELECT , UPDATE , DELETE ON OreSiUser TO "superadmin", "applicationCreator";
 
-CREATE POLICY "applicationCreator_Application_insert" ON Application AS PERMISSIVE
-            FOR INSERT TO "applicationCreator"
-            WITH CHECK ( true );
+GRANT SELECT, UPDATE, DELETE, REFERENCES ON Application TO "applicationCreator",superadmin;
+
+ALTER TABLE Application
+    ENABLE ROW LEVEL SECURITY;
+CREATE POLICY "superadmin_Application_insert"
+    ON Application AS PERMISSIVE
+    TO superadmin
+    using (true)
+    with check (true);
 
-CREATE POLICY "applicationCreator_Application_select" ON Application AS PERMISSIVE
-            FOR SELECT TO "applicationCreator"
-            USING ( true );
 
 CREATE AGGREGATE jsonb_object_agg(jsonb) (SFUNC = 'jsonb_concat', STYPE = jsonb, INITCOND = '{}');
 CREATE AGGREGATE aggregate_by_array_concatenation(anyarray) (SFUNC = 'array_cat', STYPE = anyarray, INITCOND = '{}');
 
-create type COMPOSITE_DATE as (
-  datetimestamp           "timestamp",
-  formattedDate           "varchar"
-) ;
+create type COMPOSITE_DATE as
+(
+    datetimestamp "timestamp",
+    formattedDate "varchar"
+);
 CREATE FUNCTION castTextToCompositeDate(Text) RETURNS COMPOSITE_DATE AS
- 'select
-        (substring($1 from 6 for 19)::timestamp,
+'select (substring($1 from 6 for 19)::timestamp,
          substring($1 from 26))::COMPOSITE_DATE;'
     LANGUAGE SQL
     IMMUTABLE
     RETURNS NULL ON NULL INPUT;
 CREATE CAST (TEXT AS COMPOSITE_DATE) WITH FUNCTION castTextToCompositeDate(Text) AS ASSIGNMENT;
 CREATE FUNCTION castCompositeDateToTimestamp(COMPOSITE_DATE) RETURNS TIMESTAMP
-AS 'select ($1).datetimestamp;'
+AS
+'select ($1).datetimestamp;'
     LANGUAGE SQL
     IMMUTABLE
     RETURNS NULL ON NULL INPUT;
 CREATE CAST (COMPOSITE_DATE AS TIMESTAMP) WITH FUNCTION castCompositeDateToTimestamp(COMPOSITE_DATE) AS ASSIGNMENT;
 CREATE FUNCTION castCompositeDateToFormattedDate(COMPOSITE_DATE) RETURNS Text
-AS 'select ($1).formattedDate;'
+AS
+'select ($1).formattedDate;'
     LANGUAGE SQL
     IMMUTABLE
     RETURNS NULL ON NULL INPUT;
diff --git a/src/test/java/fr/inra/oresing/rest/AuthorizationResourcesTest.java b/src/test/java/fr/inra/oresing/rest/AuthorizationResourcesTest.java
index 8f6eb12e09747ebf8a6248d8be5df138c311dfea..971c5ad5b1689f17934fe6eb27ef53b0c64b4f25 100644
--- a/src/test/java/fr/inra/oresing/rest/AuthorizationResourcesTest.java
+++ b/src/test/java/fr/inra/oresing/rest/AuthorizationResourcesTest.java
@@ -5,6 +5,9 @@ import fr.inra.oresing.OreSiNg;
 import fr.inra.oresing.persistence.AuthenticationService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.assertj.core.util.Strings;
+import org.hamcrest.Matchers;
+import org.hamcrest.core.IsEqual;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -14,15 +17,19 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.http.MediaType;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.TestExecutionListeners;
 import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit4.SpringRunner;
 import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
 import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.servlet.http.Cookie;
+import java.util.Map;
 
 import static org.hamcrest.Matchers.*;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -45,31 +52,35 @@ public class AuthorizationResourcesTest {
     @Autowired
     private AuthenticationService authenticationService;
 
+
+    @Autowired
+    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+
     @Autowired
     private Fixtures fixtures;
 
     @Test
     public void testAddAuthorization() throws Exception {
         Cookie authCookie = fixtures.addApplicationAcbb();
-        CreateUserResult createUserResult = authenticationService.createUser("UnReader" , "xxxxxxxx");
+        CreateUserResult createUserResult = authenticationService.createUser("UnReader", "xxxxxxxx");
         String readerUserId = createUserResult.getUserId().toString();
         Cookie authReaderCookie = mockMvc.perform(post("/api/v1/login")
-                        .param("login" , "UnReader")
-                        .param("password" , "xxxxxxxx"))
+                        .param("login", "UnReader")
+                        .param("password", "xxxxxxxx"))
                 .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
 
         {
             String response = mockMvc.perform(get("/api/v1/applications")
                     .cookie(authCookie)
             ).andReturn().getResponse().getContentAsString();
-            Assert.assertTrue("Le créateur de l'application doit pouvoir la retrouver dans la liste" , response.contains("acbb"));
+            Assert.assertTrue("Le créateur de l'application doit pouvoir la retrouver dans la liste", response.contains("acbb"));
         }
 
         {
             String response = mockMvc.perform(get("/api/v1/applications")
                     .cookie(authReaderCookie)
             ).andReturn().getResponse().getContentAsString();
-            Assert.assertFalse("On ne devrait pas voir l'application car les droits n'ont pas encore été accordés" , response.contains("acbb"));
+            Assert.assertFalse("On ne devrait pas voir l'application car les droits n'ont pas encore été accordés", response.contains("acbb"));
         }
 
         {
@@ -89,7 +100,7 @@ public class AuthorizationResourcesTest {
 
         {
             String json = "{\n" +
-                    "   \"usersId\":[\""+readerUserId+"\"],\n" +
+                    "   \"usersId\":[\"" + readerUserId + "\"],\n" +
                     "   \"applicationNameOrId\":\"acbb\",\n" +
                     "   \"id\": null,\n" +
                     "   \"name\": \"une authorization sur acbb\",\n" +
@@ -134,7 +145,7 @@ public class AuthorizationResourcesTest {
             String response = mockMvc.perform(get("/api/v1/applications")
                     .cookie(authReaderCookie)
             ).andReturn().getResponse().getContentAsString();
-            Assert.assertTrue("Une fois l'accès donné, on doit pouvoir avec l'application dans la liste" , response.contains("acbb"));
+            Assert.assertTrue("Une fois l'accès donné, on doit pouvoir avec l'application dans la liste", response.contains("acbb"));
         }
 
         {
@@ -153,14 +164,13 @@ public class AuthorizationResourcesTest {
 
     @Test
     public void testAddAuthorizationOnTwoScopes() throws Exception {
-
         Cookie authCookie = fixtures.addApplicationHauteFrequence();
 
-        CreateUserResult createUserResult = authenticationService.createUser("UnReader" , "xxxxxxxx");
+        CreateUserResult createUserResult = authenticationService.createUser("UnReader", "xxxxxxxx");
         String readerUserId = createUserResult.getUserId().toString();
         Cookie authReaderCookie = mockMvc.perform(post("/api/v1/login")
-                        .param("login" , "UnReader")
-                        .param("password" , "xxxxxxxx"))
+                        .param("login", "UnReader")
+                        .param("password", "xxxxxxxx"))
                 .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
 
         String authorizationId;
@@ -168,7 +178,7 @@ public class AuthorizationResourcesTest {
         {
 
             String json = "{\n" +
-                    "   \"usersId\":[\""+readerUserId+"\"],\n" +
+                    "   \"usersId\":[\"" + readerUserId + "\"],\n" +
                     "   \"applicationNameOrId\":\"hautefrequence\",\n" +
                     "   \"id\": null,\n" +
                     "   \"name\": \"une authorization sur haute fréquence\",\n" +
@@ -214,8 +224,7 @@ public class AuthorizationResourcesTest {
 
         {
             String json = mockMvc.perform(get("/api/v1/applications/hautefrequence/dataType/hautefrequence/authorization/" + authorizationId)
-                            .cookie(authCookie)
-                            .accept(MediaType.APPLICATION_JSON))
+                            .cookie(authCookie))
                     .andExpect(status().isOk())
                     .andReturn().getResponse().getContentAsString();
 
@@ -235,7 +244,7 @@ public class AuthorizationResourcesTest {
                     .andExpect(jsonPath("$.rows[*].values.localization.projet").value(not(hasItemInArray(equalTo("rnt"))), String[].class))
                     .andExpect(jsonPath("$.rows[*].values.date.day").value(hasItemInArray(equalTo("date:2016-06-14T00:00:00:14/06/2016")), String[].class))
                     .andExpect(jsonPath("$.rows[*].values.date.day").value(not(hasItemInArray(equalTo("date:2017-01-30T00:00:00:30/01/2017"))), String[].class))
-                    .andExpect(jsonPath("$.totalRows" , equalTo(7456)))
+                    .andExpect(jsonPath("$.totalRows", equalTo(7456)))
                     .andReturn().getResponse().getContentAsString();
 
 
@@ -257,8 +266,105 @@ public class AuthorizationResourcesTest {
                             .cookie(authReaderCookie)
                             .accept(MediaType.APPLICATION_JSON))
                     .andExpect(status().isOk())
-                    .andExpect(jsonPath("$.totalRows" , equalTo(-1)))
+                    .andExpect(jsonPath("$.totalRows", equalTo(-1)))
                     .andReturn().getResponse().getContentAsString();
         }
     }
+
+    @Test
+    public void testAddApplicationMonsoere() throws Exception {
+        fixtures.addMonsoreApplication();
+    }
+
+    @Test
+    public void testAddRightForAddApplication() throws Exception {
+
+        {
+            final String TEST = "test";
+            CreateUserResult dbUserResult = authenticationService.createUser(TEST, TEST);
+            final Cookie dbUserCookies = mockMvc.perform(post("/api/v1/login")
+                            .param("login", TEST)
+                            .param("password", TEST))
+                    .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
+            addRoleAdmin(dbUserResult);
+            String applicationCreatorLogin = "applicationCreator";
+            String applicationCreatorPassword = "xxxxxxxx";
+            CreateUserResult applicationCreatorResult = authenticationService.createUser(applicationCreatorLogin, applicationCreatorPassword);
+            final Cookie applicationCreatorCookies = mockMvc.perform(post("/api/v1/login")
+                            .param("login", applicationCreatorLogin)
+                            .param("password", applicationCreatorPassword))
+                    .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
+            String lambdaLogin = "lambda";
+            String lambdaPassword = "xxxxxxxx";
+            CreateUserResult lambdaResult = authenticationService.createUser(lambdaLogin, lambdaPassword);
+            final Cookie lambdaCookie = mockMvc.perform(post("/api/v1/login")
+                            .param("login", lambdaLogin)
+                            .param("password", lambdaPassword))
+                    .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
+
+            {
+                //l'administrateur peut créer des applications.
+                final String monsoreResult = fixtures.createApplicationMonSore(dbUserCookies, "monsore");
+                Assert.assertFalse(Strings.isNullOrEmpty(JsonPath.parse(monsoreResult).read("$.id", String.class)));
+            }
+            {
+                // on donne les droits pour un pattern acbb
+
+                ResultActions resultActions = mockMvc.perform(put("/api/v1/authorization/applicationCreator")
+                                .param("userId", applicationCreatorResult.getUserId().toString())
+                                .param("applicationPattern", "acbb")
+                                .cookie(dbUserCookies))
+                        .andExpect(status().is2xxSuccessful())
+                        .andExpect(jsonPath("$.roles.currentUser", IsEqual.equalTo(applicationCreatorResult.getUserId().toString())))
+                        .andExpect(jsonPath("$.roles.memberOf", Matchers.hasItem("applicationCreator")))
+                        .andExpect(jsonPath("$.authorizations", Matchers.hasItem("acbb")))
+                        .andExpect(jsonPath("$.id", IsEqual.equalTo(applicationCreatorResult.getUserId().toString())));
+
+                //on peut déposer acbb
+                final String acbbResult = fixtures.createApplicationMonSore(applicationCreatorCookies, "acbb");
+                Assert.assertFalse(Strings.isNullOrEmpty(JsonPath.parse(acbbResult).read("$.id", String.class)));
+                //on ne peut déposer monsore
+                Assert.assertEquals("NO_RIGHT_FOR_APPLICATION_CREATION", fixtures.createApplicationMonSore(applicationCreatorCookies, "monsore"));
+
+            }
+            {
+                //on donne des droits pour le pattern monsore
+                ResultActions resultActions = mockMvc.perform(put("/api/v1/authorization/applicationCreator")
+                                .param("userId", applicationCreatorResult.getUserId().toString())
+                                .param("applicationPattern", "monsore")
+                                .cookie(dbUserCookies))
+                        .andExpect(status().is2xxSuccessful())
+                        .andExpect(jsonPath("$.roles.currentUser", IsEqual.equalTo(applicationCreatorResult.getUserId().toString())))
+                        .andExpect(jsonPath("$.roles.memberOf", Matchers.hasItem("applicationCreator")))
+                        .andExpect(jsonPath("$.authorizations", Matchers.hasItem("monsore")))
+                        .andExpect(jsonPath("$.id", IsEqual.equalTo(applicationCreatorResult.getUserId().toString())));
+
+                //on peut déposer monsore
+                final String acbbResult = fixtures.createApplicationMonSore(applicationCreatorCookies, "acbb");
+                Assert.assertFalse(Strings.isNullOrEmpty(JsonPath.parse(acbbResult).read("$.id", String.class)));
+
+            }
+            {
+                //on supprime des droits pour le pattern monsore
+                ResultActions resultActions = mockMvc.perform(delete("/api/v1/authorization/applicationCreator")
+                                .param("userId", applicationCreatorResult.getUserId().toString())
+                                .param("applicationPattern", "monsore")
+                                .cookie(dbUserCookies))
+                        .andExpect(status().is2xxSuccessful())
+                        .andExpect(jsonPath("$.roles.currentUser", IsEqual.equalTo(applicationCreatorResult.getUserId().toString())))
+                        .andExpect(jsonPath("$.roles.memberOf", not(Matchers.hasItem("applicationCreator"))))
+                        .andExpect(jsonPath("$.authorizations", not(Matchers.hasItem("monsore"))))
+                        .andExpect(jsonPath("$.id", IsEqual.equalTo(applicationCreatorResult.getUserId().toString())));
+
+                //on ne peut déposer monsore
+                Assert.assertEquals("NO_RIGHT_FOR_APPLICATION_CREATION", fixtures.createApplicationMonSore(applicationCreatorCookies, "monsore"));
+            }
+        }
+
+    }
+
+    @Transactional
+    void addRoleAdmin(CreateUserResult dbUserResult) {
+        namedParameterJdbcTemplate.update("grant \"superadmin\" to \"" + dbUserResult.getUserId().toString() + "\"", Map.of());
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/fr/inra/oresing/rest/Fixtures.java b/src/test/java/fr/inra/oresing/rest/Fixtures.java
index b2dfa7a657c201a2062b90ed7e2772a21c855753..6e112612acd40f4afcae62eaaa31fe79633cadb9 100644
--- a/src/test/java/fr/inra/oresing/rest/Fixtures.java
+++ b/src/test/java/fr/inra/oresing/rest/Fixtures.java
@@ -5,14 +5,24 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.io.Resources;
 import fr.inra.oresing.OreSiTechnicalException;
+import fr.inra.oresing.model.OreSiUser;
 import fr.inra.oresing.persistence.AuthenticationService;
+import fr.inra.oresing.persistence.UserRepository;
 import org.apache.commons.io.IOUtils;
+import org.hamcrest.Matchers;
+import org.hamcrest.core.IsEqual;
+import org.junit.Assert;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.stereotype.Component;
 import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
 import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.util.NestedServletException;
 
 import javax.servlet.http.Cookie;
 import java.io.IOException;
@@ -24,11 +34,14 @@ import java.time.temporal.ChronoUnit;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.UUID;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 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.jsonPath;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 @Component
@@ -39,7 +52,11 @@ public class Fixtures {
 
     @Autowired
     private AuthenticationService authenticationService;
+    @Autowired
+    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
 
+    @Autowired
+    private UserRepository userRepository;
     private Cookie cookie;
 
     public String getMonsoreApplicationName() {
@@ -82,12 +99,12 @@ public class Fixtures {
         //fougeres-fou_4_swc_j_01-01-1999_31-01-1999.csv
         final Pattern pattern = Pattern.compile("(.*)_" + datatype + "_(.*)_(.*).csv");
         final Matcher matcher = pattern.matcher(fileName);
-        if(!matcher.matches()){
+        if (!matcher.matches()) {
             return null;
         }
         String zone_etude = matcher.group(1);
         final String[] parent_site = zone_etude.split("-");
-        if(parent_site.length>1){
+        if (parent_site.length > 1) {
             zone_etude = String.format("%1$s.%1$s__%2$s", parent_site[0], parent_site[1]);
         }
         final DateTimeFormatter formaterIn = DateTimeFormatter.ofPattern("dd-MM-yyyy");
@@ -95,8 +112,8 @@ public class Fixtures {
 
         final boolean isMonthly = datatype.matches(".*_m");
         final String format = (isMonthly ? "01-" : "") + "%s";
-        String dateDebut =formaterOut.format(LocalDate.parse(String.format(format, matcher.group(2)), formaterIn).atStartOfDay(ZoneOffset.UTC))+" 00:00:00";
-        String dateFin =formaterOut.format(LocalDate.parse(String.format(format, matcher.group(3)), formaterIn).atTime(0,0).plus(1, isMonthly ? ChronoUnit.MONTHS:ChronoUnit.DAYS))+" 00:00:00";
+        String dateDebut = formaterOut.format(LocalDate.parse(String.format(format, matcher.group(2)), formaterIn).atStartOfDay(ZoneOffset.UTC)) + " 00:00:00";
+        String dateFin = formaterOut.format(LocalDate.parse(String.format(format, matcher.group(3)), formaterIn).atTime(0, 0).plus(1, isMonthly ? ChronoUnit.MONTHS : ChronoUnit.DAYS)) + " 00:00:00";
         return String.format("{\n" +
                 "   \"fileid\":null,\n" +
                 "   \"binaryfiledataset\":{\n" +
@@ -249,12 +266,12 @@ public class Fixtures {
         return "/data/migration/couleurs.csv";
     }
 
-    private Cookie addApplicationCreatorUser() throws Exception {
+    public Cookie addSuperAdmin(String applicationPattern) throws Exception {
         if (cookie == null) {
             String aPassword = "xxxxxxxx";
-            String aLogin = "poussin";
+            String aLogin = "superAdmin";
             CreateUserResult createUserResult = authenticationService.createUser(aLogin, aPassword);
-            authenticationService.addUserRightCreateApplication(createUserResult.getUserId());
+            authenticationService.addUserRightCreateApplication(createUserResult.getUserId(), applicationPattern);
             cookie = mockMvc.perform(post("/api/v1/login")
                             .param("login", aLogin)
                             .param("password", aPassword))
@@ -263,15 +280,68 @@ public class Fixtures {
         return cookie;
     }
 
-    public Cookie addMonsoreApplication() throws Exception {
-        Cookie authCookie = addApplicationCreatorUser();
+    @Transactional
+    void addRoleAdmin(CreateUserResult dbUserResult) {
+        namedParameterJdbcTemplate.update("grant \"superadmin\" to \"" + dbUserResult.getUserId().toString() + "\"", Map.of());
+    }
+
+    public Cookie addApplicationCreatorUser(String applicationPattern) throws Exception {
+        if (cookie == null) {
+            String aPassword = "xxxxxxxx";
+            String aLogin = "poussin";
+            CreateUserResult createUserResult = authenticationService.createUser(aLogin, aPassword);
+            addRoleAdmin(createUserResult);
+            final MockHttpServletResponse response = mockMvc.perform(post("/api/v1/login")
+                            .param("login", aLogin)
+                            .param("password", aPassword))
+                    .andReturn().getResponse();
+            cookie = response.getCookie(AuthHelper.JWT_COOKIE_NAME);
+        }
+        String aPassword = "xxxxxxxx";
+        String aLogin = applicationPattern;
+        CreateUserResult createUserResult = authenticationService.createUser(aLogin, aPassword);
+        final UUID userId = createUserResult.getUserId();
+        ResultActions resultActions = mockMvc.perform(put("/api/v1/authorization/applicationCreator")
+                        .param("userId", userId.toString())
+                        .param("applicationPattern", applicationPattern)
+                        .cookie(cookie))
+                .andExpect(status().is2xxSuccessful())
+                .andExpect(jsonPath("$.roles.currentUser", IsEqual.equalTo(userId.toString())))
+                .andExpect(jsonPath("$.roles.memberOf", Matchers.hasItem("applicationCreator")))
+                .andExpect(jsonPath("$.authorizations", Matchers.hasItem(applicationPattern)))
+                .andExpect(jsonPath("$.id", IsEqual.equalTo(userId.toString())));
+        final OreSiUser user = userRepository.findById(userId);
+        Assert.assertTrue(user.getAuthorizations().contains(applicationPattern));
+        Cookie applicationCreator = mockMvc.perform(post("/api/v1/login")
+                        .param("login", aLogin)
+                        .param("password", aPassword))
+                .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
+        return applicationCreator;
+    }
+
+    public String createApplicationMonSore(Cookie authCookie, String applicationName) throws Exception {
+        ResultActions resultActions = null;
         try (InputStream configurationFile = getClass().getResourceAsStream(getMonsoreApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "monsore.yaml", "text/plain", configurationFile);
-            mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore")
-                            .file(configuration)
-                            .cookie(authCookie))
-                    .andExpect(MockMvcResultMatchers.status().isCreated());
+            resultActions = mockMvc.perform(MockMvcRequestBuilders.multipart(String.format("/api/v1/applications/%s", applicationName == null ? "monsore" : applicationName))
+                    .file(configuration)
+                    .cookie(authCookie));
+            return resultActions.andExpect(MockMvcResultMatchers.status().isCreated())
+                    .andReturn()
+                    .getResponse().getContentAsString();
+        } catch (NestedServletException e) {
+            if (e.getCause() instanceof NotApplicationCreatorRightsException) {
+                throw (NotApplicationCreatorRightsException) e.getCause();
+            }
+            throw e;
+        } catch (AssertionError e) {
+            return resultActions.andReturn().getResolvedException().getMessage();
         }
+    }
+
+    public Cookie addMonsoreApplication() throws Exception {
+        Cookie authCookie = addApplicationCreatorUser("monsore");
+        String result = createApplicationMonSore(authCookie, "monsore");
 
         // Ajout de referentiel
         for (Map.Entry<String, String> e : getMonsoreReferentielFiles().entrySet()) {
@@ -296,7 +366,7 @@ public class Fixtures {
     }
 
     public Cookie addMigrationApplication() throws Exception {
-        Cookie authCookie = addApplicationCreatorUser();
+        Cookie authCookie = addApplicationCreatorUser("fakeapp");
         try (InputStream configurationFile = getClass().getResourceAsStream(getMigrationApplicationConfigurationResourceName(1))) {
             MockMultipartFile configuration = new MockMultipartFile("file", "fake-app.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/fakeapp")
@@ -327,7 +397,7 @@ public class Fixtures {
     }
 
     public Cookie addApplicationAcbb() throws Exception {
-        Cookie authCookie = addApplicationCreatorUser();
+        Cookie authCookie = addApplicationCreatorUser("acbb");
         try (InputStream configurationFile = getClass().getResourceAsStream(getAcbbApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "acbb.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/acbb")
@@ -399,7 +469,7 @@ public class Fixtures {
     }
 
     public Cookie addApplicationHauteFrequence() throws Exception {
-        Cookie authCookie = addApplicationCreatorUser();
+        Cookie authCookie = addApplicationCreatorUser("hautefrequence");
         try (InputStream configurationFile = getClass().getResourceAsStream(getHauteFrequenceApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "hautefrequence.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/hautefrequence")
@@ -468,7 +538,7 @@ public class Fixtures {
     }
 
     public Cookie addApplicationOLAC() throws Exception {
-        Cookie authCookie = addApplicationCreatorUser();
+        Cookie authCookie = addApplicationCreatorUser("olac");
         try (InputStream configurationFile = getClass().getResourceAsStream(getOlaApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "olac.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/olac")
@@ -629,7 +699,7 @@ public class Fixtures {
     }
 
     public Cookie addApplicationFORET() throws Exception {
-        Cookie authCookie = addApplicationCreatorUser();
+        Cookie authCookie = addApplicationCreatorUser("foret");
         try (InputStream configurationFile = getClass().getResourceAsStream(getForetApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "foret.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/foret")
@@ -700,7 +770,7 @@ public class Fixtures {
     }
 
     public void addApplicationRecursivity() throws Exception {
-        Cookie authCookie = addApplicationCreatorUser();
+        Cookie authCookie = addApplicationCreatorUser("recursivite");
         try (InputStream in = getClass().getResourceAsStream(getRecursivityApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "recursivity.yaml", "text/plain", in);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/recursivite")
diff --git a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
index a52761084da178b0301b97ea355dd30a804d979f..a9abeb742d79e7a6a58c3c2adfae53724861ff41 100644
--- a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
+++ b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
@@ -10,6 +10,7 @@ import fr.inra.oresing.ValidationLevel;
 import fr.inra.oresing.checker.InvalidDatasetContentException;
 import fr.inra.oresing.persistence.AuthenticationService;
 import fr.inra.oresing.persistence.JsonRowMapper;
+import fr.inra.oresing.persistence.UserRepository;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -31,6 +32,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.http.MediaType;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.TestExecutionListeners;
@@ -42,6 +44,7 @@ import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
 import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
 import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.util.NestedServletException;
 
 import javax.servlet.http.Cookie;
@@ -54,9 +57,9 @@ import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static org.hamcrest.Matchers.*;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItemInArray;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 @RunWith(SpringRunner.class)
@@ -88,14 +91,27 @@ public class OreSiResourcesTest {
     private UUID userId;
     private CreateUserResult lambdaUser;
 
+    @Autowired
+    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+    @Autowired
+    private UserRepository userRepository;
+
+
     @Before
     public void createUser() throws Exception {
-        userId = authenticationService.createUser("poussin", "xxxxxxxx").getUserId();
+        final CreateUserResult authUser = authenticationService.createUser("poussin", "xxxxxxxx");
+        userId = authUser.getUserId();
         lambdaUser = authenticationService.createUser("lambda", "xxxxxxxx");
         authCookie = mockMvc.perform(post("/api/v1/login")
                         .param("login", "poussin")
                         .param("password", "xxxxxxxx"))
                 .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
+        addRoleAdmin(authUser);
+    }
+
+    @Transactional
+    void addRoleAdmin(CreateUserResult dbUserResult) {
+        namedParameterJdbcTemplate.update("grant \"superadmin\" to \"" + dbUserResult.getUserId().toString() + "\"", Map.of());
     }
 
     @Test
@@ -103,21 +119,31 @@ public class OreSiResourcesTest {
     public void addApplicationMonsore() throws Exception {
         String appId;
 
+        final CreateUserResult monsoereUser = authenticationService.createUser("monsore", "xxxxxxxx");
+        UUID monsoreUserId = monsoereUser.getUserId();
+        Cookie monsoreCookie = mockMvc.perform(post("/api/v1/login")
+                        .param("login", "monsore")
+                        .param("password", "xxxxxxxx"))
+                .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
+
         URL resource = getClass().getResource(fixtures.getMonsoreApplicationConfigurationResourceName());
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "monsore.yaml", "text/plain", in);
 
             // on n'a pas le droit de creer de nouvelle application
-            mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore")
-                            .file(configuration)
-                            .cookie(authCookie))
-                    .andExpect(status().is4xxClientError());
-            authenticationService.addUserRightCreateApplication(userId);
+                final NotApplicationCreatorRightsException resolvedException = (NotApplicationCreatorRightsException) mockMvc.perform(multipart("/api/v1/applications/monsore")
+                                .file(configuration)
+                                .cookie(monsoreCookie))
+                        .andExpect(status().is4xxClientError())
+                        .andReturn().getResolvedException();
+                addUserRightCreateApplication(monsoreUserId, "monsore");
+            Assert.assertEquals("monsore", resolvedException.applicationName);
+            addUserRightCreateApplication(monsoreUserId, "monsore");
 
             String response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore")
                             .file(configuration)
                             .param("comment", "commentaire")
-                            .cookie(authCookie))
+                            .cookie(monsoreCookie))
                     .andExpect(status().isCreated())
                     .andExpect(jsonPath("$.id", IsNull.notNullValue()))
                     .andReturn().getResponse().getContentAsString();
@@ -127,7 +153,7 @@ public class OreSiResourcesTest {
 
         String response = mockMvc.perform(get("/api/v1/applications/{appId}", appId)
                         .contentType(MediaType.APPLICATION_JSON)
-                        .cookie(authCookie))
+                        .cookie(monsoreCookie))
                 .andExpect(status().isOk())
                 .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
                 // id
@@ -148,7 +174,7 @@ public class OreSiResourcesTest {
 
                 response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore/references/{refType}", e.getKey())
                                 .file(refFile)
-                                .cookie(authCookie))
+                                .cookie(monsoreCookie))
                         .andExpect(status().isCreated())
                         .andExpect(jsonPath("$.id", IsNull.notNullValue()))
                         .andReturn().getResponse().getContentAsString();
@@ -158,13 +184,13 @@ public class OreSiResourcesTest {
         }
         mockMvc.perform(get("/api/v1/applications/{appId}", appId)
                         .contentType(MediaType.APPLICATION_JSON)
-                        .cookie(authCookie))
+                        .cookie(monsoreCookie))
                 .andExpect(status().isOk())
                 .andExpect(jsonPath("$.referenceSynthesis[ ?(@.referenceType=='valeurs_qualitatives')].lineCount", IsEqual.equalTo(List.of(3))));
 
         String getReferencesResponse = mockMvc.perform(get("/api/v1/applications/monsore/references/sites")
                         .contentType(MediaType.APPLICATION_JSON)
-                        .cookie(authCookie))
+                        .cookie(monsoreCookie))
                 .andExpect(status().isOk())
                 .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
                 .andReturn().getResponse().getContentAsString();
@@ -179,7 +205,7 @@ public class OreSiResourcesTest {
 
             response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore/data/pem")
                             .file(refFile)
-                            .cookie(authCookie))
+                            .cookie(monsoreCookie))
                     .andExpect(status().is2xxSuccessful())
                     .andReturn().getResponse().getContentAsString();
 
@@ -193,7 +219,7 @@ public class OreSiResourcesTest {
             MockMultipartFile refFile = new MockMultipartFile("file", "data-pem.csv", "text/plain", bytes);
             response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore/data/pem")
                             .file(refFile)
-                            .cookie(authCookie))
+                            .cookie(monsoreCookie))
                     .andExpect(status().isBadRequest())
                     .andReturn().getResponse().getContentAsString();
             log.debug(StringUtils.abbreviate(response, 50));
@@ -203,7 +229,7 @@ public class OreSiResourcesTest {
 
         // list des types de data
         response = mockMvc.perform(get("/api/v1/applications/monsore/data")
-                        .cookie(authCookie))
+                        .cookie(monsoreCookie))
                 .andExpect(status().isOk())
                 .andReturn().getResponse().getContentAsString();
 
@@ -232,7 +258,7 @@ public class OreSiResourcesTest {
             }
 
             String actualJson = mockMvc.perform(get("/api/v1/applications/monsore/data/pem")
-                            .cookie(authCookie)
+                            .cookie(monsoreCookie)
                             .accept(MediaType.APPLICATION_JSON))
                     .andExpect(status().isOk())
                     .andExpect(jsonPath("$.variables").isArray())
@@ -266,7 +292,7 @@ public class OreSiResourcesTest {
             String filter = "{\"application\":null,\"applicationNameOrId\":null,\"dataType\":null,\"offset\":null,\"limit\":15,\"variableComponentSelects\":[],\"variableComponentFilters\":[{\"variableComponentKey\":{\"variable\":\"date\",\"component\":\"value\"},\"filter\":null,\"type\":\"date\",\"format\":\"dd/MM/yyyy\",\"intervalValues\":{\"from\":\"1984-01-01\",\"to\":\"1984-01-01\"}},{\"variableComponentKey\":{\"variable\":\"Nombre d'individus\",\"component\":\"value\"},\"filter\":null,\"type\":\"numeric\",\"format\":\"integer\",\"intervalValues\":{\"from\":\"20\",\"to\":\"29\"}},{\"variableComponentKey\":{\"variable\":\"Couleur des individus\",\"component\":\"value\"},\"filter\":\"vert\",\"type\":\"reference\",\"format\":\"uuid\",\"intervalValues\":null}],\"variableComponentOrderBy\":[{\"variableComponentKey\":{\"variable\":\"site\",\"component\":\"plateforme\"},\"order\":\"ASC\",\"type\":null,\"format\":null}]}";
             Resources.toString(Objects.requireNonNull(getClass().getResource("/data/monsore/compare/export.json")), Charsets.UTF_8);
             String actualJson = mockMvc.perform(get("/api/v1/applications/monsore/data/pem")
-                            .cookie(authCookie)
+                            .cookie(monsoreCookie)
                             .param("downloadDatasetQuery", filter)
                             .accept(MediaType.APPLICATION_JSON))
                     .andExpect(status().isOk())
@@ -284,7 +310,7 @@ public class OreSiResourcesTest {
         {
             String expectedCsv = Resources.toString(Objects.requireNonNull(getClass().getResource("/data/monsore/compare/export.csv")), Charsets.UTF_8);
             String actualCsv = mockMvc.perform(get("/api/v1/applications/monsore/data/pem")
-                            .cookie(authCookie)
+                            .cookie(monsoreCookie)
                             .accept(MediaType.TEXT_PLAIN))
                     .andExpect(status().isOk())
                     //     .andExpect(content().string(expectedCsv))
@@ -308,7 +334,7 @@ public class OreSiResourcesTest {
             MockMultipartFile refFile = new MockMultipartFile("file", "data-pem.csv", "text/plain", invalidCsv.getBytes(StandardCharsets.UTF_8));
             response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore/data/pem")
                             .file(refFile)
-                            .cookie(authCookie))
+                            .cookie(monsoreCookie))
                     .andExpect(status().is4xxClientError())
                     .andReturn().getResponse().getContentAsString();
             log.debug(StringUtils.abbreviate(response, 50));
@@ -408,7 +434,7 @@ public class OreSiResourcesTest {
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "monsore.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "monsore");
 
             String response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/monsore")
                             .file(configuration)
@@ -597,12 +623,12 @@ public class OreSiResourcesTest {
      */
     @Test
     public void testProgressiveYamlWithoutAuthorization() throws Exception {
-
+        String authorizationId;
         URL resource = getClass().getResource(fixtures.getProgressiveYaml().get("yamlWithoutAuthorization"));
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "progressive.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "progressive");
 
             String result = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/progressive")
                             .file(configuration)
@@ -614,7 +640,7 @@ public class OreSiResourcesTest {
         progressiveYamlAddData();
 
         String lambdaUserId = lambdaUser.getUserId().toString();
-        Cookie authReaderCookie = mockMvc.perform(post("/api/v1/login")
+        Cookie readerCookies = mockMvc.perform(post("/api/v1/login")
                         .param("login", "lambda")
                         .param("password", "xxxxxxxx"))
                 .andReturn().getResponse().getCookie(AuthHelper.JWT_COOKIE_NAME);
@@ -622,14 +648,14 @@ public class OreSiResourcesTest {
 
         {
             String response = mockMvc.perform(get("/api/v1/applications")
-                    .cookie(authReaderCookie)
+                    .cookie(readerCookies)
             ).andReturn().getResponse().getContentAsString();
             Assert.assertFalse("On ne devrait pas voir l'application car les droits n'ont pas encore été accordés", response.contains("progressive"));
         }
 
         {
             mockMvc.perform(get("/api/v1/applications/progressive/data/date_de_visite")
-                            .cookie(authReaderCookie)
+                            .cookie(readerCookies)
                             .accept(MediaType.TEXT_PLAIN))
                     .andExpect(status().is4xxClientError());
         }
@@ -666,31 +692,59 @@ public class OreSiResourcesTest {
                     "}\n" +
                     "}";
 
+            // L'utilisateur sans droit ne peut voir les applications
+            String response = mockMvc.perform(get("/api/v1/applications")
+                            .cookie(readerCookies)
+                    )
+                    .andExpect(jsonPath("$[*].name", Matchers.hasSize(0)))
+                    .andReturn().getResponse().getContentAsString();
+
+
             MockHttpServletRequestBuilder create = post("/api/v1/applications/progressive/dataType/date_de_visite/authorization")
                     .contentType(MediaType.APPLICATION_JSON)
                     .cookie(authCookie)
                     .content(json);
-            String response = mockMvc.perform(create)
+            response = mockMvc.perform(create)
                     .andExpect(status().isCreated())
                     .andReturn().getResponse().getContentAsString();
+            authorizationId = JsonPath.parse(response).read("$.authorizationId", String.class);
             log.debug(StringUtils.abbreviate(response, 50));
         }
 
         {
+            // Une fois l'accès donné, on doit pouvoir avec l'application dans la liste"
             String response = mockMvc.perform(get("/api/v1/applications")
-                    .cookie(authReaderCookie)
-            ).andReturn().getResponse().getContentAsString();
-            Assert.assertTrue("Une fois l'accès donné, on doit pouvoir avec l'application dans la liste", response.contains("progressive"));
+                            .cookie(readerCookies)
+                    )
+                    .andExpect(jsonPath("$[*].name", Matchers.hasSize(1)))
+                    .andExpect(jsonPath("$[*].name", Matchers.contains("progressive")))
+                    .andReturn().getResponse().getContentAsString();
         }
 
         {
             String json = mockMvc.perform(get("/api/v1/applications/progressive/data/date_de_visite")
-                            .cookie(authReaderCookie)
+                            .cookie(readerCookies)
                             .accept(MediaType.APPLICATION_JSON))
                     .andExpect(status().isOk())
                     .andExpect(jsonPath("$.rows[*].values.relevant.numero").value(hasItemInArray(equalTo("125")), String[].class))
                     .andReturn().getResponse().getContentAsString();
         }
+            MockHttpServletRequestBuilder delete = delete(String.format("/api/v1/applications/progressive/dataType/date_de_visite/authorization/%s", authorizationId))
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .cookie(authCookie);
+             mockMvc.perform(delete)
+                    .andExpect(status().is2xxSuccessful())
+                    .andReturn().getResponse().getContentAsString();
+            // L'utilisateur sans droit ne peut voir les applications
+
+        //TODO
+
+            /*String response = mockMvc.perform(get("/api/v1/applications")
+                            .cookie(readerCookies)
+                    )
+                    .andExpect(jsonPath("$[*].name", Matchers.hasSize(0)))
+                    .andReturn().getResponse().getContentAsString();*/
+
 
     }
 
@@ -701,7 +755,7 @@ public class OreSiResourcesTest {
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "progressive.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "progressive");
 
             String result = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/progressive")
                             .file(configuration)
@@ -727,7 +781,7 @@ public class OreSiResourcesTest {
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "progressive.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "progressive");
 
             BadApplicationConfigurationException exception = (BadApplicationConfigurationException) mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/progressive")
                             .file(configuration)
@@ -753,7 +807,7 @@ public class OreSiResourcesTest {
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "progressive.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "progressive");
 
             final ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/progressive")
                             .file(configuration)
@@ -772,7 +826,7 @@ public class OreSiResourcesTest {
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "progressive.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "progressive");
 
             final ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/progressive")
                             .file(configuration)
@@ -796,7 +850,7 @@ public class OreSiResourcesTest {
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "progressive.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "progressive");
 
             String response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/progressive")
                             .file(configuration)
@@ -851,7 +905,7 @@ public class OreSiResourcesTest {
         try (InputStream in = Objects.requireNonNull(resource).openStream()) {
             MockMultipartFile configuration = new MockMultipartFile("file", "recursivity.yaml", "text/plain", in);
             //définition de l'application
-            authenticationService.addUserRightCreateApplication(userId);
+            addUserRightCreateApplication(userId, "recursivite");
 
             String response = mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/recursivite")
                             .file(configuration)
@@ -867,9 +921,9 @@ public class OreSiResourcesTest {
                             .cookie(authCookie))
                     .andExpect(status().is2xxSuccessful())
                     .andExpect(jsonPath("$.references.taxon.dynamicColumns['propriétés de taxons'].reference", IsEqual.equalTo("proprietes_taxon")))
-                   .andExpect(jsonPath("$.references.taxon.dynamicColumns['propriétés de taxons'].headerPrefix", IsEqual.equalTo("pt_")))
-                   .andExpect(jsonPath("$.internationalization.references.taxon.internationalizedDynamicColumns['propriétés de taxons'].en", IsEqual.equalTo("Properties of Taxa")))
-                     .andReturn().getResponse().getContentAsString();
+                    .andExpect(jsonPath("$.references.taxon.dynamicColumns['propriétés de taxons'].headerPrefix", IsEqual.equalTo("pt_")))
+                    .andExpect(jsonPath("$.internationalization.references.taxon.internationalizedDynamicColumns['propriétés de taxons'].en", IsEqual.equalTo("Properties of Taxa")))
+                    .andReturn().getResponse().getContentAsString();
 
         }
 
@@ -928,8 +982,7 @@ public class OreSiResourcesTest {
     @Test
     @Category(ACBB_TEST.class)
     public void addApplicationAcbb() throws Exception {
-        authenticationService.addUserRightCreateApplication(userId);
-
+        addUserRightCreateApplication(userId, "acbb");
         URL resource = getClass().getResource(fixtures.getAcbbApplicationConfigurationResourceName());
         assert resource != null;
         try (InputStream in = resource.openStream()) {
@@ -951,6 +1004,18 @@ public class OreSiResourcesTest {
         addDataSWC();
     }
 
+    private void addUserRightCreateApplication(UUID userId, String pattern) throws Exception {
+        ResultActions resultActions = mockMvc.perform(put("/api/v1/authorization/applicationCreator")
+                        .param("userId", userId.toString())
+                        .param("applicationPattern", pattern)
+                        .cookie(authCookie))
+                .andExpect(status().is2xxSuccessful())
+                .andExpect(jsonPath("$.roles.currentUser", IsEqual.equalTo(userId.toString())))
+                .andExpect(jsonPath("$.roles.memberOf", Matchers.hasItem("applicationCreator")))
+                .andExpect(jsonPath("$.authorizations", Matchers.hasItem(pattern)))
+                .andExpect(jsonPath("$.id", IsEqual.equalTo(userId.toString())));
+    }
+
     private void addDataSWC() throws Exception {
         try (InputStream in = fixtures.openSwcDataResourceName(true)) {
             MockMultipartFile file = new MockMultipartFile("file", "SWC.csv", "text/plain", in);
@@ -1106,7 +1171,7 @@ public class OreSiResourcesTest {
     @Test
     @Category(HAUTE_FREQUENCE_TEST.class)
     public void addApplicationHauteFrequence() throws Exception {
-        authenticationService.addUserRightCreateApplication(userId);
+        addUserRightCreateApplication(userId, "hautefrequence");
         try (InputStream configurationFile = fixtures.getClass().getResourceAsStream(fixtures.getHauteFrequenceApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "hautefrequence.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/hautefrequence")
@@ -1139,7 +1204,7 @@ public class OreSiResourcesTest {
     @Test
     @Category(OTHERS_TEST.class)
     public void addDuplicatedTest() throws Exception {
-        authenticationService.addUserRightCreateApplication(userId);
+        addUserRightCreateApplication(userId, "duplicated");
         try (InputStream configurationFile = fixtures.getClass().getResourceAsStream(fixtures.getDuplicatedApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "duplicated.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/duplicated")
@@ -1394,7 +1459,7 @@ on test le dépôt d'un fichier récursif
     @Test
     @Category(OTHERS_TEST.class)
     public void addApplicationOLAC() throws Exception {
-        authenticationService.addUserRightCreateApplication(userId);
+        addUserRightCreateApplication(userId, "olac");
         try (InputStream configurationFile = fixtures.getClass().getResourceAsStream(fixtures.getOlaApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "olac.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/olac")
@@ -1482,7 +1547,7 @@ on test le dépôt d'un fichier récursif
     @Test
     @Category(OTHERS_TEST.class)
     public void addApplicationFORET_essai() throws Exception {
-        authenticationService.addUserRightCreateApplication(userId);
+        addUserRightCreateApplication(userId, "foret");
         try (InputStream configurationFile = fixtures.getClass().getResourceAsStream(fixtures.getForetEssaiApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "foret_essai.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/foret")
@@ -1514,7 +1579,7 @@ on test le dépôt d'un fichier récursif
 
                 if (entry.getKey().equals("swc_j")) {
                     authenticationService.setRoleAdmin();
-                    final String responseForBuildSynthesis = mockMvc.perform(MockMvcRequestBuilders.put("/api/v1/applications/foret/synthesis/{refType}", entry.getKey())
+                    final String responseForBuildSynthesis = mockMvc.perform(put("/api/v1/applications/foret/synthesis/{refType}", entry.getKey())
                                     .cookie(authCookie))
                             .andExpect(jsonPath("$.SWC", Matchers.hasSize(8)))
                             .andReturn().getResponse().getContentAsString();
@@ -1531,7 +1596,7 @@ on test le dépôt d'un fichier récursif
     @Test
     @Category(OTHERS_TEST.class)
     public void addApplicationFORET() throws Exception {
-        authenticationService.addUserRightCreateApplication(userId);
+        addUserRightCreateApplication(userId, "foret");
         try (InputStream configurationFile = fixtures.getClass().getResourceAsStream(fixtures.getForetApplicationConfigurationResourceName())) {
             MockMultipartFile configuration = new MockMultipartFile("file", "foret.yaml", "text/plain", configurationFile);
             mockMvc.perform(MockMvcRequestBuilders.multipart("/api/v1/applications/foret")