diff --git a/frontend-js/src/main/js/ConfigurationType.js b/frontend-js/src/main/js/ConfigurationType.js
index 0b85d8d10838ecdd82477b315eab0bdf5957a6cd..abe4fdd441a31848a892b26060d5f68be0328628 100644
--- a/frontend-js/src/main/js/ConfigurationType.js
+++ b/frontend-js/src/main/js/ConfigurationType.js
@@ -13,6 +13,7 @@ var ConfigurationType = {
   SIMPLE_COLOR_VAL: "SIMPLE_COLOR_VAL",
   SEARCH_DISTANCE: "SEARCH_DISTANCE",
   SEARCH_RESULT_NUMBER: "SEARCH_RESULT_NUMBER",
+  TERMS_OF_USE: "TERMS_OF_USE",
   USER_MANUAL_FILE: "USER_MANUAL_FILE",
 };
 
diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js
index f75bd1ded45626424829e6e27898b810887ef691..5b9ab60c6253b2701f229f93a7ff860ad0d97faf 100644
--- a/frontend-js/src/main/js/ServerConnector.js
+++ b/frontend-js/src/main/js/ServerConnector.js
@@ -652,6 +652,17 @@ ServerConnector.getModels = function (projectId) {
     return models;
   });
 };
+
+/**
+ * TODO REMOVE when API v12 appears (this is just a workaround)
+ */
+ServerConnector.updateTermsOfUse = function (user, value) {
+  var self = this;
+  var url = ServerConnector.getUserUrl({login:user.getLogin()});
+  url += "/updateTermsOfUse?value=" + value;
+  return self.readFile(url);
+};
+
 ServerConnector.getProject = function (projectId) {
   var queryParams = {};
   var filterParams = {};
diff --git a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
index b3a1a1a9421a4a7800baae47cc9b3028f8dcc1ab..a2a207664e1fb12d2ca016cc1d40fff11aa4972f 100644
--- a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
+++ b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js
@@ -458,6 +458,13 @@ OverlayPanel.prototype.openAddOverlayDialog = function () {
   content.appendChild(contentInput);
   content.appendChild(guiUtils.createNewLine());
 
+  var consentCheckbox = document.createElement("input");
+  consentCheckbox.type = "checkbox";
+  content.appendChild(consentCheckbox);
+  content.appendChild(guiUtils.createLabel("I am aware that this map is displayed under the terms of the <a href='https://cloud.google.com/maps-platform/terms/' target='_blank'>license of Google Maps Platform</a> and I agree to these terms. " +
+    "In particular, I warrant that this dataset does not contain Protected Health Information (as defined in and subject to HIPAA). "));
+
+
   var buttons = [{
     text: "UPLOAD",
     click: function () {
@@ -477,6 +484,7 @@ OverlayPanel.prototype.openAddOverlayDialog = function () {
           name: nameInput.value,
           description: descriptionInput.value,
           content: fileContent,
+          googleLicenseConsent: consentCheckbox.checked,
           filename: fileInput.value
         };
         GuiConnector.showProcessing();
diff --git a/frontend-js/src/main/js/map/data/User.js b/frontend-js/src/main/js/map/data/User.js
index cd41f7d7f9760ec82f889fe2618259a19fc1c792..2828e4175e8da0d4652755f1871cd417c7a320b0 100644
--- a/frontend-js/src/main/js/map/data/User.js
+++ b/frontend-js/src/main/js/map/data/User.js
@@ -14,6 +14,7 @@ function User(javaObject) {
   this.setMinColor(javaObject.minColor);
   this.setMaxColor(javaObject.maxColor);
   this.setSimpleColor(javaObject.simpleColor);
+  this.setTermsOfUseConsent(javaObject.termsOfUseConsent);
 }
 
 User.prototype.setLogin = function(login) {
@@ -88,4 +89,12 @@ User.prototype.getPrivileges = function() {
   return this._privileges;
 };
 
+User.prototype.setTermsOfUseConsent = function(termsOfUseConsent) {
+  this._termsOfUseConsent = termsOfUseConsent;
+};
+
+User.prototype.isTermsOfUseConsent = function() {
+  return this._termsOfUseConsent;
+};
+
 module.exports = User;
diff --git a/frontend-js/src/main/js/minerva.js b/frontend-js/src/main/js/minerva.js
index 5d8ba60ef56cb304e5e9869ec9c9550725307edc..6556f66841cb5010100bfbafc9dc59625629c382 100644
--- a/frontend-js/src/main/js/minerva.js
+++ b/frontend-js/src/main/js/minerva.js
@@ -57,6 +57,54 @@ function processUrlGetParams(params) {
 
 }
 
+function requestConsent(user, termsOfUseUrl) {
+  var dialog = document.createElement("div");
+  var dialogContent = document.createElement("div");
+  dialogContent.appendChild(functions.createElement({
+    type: "span",
+    content: "I agree to the minerva <a href='" + termsOfUseUrl + "' target='_blank'>Terms of Use</a>."
+  }));
+  var checkbox = functions.createElement({type: "input", inputType: "checkbox", style: "float: left"});
+  var okButton = functions.createElement({
+    type: "button",
+    content: "OK",
+    className: "ui-button ui-corner-all ui-widget",
+    onclick: function () {
+      return ServerConnector.updateTermsOfUse(user, $(checkbox).is(':checked')).then(function () {
+        $(dialog).dialog("close");
+      }).catch(GuiConnector.alert);
+    }
+  });
+  var cancelButton = functions.createElement({
+    type: "button",
+    content: "I disagree",
+    className: "ui-button ui-corner-all ui-widget",
+    onclick: function () {
+      return ServerConnector.logout().catch(GuiConnector.alert);
+    }
+  });
+  $(okButton).prop("disabled", true);
+  $(checkbox).change(function () {
+    $(okButton).prop("disabled", !$(checkbox).is(':checked'));
+  });
+  dialogContent.appendChild(checkbox);
+  dialogContent.appendChild(okButton);
+  dialogContent.appendChild(cancelButton);
+
+  dialog.appendChild(dialogContent);
+  document.body.appendChild(dialog);
+  $(dialog).dialog({
+    classes: {
+      "ui-dialog": "ui-state-error"
+    },
+    modal: true,
+    closeOnEscape: false,
+    title: "Terms of Use"
+  }).siblings('.ui-dialog-titlebar').css("background", "red");
+  $(".ui-dialog-titlebar-close", $(dialog).dialog().siblings('.ui-dialog-titlebar')).hide();
+  $(dialog).dialog("open");
+}
+
 function insertGoogleAnalyticsCode() {
   return ServerConnector.getConfigurationParam(ConfigurationType.GOOGLE_ANALYTICS_IDENTIFIER).then(
     function (identifier) {
@@ -553,9 +601,14 @@ function create(params) {
       return customMap.openSubmap(submapId);
     }
   }).then(function () {
+    return ServerConnector.getLoggedUser();
+  }).then(function (user) {
     if (leftPanel.isGoogleLicenseConsentRequired()) {
       GuiConnector.alert("Some data overlays doesn't have consent to the terms of the <a href='https://cloud.google.com/maps-platform/terms/' target='_blank'>license of Google Maps Platform</a>. To be able to visualize them you must edit data overlay. ")
     }
+    if (user.getLogin() !== "anonymous" && !user.isTermsOfUseConsent()) {
+      requestConsent(user, params.getConfiguration().getOption(ConfigurationType.TERMS_OF_USE));
+    }
     var result = createResult(customMap);
 
     if (params.isDebug()) {
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
index e38e7d1c1d1bfeb3bd8bf509ca6b4a193f2bf311..7937c6f9a5dfb0b05b81c2b7e55250ca9fa9b9fe 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/ConfigurationElementType.java
@@ -165,6 +165,11 @@ public enum ConfigurationElementType {
       + "(\"General overlays\") on this MINERVA server contain Protected Health Information (as defined in and subject to HIPAA).", 
       "", ConfigurationElementEditType.STRING, false),
 
+  /**
+   * File where legend 4/4 is stored.
+   */
+  TERMS_OF_USE("Terms of use file", "resources/other/terms_of_use.pdf", ConfigurationElementEditType.URL, false),
+
   ;
 
 	/**
diff --git a/model/src/main/java/lcsb/mapviewer/model/user/User.java b/model/src/main/java/lcsb/mapviewer/model/user/User.java
index 216c7837dbf52005d912857520f45af158284698..65d41b9972dd369814bf13b56f624c1ec4ec768e 100644
--- a/model/src/main/java/lcsb/mapviewer/model/user/User.java
+++ b/model/src/main/java/lcsb/mapviewer/model/user/User.java
@@ -92,6 +92,9 @@ public class User implements Serializable {
 	 */
 	private boolean							 removed					= false;
 
+    @Column(name="terms_of_use_consent")
+    private boolean                     termsOfUseConsent = false;
+
 	/**
 	 * Set of user privileges.
 	 */
@@ -333,4 +336,12 @@ public class User implements Serializable {
 		this.simpleColor = simpleColor;
 	}
 
+  public boolean isTermsOfUseConsent() {
+    return termsOfUseConsent;
+  }
+
+  public void setTermsOfUseConsent(boolean termsOfUseConsent) {
+    this.termsOfUseConsent = termsOfUseConsent;
+  }
+
 }
diff --git a/persist/src/db/11.1.0/fix_db_20180525.sql b/persist/src/db/11.1.0/fix_db_20180525.sql
new file mode 100644
index 0000000000000000000000000000000000000000..70350604e3100f5731f53e5b0162df1098da67f7
--- /dev/null
+++ b/persist/src/db/11.1.0/fix_db_20180525.sql
@@ -0,0 +1 @@
+alter table user_table add column terms_of_use_consent boolean default false;
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
index c2ac91b71fa855a848b67eec50bea82bed307d85..61db38733a967ded7a8cbbb616945f3bfb471cfe 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayController.java
@@ -100,10 +100,11 @@ public class OverlayController extends BaseController {
 			@RequestParam(value = "name") String name, //
 			@RequestParam(value = "description") String description, //
 			@RequestParam(value = "content") String content, //
-			@RequestParam(value = "filename") String filename, //
+            @RequestParam(value = "filename") String filename, //
+            @RequestParam(value = "googleLicenseConsent") String googleLicenseConsent, //			
 			@RequestParam(value = "type", defaultValue = "") String type //
 	) throws SecurityException, QueryException, IOException {
-		return overlayRestImp.addOverlay(token, projectId, name, description, content, filename, type);
+		return overlayRestImp.addOverlay(token, projectId, name, description, content, filename, type, googleLicenseConsent);
 	}
 
 	@RequestMapping(value = "/projects/{projectId}/overlays/{overlayId}", method = { RequestMethod.DELETE }, produces = { MediaType.APPLICATION_JSON_VALUE })
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
index 6afdfab0642b513c632fbc78cbeb5bfc83a22edc..596b9b41cadffdbb22e25cc9dcbe8006efc3856e 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayRestImpl.java
@@ -212,7 +212,7 @@ public class OverlayRestImpl extends BaseRestImpl {
 		this.layoutDao = layoutDao;
 	}
 
-	public LayoutView addOverlay(String token, String projectId, String name, String description, String content, String filename, String type)
+	public LayoutView addOverlay(String token, String projectId, String name, String description, String content, String filename, String type, String googleLicenseConsent)
 			throws SecurityException, QueryException, IOException {
 		AuthenticationToken authenticationToken = getUserService().getToken(token);
 		User user = getUserService().getUserByToken(token);
@@ -239,7 +239,7 @@ public class OverlayRestImpl extends BaseRestImpl {
 			LayoutView layout = layoutService.createLayout(
 					new CreateLayoutParams()
 							.async(false).colorInputStream(stream).description(description).layoutFileName(filename).model(model).name(name).user(user)
-							.colorSchemaType(colorSchemaType).directory("."));
+							.colorSchemaType(colorSchemaType).directory(".").googleLicenseConsent(googleLicenseConsent.equalsIgnoreCase("true")));
 			return layoutService.getLayoutById(model, Integer.valueOf(layout.getIdObject()), authenticationToken);
 		} catch (InvalidColorSchemaException e) {
 			throw new QueryException(e.getMessage(), e);
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserController.java b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserController.java
index ac97009a284e85a6ab2322187953fca0e40ae2ed..023ba7de7e9f5625b0801eba5b93b2bda856e2e6 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserController.java
@@ -91,6 +91,18 @@ public class UserController extends BaseController {
         result.put("status", "OK");
 		return result;
 	}
+	
+	/**
+	 * TODO remove when API 12 will be released!!!
+	 */
+    @RequestMapping(value = "/users/{login:.+}/updateTermsOfUse", method = { RequestMethod.GET, RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
+    public Map<String, Object> updateTermsOfUse(@CookieValue(value = Configuration.AUTH_TOKEN) String token,
+        @PathVariable(value = "login") String login, //
+        @RequestParam(value = "value") String value, //
+            HttpServletResponse response //
+            ) throws SecurityException, ObjectNotFoundException {
+      return userRest.updateTermsOfUse(token, login, value);
+    }
 
 	/**
 	 * @return the userService
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
index bcd07b094b7ae9854fe2952e8f656493de13458f..bf94bdf6be3ab6e1535534f578fbb38e22ad8ec9 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
@@ -79,6 +79,7 @@ public class UserRestImpl {
 			columnsSet.add("simpleColor");
 			columnsSet.add("removed");
 			columnsSet.add("privileges");
+            columnsSet.add("termsOfUseConsent");
 		} else {
 			for (String str : columns.split(",")) {
 				columnsSet.add(str);
@@ -108,8 +109,10 @@ public class UserRestImpl {
 				value = user.getMaxColor();
 			} else if (column.equals("simplecolor")) {
 				value = user.getSimpleColor();
-			} else if (column.equals("removed")) {
-				value = user.isRemoved();
+            } else if (column.equals("removed")) {
+              value = user.isRemoved();
+            } else if (column.equals("termsofuseconsent")) {
+              value = user.isTermsOfUseConsent();				
 			} else if (column.equals("privileges") && admin) {
 				value = preparePrivileges(user);
 			} else {
@@ -172,4 +175,19 @@ public class UserRestImpl {
 		this.layoutService = layoutService;
 	}
 
+  public Map<String, Object> updateTermsOfUse(String token, String login, String value) throws SecurityException, ObjectNotFoundException {
+    User ownUserData = userService.getUserByToken(token);
+    if (ownUserData == null || ownUserData.getLogin().equals("anonymous")) {
+      throw new ObjectNotFoundException("User doesn't exist");
+    }
+    if (!ownUserData.getLogin().equals(login)) {
+      throw new SecurityException("Access denied");
+    }
+    ownUserData.setTermsOfUseConsent(value.equalsIgnoreCase("true"));
+    userService.updateUser(ownUserData);
+    Set<String> columnSet = createUserColumnSet("");
+
+    return prepareUse(ownUserData, columnSet, true);
+  }
+
 }
diff --git a/web/src/main/webapp/resources/other/terms_of_use.pdf b/web/src/main/webapp/resources/other/terms_of_use.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..21f7fb0abbde215ce1391ed614874e4060bcb94c
Binary files /dev/null and b/web/src/main/webapp/resources/other/terms_of_use.pdf differ