diff --git a/src/main/java/org/olat/course/nodes/edubase/EdubaseContext.java b/src/main/java/org/olat/course/nodes/edubase/EdubaseContext.java
index a4cfa0350d975606d59a8e2eefe19a71371e91eb..d407ef026f54f11fe6e50614da62f364fea1df4b 100644
--- a/src/main/java/org/olat/course/nodes/edubase/EdubaseContext.java
+++ b/src/main/java/org/olat/course/nodes/edubase/EdubaseContext.java
@@ -30,7 +30,6 @@ import org.olat.ims.lti.LTIContext;
 import org.olat.ims.lti.LTIDisplayOptions;
 import org.olat.ims.lti.LTIManager;
 import org.olat.modules.edubase.EdubaseManager;
-import org.olat.modules.edubase.EdubaseModule;
 
 /**
  *
@@ -104,9 +103,10 @@ public class EdubaseContext implements LTIContext {
 	public String getCustomProperties() {
 		Map<String, String> customProps = new HashMap<>();
 
-		String readerUrl =  CoreSpringFactory.getImpl(EdubaseModule.class).getReaderUrl();
-		if (StringHelper.containsNonWhitespace(readerUrl)) {
-			customProps.put(CUSTOM_APPLICATION, readerUrl);
+		Identity identity = identityEnvironment.getIdentity();
+		String applicationUrl =  CoreSpringFactory.getImpl(EdubaseManager.class).getApplicationUrl(identity);
+		if (StringHelper.containsNonWhitespace(applicationUrl)) {
+			customProps.put(CUSTOM_APPLICATION, applicationUrl);
 		}
 		if (pageTo != null) {
 			customProps.put(CUSTOM_END_PAGE, Integer.toString(pageTo));
diff --git a/src/main/java/org/olat/modules/edubase/EdubaseManager.java b/src/main/java/org/olat/modules/edubase/EdubaseManager.java
index 2c925ec8194c3faaebccd1d9f9165433659625a1..73bb0fbcba3416466ba8bedb49a9e5e9583afcc4 100644
--- a/src/main/java/org/olat/modules/edubase/EdubaseManager.java
+++ b/src/main/java/org/olat/modules/edubase/EdubaseManager.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.edubase;
 
+import org.olat.core.id.Identity;
 import org.olat.core.id.IdentityEnvironment;
 
 /**
@@ -63,6 +64,15 @@ public interface EdubaseManager {
 	 */
 	public String getLtiLaunchUrl(BookSection bookSection);
 
+	/**
+	 * The application url is the target url of the edubase reader. The url is
+	 * depending on the module configuration unique per identity.
+	 * 
+	 * @param identity
+	 * @return
+	 */
+	public String getApplicationUrl(Identity identity);
+
 	/**
 	 * Request details of a book version from the Edubase InfoDocVers Service.
 	 *
diff --git a/src/main/java/org/olat/modules/edubase/EdubaseModule.java b/src/main/java/org/olat/modules/edubase/EdubaseModule.java
index 0e349d51478e87a8d0115d97d72a855da50246fd..81ab22f3c82d846726422e6ea6a7450a6bde6077 100644
--- a/src/main/java/org/olat/modules/edubase/EdubaseModule.java
+++ b/src/main/java/org/olat/modules/edubase/EdubaseModule.java
@@ -40,6 +40,7 @@ public class EdubaseModule extends AbstractSpringModule implements ConfigOnOff {
 	public static final String EDUBASE_OAUTH_KEY = "edubase.oauthKey";
 	public static final String EDUBASE_OAUTH_SECRET = "edubase.oauth";
 	public static final String EDUBASE_READER_URL = "edubase.readerUrl";
+	public static final String EDUBASE_READER_URL_UNIQUE = "edubase.readerUrl.unique";
 	public static final String EDUBASE_LTI_LAUNCH_URL = "edubase.ltiLaunchUrl";
 	public static final String EDUBASE_INFOVER_URL = "edubase.infoverUrl";
 
@@ -49,6 +50,8 @@ public class EdubaseModule extends AbstractSpringModule implements ConfigOnOff {
 	private String oauthSecret;
 	@Value("${edubase.readerUrl}")
 	private String readerUrl;
+	@Value("${edubase.readerUrl.unique:true}")
+	private boolean readerUrlUnique;
 	@Value("${edubase.ltiLaunchUrl}")
 	private String ltiLaunchUrl;
 	@Value("${edubase.infoverUrl}")
@@ -85,6 +88,11 @@ public class EdubaseModule extends AbstractSpringModule implements ConfigOnOff {
 		if (StringHelper.containsNonWhitespace(readerUrlObj)) {
 			readerUrl = readerUrlObj;
 		}
+		
+		String readerUrlUniqueObj = getStringPropertyValue(EDUBASE_READER_URL_UNIQUE, true);
+		if(StringHelper.containsNonWhitespace(readerUrlUniqueObj)) {
+			readerUrlUnique = "true".equals(readerUrlUniqueObj);
+		}
 
 		String ltiLaunchUrlObj = getStringPropertyValue(EDUBASE_LTI_LAUNCH_URL, true);
 		if (StringHelper.containsNonWhitespace(ltiLaunchUrlObj)) {
@@ -129,6 +137,14 @@ public class EdubaseModule extends AbstractSpringModule implements ConfigOnOff {
 		setStringProperty(EDUBASE_READER_URL, readerUrl, true);
 	}
 
+	public boolean isReaderUrlUnique() {
+		return readerUrlUnique;
+	}
+
+	public void setReaderUrlUnique(boolean readerUrlUnique) {
+		this.readerUrlUnique = readerUrlUnique;
+	}
+
 	public String getLtiLaunchUrl() {
 		return ltiLaunchUrl;
 	}
diff --git a/src/main/java/org/olat/modules/edubase/manager/EdubaseManagerImpl.java b/src/main/java/org/olat/modules/edubase/manager/EdubaseManagerImpl.java
index 11463e6d503e4afba6063b6e140b794022f03629..628d3bde81adccb478410d1ea97146428fc3a05c 100644
--- a/src/main/java/org/olat/modules/edubase/manager/EdubaseManagerImpl.java
+++ b/src/main/java/org/olat/modules/edubase/manager/EdubaseManagerImpl.java
@@ -23,6 +23,7 @@ package org.olat.modules.edubase.manager;
 import java.io.EOFException;
 import java.net.SocketTimeoutException;
 import java.util.Optional;
+import java.util.UUID;
 
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.CloseableHttpResponse;
@@ -33,10 +34,12 @@ import org.apache.http.util.EntityUtils;
 import org.codehaus.jackson.JsonParseException;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.olat.basesecurity.AuthHelper;
+import org.olat.core.id.Identity;
 import org.olat.core.id.IdentityEnvironment;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
+import org.olat.core.util.WebappHelper;
 import org.olat.login.LoginModule;
 import org.olat.login.auth.AuthenticationProvider;
 import org.olat.modules.edubase.BookDetails;
@@ -137,6 +140,27 @@ public class EdubaseManagerImpl implements EdubaseManager {
 		return url.toString();
 	}
 
+	@Override
+	public String getApplicationUrl(Identity identity) {
+		String readerUrl = edubaseModule.getReaderUrl();
+		if (edubaseModule.isReaderUrlUnique()) {
+			int protocolEnd = readerUrl.indexOf("//") + 2;
+			String protocol = readerUrl.substring(0, protocolEnd);
+			String host = readerUrl.substring(protocolEnd);
+			// Is OpenOLAT identity ok or should it be the getUserId(identEnv)?
+			String identityKey = String.valueOf(identity.getKey());
+			String identityHash = UUID.nameUUIDFromBytes(identityKey.getBytes()).toString().replace("-", "");
+			readerUrl = new StringBuilder()
+					.append(protocol)
+					.append(identityHash)
+					.append("-")
+					.append(WebappHelper.getInstanceId())
+					.append(".")
+					.append(host).toString();
+		}
+		return readerUrl;
+	}
+
 	@Override
 	public BookDetails fetchBookDetails(String bookId) {
 		BookDetails infoReponse = new BookDetailsImpl();
diff --git a/src/main/java/org/olat/modules/edubase/ui/EdubaseAdminController.java b/src/main/java/org/olat/modules/edubase/ui/EdubaseAdminController.java
index cb860e20441756e535e0c036d0fac0ea5f3e03ad..025fc61053b01bf9d2aa47fd1281f389ac0e5900 100644
--- a/src/main/java/org/olat/modules/edubase/ui/EdubaseAdminController.java
+++ b/src/main/java/org/olat/modules/edubase/ui/EdubaseAdminController.java
@@ -46,6 +46,7 @@ public class EdubaseAdminController extends FormBasicController {
 	private TextElement edubaseOauthSecretEl;
 	private TextElement edubaseLtiLaunchUrlEl;
 	private TextElement edubaseReaderUrlEl;
+	private MultipleSelectionElement edubaseReaderUrlUniqueEl;
 	private TextElement edubaseInfoverUrlEl;
 
 	@Autowired
@@ -68,9 +69,7 @@ public class EdubaseAdminController extends FormBasicController {
 
 		String[] enableValues = new String[]{ translate("on") };
 		edubaseEnabledEl = uifactory.addCheckboxesHorizontal("admin.edubase.enabled", edubaseCont, enabledKeys, enableValues);
-		if (edubaseModule.isEnabled()) {
-			edubaseEnabledEl.select(enabledKeys[0], true);
-		}
+		edubaseEnabledEl.select(enabledKeys[0], edubaseModule.isEnabled());
 
 		String edubaseOauthKey = edubaseModule.getOauthKey();
 		edubaseOauthKeyEl = uifactory.addTextElement("admin.edubase.oauth.key", "admin.edubase.oauth.key", 128, edubaseOauthKey, edubaseCont);
@@ -90,6 +89,10 @@ public class EdubaseAdminController extends FormBasicController {
 		String edubaseReaderUrl = edubaseModule.getReaderUrl();
 		edubaseReaderUrlEl = uifactory.addTextElement("admin.edubase.reader.url", "admin.edubase.reader.url", 128, edubaseReaderUrl, edubaseCont);
 		edubaseReaderUrlEl.setMandatory(true);
+		
+		edubaseReaderUrlUniqueEl = uifactory.addCheckboxesHorizontal("admin.edubase.reader.url.unique", edubaseCont, enabledKeys, enableValues);
+		edubaseReaderUrlUniqueEl.setHelpTextKey("admin.edubase.reader.url.unique.help", null);
+		edubaseReaderUrlUniqueEl.select(enabledKeys[0], edubaseModule.isReaderUrlUnique());
 
 		String edubaseInfoverUrl = edubaseModule.getInfoverUrl();
 		edubaseInfoverUrlEl = uifactory.addTextElement("admin.edubase.infover.url", "admin.edubase.infover.url", 128, edubaseInfoverUrl, edubaseCont);
@@ -116,6 +119,7 @@ public class EdubaseAdminController extends FormBasicController {
 		edubaseModule.setOauthSecret(edubaseOauthSecretEl.getValue());
 		edubaseModule.setLtiLaunchUrl(edubaseLtiLaunchUrlEl.getValue());
 		edubaseModule.setReaderUrl(edubaseReaderUrlEl.getValue());
+		edubaseModule.setReaderUrlUnique(edubaseReaderUrlUniqueEl.isAtLeastSelected(1));
 		edubaseModule.setInfoverUrl(edubaseInfoverUrlEl.getValue());
 	}
 
diff --git a/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_de.properties
index 6bc9feaf0174f83adb0e1b5a167161ffa5c0a9f8..6953bd7bff015e14d07ab73d001e768f20396946 100644
--- a/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_de.properties
@@ -6,6 +6,8 @@ admin.edubase.lti.launch.url=URL LTI Start
 admin.edubase.oauth.key=Key
 admin.edubase.oauth.secret=Secret
 admin.edubase.reader.url=URL Edubase Reader
+admin.edubase.reader.url.unique=URL Edubase Reader eindeutig
+admin.edubase.reader.url.unique.help=Die Edubase Reader URL wird um ein pro Benutzer eindeutiges K\u00fcrzel erg\u00e4nzt, damit Probleme mit der Anzahl registrierter Ger\u00e4te vermieden werden k\u00f6nnen.
 admin.edubase.title=Edubase
 admin.expert.settings=Experteneistellungen
 admin.menu.title.alt=Edubase und Edubook Kursbausteine
diff --git a/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_en.properties
index e24e25b3860760e73ecddd33912cd9ada2aa2681..29f4d7dfe50e5fc0814d747fd5e88b3fd485d552 100644
--- a/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/edubase/ui/_i18n/LocalStrings_en.properties
@@ -6,6 +6,8 @@ admin.edubase.lti.launch.url=URL LTI launch
 admin.edubase.oauth.key=Key
 admin.edubase.oauth.secret=Secret
 admin.edubase.reader.url=URL Edubase Reader
+admin.edubase.reader.url.unique=URL Edubase Reader unique
+admin.edubase.reader.url.unique.help=The Edubase Reader URL is amended by a user specific token to avoid problems with the number of devices.
 admin.edubase.title=Edubase
 admin.expert.settings=Expert settings
 admin.menu.title.alt=Edubase and Edubook course elements
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index ab6e4e7be6b2b8a893be212cadebf90e99289ba1..beda32fd2fe2efdedf39fbec82679d31ac8312d6 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -1351,6 +1351,7 @@ card2brain.verifyLtiUrl=https://card2brain.ch/grails/SSO/verifyLti.dispatch
 ########################################
 edubase.enabled=false
 edubase.readerUrl=https://app.edubase.ch/
+edubase.readerUrl.unique=true
 edubase.ltiLaunchUrl=https://reader.silkcodeapps.de/lookup/srv/v2/lti/basicLaunch/
 edubase.infoverUrl=https://reader.silkcodeapps.de/lookup/srv/v2/information/infodocvers/%s
 
diff --git a/src/test/java/org/olat/modules/edubase/manager/EdubaseManagerImplTest.java b/src/test/java/org/olat/modules/edubase/manager/EdubaseManagerImplTest.java
index c37dbe2bb77f5d016776053d49421f62b622d90c..936755b5a48da9dd536384989d5c941140893826 100644
--- a/src/test/java/org/olat/modules/edubase/manager/EdubaseManagerImplTest.java
+++ b/src/test/java/org/olat/modules/edubase/manager/EdubaseManagerImplTest.java
@@ -209,5 +209,61 @@ public class EdubaseManagerImplTest {
 		String expectedLtiUrl = baseUrl + "/" + BOOK_ID + "/" + pageFrom;
 		assertThat(generatedLtiUrl).isEqualTo(expectedLtiUrl);
 	}
+	
+	@Test
+	public void shouldGetApplicationUrl() {
+		IdentityImpl identityImpl = new IdentityImpl();
+		String readerUrl = "https://reader.openolat.com";
+		when(edubaseModuleMock.getReaderUrl()).thenReturn(readerUrl);
+		when(edubaseModuleMock.isReaderUrlUnique()).thenReturn(Boolean.FALSE);
+		
+		String applicationUrl = sut.getApplicationUrl(identityImpl);
+		
+		assertThat(applicationUrl).isEqualTo(readerUrl);
+	}
+	
+	@Test
+	public void shouldGetApplicationUrlWithToken() {
+		IdentityImpl identityImpl = new IdentityImpl();
+		identityImpl.setKey(Long.valueOf("1"));
+		String readerUrl = "https://reader.openolat.com";
+		when(edubaseModuleMock.getReaderUrl()).thenReturn(readerUrl);
+		when(edubaseModuleMock.isReaderUrlUnique()).thenReturn(Boolean.TRUE);
+		
+		String applicationUrl = sut.getApplicationUrl(identityImpl);
+		
+		assertThat(applicationUrl).startsWith("https://").endsWith("reader.openolat.com");
+		assertThat(applicationUrl.length()).isGreaterThan(readerUrl.length());
+	}
+	
+	@Test
+	public void shouldGetAllwaysSameApplicationUrlForAUser() {
+		IdentityImpl identityImpl = new IdentityImpl();
+		identityImpl.setKey(Long.valueOf("1"));
+		String readerUrl = "https://reader.openolat.com";
+		when(edubaseModuleMock.getReaderUrl()).thenReturn(readerUrl);
+		when(edubaseModuleMock.isReaderUrlUnique()).thenReturn(Boolean.TRUE);
+		
+		String applicationUrl1 = sut.getApplicationUrl(identityImpl);
+		String applicationUrl2 = sut.getApplicationUrl(identityImpl);
+		
+		assertThat(applicationUrl1).isEqualTo(applicationUrl2);
+	}
+	
+	@Test
+	public void shouldGetDifferentApplicationUrlForDifferentUsers() {
+		IdentityImpl identityImpl1 = new IdentityImpl();
+		identityImpl1.setKey(Long.valueOf("1"));
+		IdentityImpl identityImpl2 = new IdentityImpl();
+		identityImpl2.setKey(Long.valueOf("2"));
+		String readerUrl = "https://reader.openolat.com";
+		when(edubaseModuleMock.getReaderUrl()).thenReturn(readerUrl);
+		when(edubaseModuleMock.isReaderUrlUnique()).thenReturn(Boolean.TRUE);
+		
+		String applicationUrl1 = sut.getApplicationUrl(identityImpl1);
+		String applicationUrl2 = sut.getApplicationUrl(identityImpl2);
+		
+		assertThat(applicationUrl1).isNotEqualTo(applicationUrl2);
+	}
 
 }