diff --git a/src/main/java/caosdb/server/CaosAuthenticator.java b/src/main/java/caosdb/server/CaosAuthenticator.java
index f2297c56ab843cd16d3997fc6ac8985d5c5ac33c..8fefee3b453dabc0c613228e2495acacb19deaa0 100644
--- a/src/main/java/caosdb/server/CaosAuthenticator.java
+++ b/src/main/java/caosdb/server/CaosAuthenticator.java
@@ -56,7 +56,7 @@ public class CaosAuthenticator extends Authenticator {
     try {
       final AuthenticationToken sessionToken =
           AuthenticationUtils.parseSessionTokenCookie(
-              request.getCookies().getFirst(AuthenticationUtils.SESSION_TOKEN_COOKIE), null);
+              request.getCookies().getFirst(AuthenticationUtils.SESSION_TOKEN_COOKIE));
 
       if (sessionToken != null) {
         subject.login(sessionToken);
diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java
index 4b0ead406d99ceb4214eed55c08caf8aea5e19f4..bfca2f3c13520ec83a35c8f3bd8d88cdb6ae1f81 100644
--- a/src/main/java/caosdb/server/CaosDBServer.java
+++ b/src/main/java/caosdb/server/CaosDBServer.java
@@ -24,6 +24,7 @@ import caosdb.server.accessControl.AnonymousRealm;
 import caosdb.server.accessControl.AuthenticationUtils;
 import caosdb.server.accessControl.CaosDBAuthorizingRealm;
 import caosdb.server.accessControl.CaosDBDefaultRealm;
+import caosdb.server.accessControl.ConsumedInfoCleanupJob;
 import caosdb.server.accessControl.OneTimeAuthenticationToken;
 import caosdb.server.accessControl.SessionToken;
 import caosdb.server.accessControl.SessionTokenRealm;
@@ -313,7 +314,7 @@ public class CaosDBServer extends Application {
 
   public static void initOneTimeTokens() throws Exception {
     OneTimeAuthenticationToken.initConfig();
-    OneTimeAuthenticationToken.initConsumedInfoCleanup();
+    ConsumedInfoCleanupJob.scheduleDaily();
   }
 
   /**
@@ -581,7 +582,7 @@ public class CaosDBServer extends Application {
             final Subject subject = SecurityUtils.getSubject();
             if (subject.isAuthenticated()
                 && subject.getPrincipal() != AnonymousAuthenticationToken.PRINCIPAL) {
-              final SessionToken sessionToken = SessionToken.generate(subject, null);
+              final SessionToken sessionToken = SessionToken.generate(subject);
 
               // set session token cookie (httpOnly, secure cookie which
               // is used to recognize a user session)
diff --git a/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java b/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java
index 9dd660e54fc6c91d97470467dcddef01fd7e4d05..0cbaf9ef0b6a61d66ffe9b2687c0501710ae2be9 100644
--- a/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java
+++ b/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java
@@ -97,12 +97,11 @@ public class AuthenticationUtils {
    * @return A new SessionToken
    * @see {@link AuthenticationUtils#createSessionTokenCookie(SessionToken)}, {@link SessionToken}
    */
-  public static SelfValidatingAuthenticationToken parseSessionTokenCookie(
-      final Cookie cookie, final String curry) {
+  public static SelfValidatingAuthenticationToken parseSessionTokenCookie(final Cookie cookie) {
     if (cookie != null) {
       final String tokenString = URLDecodeWithUTF8(cookie.getValue());
       if (tokenString != null && !tokenString.equals("")) {
-        return SelfValidatingAuthenticationToken.parse(tokenString, curry);
+        return SelfValidatingAuthenticationToken.parse(tokenString);
       }
     }
     return null;
@@ -195,4 +194,10 @@ public class AuthenticationUtils {
   public static Collection<String> getRoles(Subject user) {
     return new CaosDBAuthorizingRealm().doGetAuthorizationInfo(user.getPrincipals()).getRoles();
   }
+
+  public static boolean isFromOneTimeTokenRealm(Subject subject) {
+    return ((Principal) subject.getPrincipal())
+        .getRealm()
+        .equals(OneTimeAuthenticationToken.REALM_NAME);
+  }
 }
diff --git a/src/main/java/caosdb/server/accessControl/ConsumedInfoCleanupJob.java b/src/main/java/caosdb/server/accessControl/ConsumedInfoCleanupJob.java
new file mode 100644
index 0000000000000000000000000000000000000000..97652d6f24e74efb1686fe816d0aa83b7b9c2d9f
--- /dev/null
+++ b/src/main/java/caosdb/server/accessControl/ConsumedInfoCleanupJob.java
@@ -0,0 +1,29 @@
+package caosdb.server.accessControl;
+
+import caosdb.server.CaosDBServer;
+import org.quartz.CronScheduleBuilder;
+import org.quartz.Job;
+import org.quartz.JobBuilder;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.SchedulerException;
+import org.quartz.Trigger;
+import org.quartz.TriggerBuilder;
+
+public class ConsumedInfoCleanupJob implements Job {
+
+  public static void scheduleDaily() throws SchedulerException {
+    JobDetail job = JobBuilder.newJob(ConsumedInfoCleanupJob.class).build();
+    Trigger trigger =
+        TriggerBuilder.newTrigger()
+            .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(0, 0))
+            .build();
+    CaosDBServer.scheduleJob(job, trigger);
+  }
+
+  @Override
+  public void execute(JobExecutionContext context) throws JobExecutionException {
+    ConsumedInfo.cleanupConsumedInfo();
+  }
+}
diff --git a/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java b/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java
index 16b48b54dbca9ab0bf51b4001dcee7ddeac42c41..886a7ba33e1ec5a528aa2f9cdb787c8f53168d7f 100644
--- a/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java
+++ b/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java
@@ -51,15 +51,37 @@ import org.quartz.SchedulerException;
 import org.quartz.Trigger;
 import org.quartz.TriggerBuilder;
 
-class ConsumedInfoCleanupJob implements Job {
+class ConsumedInfo {
 
-  @Override
-  public void execute(JobExecutionContext context) throws JobExecutionException {
-    OneTimeAuthenticationToken.cleanupConsumedInfo();
+  private static Map<String, ConsumedInfo> consumedOneTimeTokens = new HashMap<>();
+
+  public static void cleanupConsumedInfo() {
+    synchronized (consumedOneTimeTokens) {
+      for (Iterator<Map.Entry<String, ConsumedInfo>> it =
+              consumedOneTimeTokens.entrySet().iterator();
+          it.hasNext(); ) {
+        Map.Entry<String, ConsumedInfo> next = it.next();
+        if (next.getValue().isExpired()) {
+          it.remove();
+        }
+      }
+    }
   }
-}
 
-class ConsumedInfo {
+  public static void consume(OneTimeAuthenticationToken oneTimeAuthenticationToken) {
+    if (oneTimeAuthenticationToken.isValid()) {
+      String key = ConsumedInfo.getKey(oneTimeAuthenticationToken);
+      ConsumedInfo consumedInfo = null;
+      synchronized (consumedOneTimeTokens) {
+        consumedInfo = consumedOneTimeTokens.get(key);
+        if (consumedInfo == null) {
+          consumedInfo = new ConsumedInfo(oneTimeAuthenticationToken);
+          consumedOneTimeTokens.put(key, consumedInfo);
+        }
+      }
+      consumedInfo.consume();
+    }
+  }
 
   private OneTimeAuthenticationToken oneTimeAuthenticationToken;
   private List<Long> attempts = new LinkedList<>();
@@ -95,6 +117,7 @@ class ConsumedInfo {
       } else if (getAttemptTimeout() < System.currentTimeMillis()) {
         throw new AuthenticationException("One-time token attempts timeout expired.");
       }
+      // TODO log?
       attempts.add(System.currentTimeMillis());
     }
   }
@@ -113,8 +136,8 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
   public static final int DEFAULT_TIMEOUT_MS =
       Integer.parseInt(
           CaosDBServer.getServerProperty(ServerProperties.KEY_ONE_TIME_TOKEN_EXPIRES_MS));
+  public static final String REALM_NAME = "OneTimeAuthenticationToken"; // TODO move to UserSources
 
-  private static Map<String, ConsumedInfo> consumedOneTimeTokens = new HashMap<>();
   private long maxAttempts;
   private long attemptsTimeout;
 
@@ -123,61 +146,28 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
       final long date,
       final long timeout,
       final String salt,
-      final String curry,
       final String checksum,
       final String[] permissions,
       final String[] roles,
       final long maxAttempts,
       final long attemptsTimeout) {
-    super(principal, date, timeout, salt, curry, checksum, permissions, roles);
+    super(principal, date, timeout, salt, checksum, permissions, roles);
     this.attemptsTimeout = attemptsTimeout;
     this.maxAttempts = maxAttempts;
     consume();
   }
 
-  /** TODO not yet called anywhere */
-  public static void cleanupConsumedInfo() {
-    synchronized (consumedOneTimeTokens) {
-      for (Iterator<Map.Entry<String, ConsumedInfo>> it =
-              consumedOneTimeTokens.entrySet().iterator();
-          it.hasNext(); ) {
-        Map.Entry<String, ConsumedInfo> next = it.next();
-        if (next.getValue().isExpired()) {
-          it.remove();
-        }
-      }
-    }
-  }
-
   public long getAttemptsTimeout() {
     return attemptsTimeout;
   }
 
   public void consume() {
-    consume(this);
-  }
-
-  public static void consume(OneTimeAuthenticationToken oneTimeAuthenticationToken) {
-    if (oneTimeAuthenticationToken.isValid()) {
-      String key = ConsumedInfo.getKey(oneTimeAuthenticationToken);
-      ConsumedInfo consumedInfo = null;
-      synchronized (consumedOneTimeTokens) {
-        consumedInfo = consumedOneTimeTokens.get(key);
-        if (consumedInfo == null) {
-          consumedInfo = new ConsumedInfo(oneTimeAuthenticationToken);
-          consumedOneTimeTokens.put(key, consumedInfo);
-        }
-      }
-      consumedInfo.consume();
-    } else {
-      oneTimeAuthenticationToken.isValid();
-    }
+    ConsumedInfo.consume(this);
   }
 
   public OneTimeAuthenticationToken(
       final Principal principal,
       final long timeout,
-      final String curry,
       final String[] permissions,
       final String[] roles,
       final Long maxAttempts,
@@ -185,7 +175,6 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
     super(
         principal,
         timeout,
-        curry,
         permissions,
         roles,
         defaultIfNull(maxAttempts, DEFAULT_MAX_ATTEMPTS),
@@ -201,7 +190,7 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
    * @param curry
    * @return
    */
-  public static OneTimeAuthenticationToken parse(final Object[] array, final String curry) {
+  public static OneTimeAuthenticationToken parse(final Object[] array) {
     final Principal principal = new Principal((String) array[1], (String) array[2]);
     final String[] roles = toStringArray((Object[]) array[3]);
     final String[] permissions = toStringArray((Object[]) array[4]);
@@ -212,21 +201,11 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
     final long maxAttempts = (Long) array[9];
     final long attemptsTimeout = (Long) array[10];
     return new OneTimeAuthenticationToken(
-        principal,
-        date,
-        timeout,
-        salt,
-        curry,
-        checksum,
-        permissions,
-        roles,
-        maxAttempts,
-        attemptsTimeout);
+        principal, date, timeout, salt, checksum, permissions, roles, maxAttempts, attemptsTimeout);
   }
 
   private static OneTimeAuthenticationToken generate(
       final Principal principal,
-      final String curry,
       final String[] permissions,
       final String[] roles,
       final long timeout,
@@ -234,7 +213,7 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
       final long attemptsTimeout) {
 
     return new OneTimeAuthenticationToken(
-        principal, timeout, curry, permissions, roles, maxAttempts, attemptsTimeout);
+        principal, timeout, permissions, roles, maxAttempts, attemptsTimeout);
   }
 
   public static List<Config> loadConfig(InputStream input) throws Exception {
@@ -261,23 +240,22 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
   }
 
   public static OneTimeAuthenticationToken generate(Config c) {
-    return generate(c, new Principal(AnonymousAuthenticationToken.PRINCIPAL), null);
+    return generate(c, new Principal(REALM_NAME, c.getName()));
   }
 
-  public static OneTimeAuthenticationToken generateForPurpose(
-      String purpose, Subject user, String curry) {
+  public static OneTimeAuthenticationToken generateForPurpose(String purpose, Subject user) {
     Config c = purposes.get(purpose);
     if (c != null) {
       Principal principal = (Principal) user.getPrincipal();
-      return generate(c, principal, curry);
+
+      return generate(c, principal);
     }
     return null;
   }
 
-  public static OneTimeAuthenticationToken generate(Config c, Principal principal, String curry) {
+  public static OneTimeAuthenticationToken generate(Config c, Principal principal) {
     return generate(
         principal,
-        curry,
         c.getPermissions(),
         c.getRoles(),
         c.getTimeout(),
@@ -355,9 +333,18 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
     private int maxAttempts = 1;
     private int timeout = DEFAULT_TIMEOUT_MS;
     private int attemptsTimeout = DEFAULT_ATTEMPTS_TIMEOUT_MS;
+    private String name = AnonymousAuthenticationToken.PRINCIPAL.getUsername();
 
     public Config() {}
 
+    public String getName() {
+      return name;
+    }
+
+    public void setName(String name) {
+      this.name = name;
+    }
+
     public int getTimeout() {
       return timeout;
     }
@@ -451,22 +438,13 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
     }
   }
 
-  public static void initConsumedInfoCleanup() throws SchedulerException {
-    JobDetail job = JobBuilder.newJob(ConsumedInfoCleanupJob.class).build();
-    Trigger trigger =
-        TriggerBuilder.newTrigger()
-            .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(0, 0))
-            .build();
-    CaosDBServer.scheduleJob(job, trigger);
-  }
-
   @Override
   protected void setFields(Object[] fields) {
     if (fields.length == 2) {
       this.maxAttempts = (long) fields[0];
       this.attemptsTimeout = (long) fields[1];
     } else {
-      throw new InstantiationError("Too few arguments.");
+      throw new InstantiationError("Too few fields.");
     }
   }
 
@@ -479,10 +457,10 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
         this.date,
         this.timeout,
         this.salt,
-        this.curry,
         calcChecksum((Object[]) this.permissions),
         calcChecksum((Object[]) this.roles),
         this.maxAttempts,
+        this.attemptsTimeout,
         pepper);
   }
 
diff --git a/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java b/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java
index 5de7cb21c52bb498eb0b065f607f3de0110741bc..e65b70efb407ea211f9ed0d5f516a7d17c05eb12 100644
--- a/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java
+++ b/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java
@@ -31,12 +31,11 @@ import org.eclipse.jetty.util.ajax.JSON;
 public abstract class SelfValidatingAuthenticationToken extends Principal
     implements AuthenticationToken {
 
-  protected static final transient String PEPPER = Utils.getUID();
+  protected static final transient String PEPPER = Utils.getSecureFilename(32);
   private static final long serialVersionUID = -7212039848895531161L;
   protected final long date;
   protected final long timeout;
   protected final String checksum;
-  protected final String curry;
   protected final String salt;
   protected final String[] permissions;
   protected final String[] roles;
@@ -50,7 +49,9 @@ public abstract class SelfValidatingAuthenticationToken extends Principal
   }
 
   public static final String getFreshSalt() {
-    return Utils.getUID();
+    // salt should be at least 8 octets long. https://www.ietf.org/rfc/rfc2898.txt
+    // let's double that
+    return Utils.getSecureFilename(16);
   }
 
   protected static <T> T defaultIfNull(T val, T def) {
@@ -65,11 +66,10 @@ public abstract class SelfValidatingAuthenticationToken extends Principal
       final long date,
       final long timeout,
       final String salt,
-      final String curry,
       final String checksum,
       final String[] permissions,
       final String[] roles) {
-    this(principal, date, timeout, salt, curry, permissions, roles, checksum, false);
+    this(principal, date, timeout, salt, permissions, roles, checksum, false);
   }
 
   private SelfValidatingAuthenticationToken(
@@ -77,7 +77,6 @@ public abstract class SelfValidatingAuthenticationToken extends Principal
       final long date,
       final long timeout,
       final String salt,
-      final String curry,
       final String[] permissions,
       final String[] roles,
       String checksum,
@@ -87,7 +86,6 @@ public abstract class SelfValidatingAuthenticationToken extends Principal
     this.date = date;
     this.timeout = timeout;
     this.salt = salt;
-    this.curry = curry;
     this.permissions = defaultIfNull(permissions, new String[] {});
     this.roles = defaultIfNull(roles, new String[] {});
     if (fields.length > 0) setFields(fields);
@@ -100,7 +98,6 @@ public abstract class SelfValidatingAuthenticationToken extends Principal
   public SelfValidatingAuthenticationToken(
       final Principal principal,
       final long timeout,
-      final String curry,
       final String[] permissions,
       final String[] roles,
       Object... fields) {
@@ -109,7 +106,6 @@ public abstract class SelfValidatingAuthenticationToken extends Principal
         System.currentTimeMillis(),
         timeout,
         getFreshSalt(),
-        curry,
         permissions,
         roles,
         null,
@@ -171,13 +167,13 @@ public abstract class SelfValidatingAuthenticationToken extends Principal
     return ret;
   }
 
-  public static SelfValidatingAuthenticationToken parse(String token, String curry) {
+  public static SelfValidatingAuthenticationToken parse(String token) {
     Object[] array = (Object[]) JSON.parse(token);
     switch (array[0].toString()) {
       case "O":
-        return OneTimeAuthenticationToken.parse(array, curry);
+        return OneTimeAuthenticationToken.parse(array);
       default:
-        return SessionToken.parse(array, curry);
+        return SessionToken.parse(array);
     }
   }
 
diff --git a/src/main/java/caosdb/server/accessControl/SessionToken.java b/src/main/java/caosdb/server/accessControl/SessionToken.java
index 5f6753afba662dc8db1b1aab539a78ff36585fff..2e82e3553497e56e4578f45a7768a9f7a5c71b77 100644
--- a/src/main/java/caosdb/server/accessControl/SessionToken.java
+++ b/src/main/java/caosdb/server/accessControl/SessionToken.java
@@ -34,25 +34,23 @@ public class SessionToken extends SelfValidatingAuthenticationToken {
       final long date,
       final long timeout,
       final String salt,
-      final String curry,
       final String checksum,
       final String[] permissions,
       final String[] roles) {
-    super(principal, date, timeout, salt, curry, checksum, permissions, roles);
+    super(principal, date, timeout, salt, checksum, permissions, roles);
   }
 
   public SessionToken(
       final Principal principal,
       final long timeout,
-      final String curry,
       final String[] permissions,
       final String[] roles) {
-    super(principal, timeout, curry, permissions, roles);
+    super(principal, timeout, permissions, roles);
   }
 
   private static final long serialVersionUID = 5887135104218573761L;
 
-  public static SessionToken parse(final Object[] array, final String curry) {
+  public static SessionToken parse(final Object[] array) {
     final Principal principal = new Principal((String) array[1], (String) array[2]);
     final String[] roles = toStringArray((Object[]) array[3]);
     final String[] permissions = toStringArray((Object[]) array[4]);
@@ -60,21 +58,18 @@ public class SessionToken extends SelfValidatingAuthenticationToken {
     final long timeout = (Long) array[6];
     final String salt = (String) array[7];
     final String checksum = (String) array[8];
-    return new SessionToken(principal, date, timeout, salt, curry, checksum, permissions, roles);
+    return new SessionToken(principal, date, timeout, salt, checksum, permissions, roles);
   }
 
   private static SessionToken generate(
-      final Principal principal,
-      final String curry,
-      final String[] permissions,
-      final String[] roles) {
+      final Principal principal, final String[] permissions, final String[] roles) {
     int timeout =
         Integer.parseInt(CaosDBServer.getServerProperty(ServerProperties.KEY_SESSION_TIMEOUT_MS));
 
-    return new SessionToken(principal, timeout, curry, permissions, roles);
+    return new SessionToken(principal, timeout, permissions, roles);
   }
 
-  public static SessionToken generate(Subject subject, String curry) {
+  public static SessionToken generate(Subject subject) {
     String[] permissions = new String[] {};
     String[] roles = new String[] {};
     if (subject.getPrincipal() instanceof SelfValidatingAuthenticationToken) {
@@ -83,7 +78,7 @@ public class SessionToken extends SelfValidatingAuthenticationToken {
       permissions = p.getPermissions().toArray(permissions);
       roles = p.getRoles().toArray(roles);
     }
-    return generate((Principal) subject.getPrincipal(), curry, permissions, roles);
+    return generate((Principal) subject.getPrincipal(), permissions, roles);
   }
 
   @Override
@@ -98,7 +93,6 @@ public class SessionToken extends SelfValidatingAuthenticationToken {
         this.date,
         this.timeout,
         this.salt,
-        this.curry,
         calcChecksum((Object[]) this.permissions),
         calcChecksum((Object[]) this.roles),
         pepper);
diff --git a/src/main/java/caosdb/server/permissions/EntityACL.java b/src/main/java/caosdb/server/permissions/EntityACL.java
index 426edaba7ca9ab49cbefedcd58d2c9a265b85ed0..e0bfcf9243eb436f9af0d6a3bacfabb79984538c 100644
--- a/src/main/java/caosdb/server/permissions/EntityACL.java
+++ b/src/main/java/caosdb/server/permissions/EntityACL.java
@@ -92,7 +92,11 @@ public class EntityACL {
   }
 
   public static final EntityACL getOwnerACLFor(final Subject subject) {
-    if (AuthenticationUtils.isAnonymous(subject)) {
+    // TODO handle the case where a valid non-guest user (e.g. me@PAM,
+    // you@CaosDB) is (just temporarily) authenticated via a
+    // OneTimeAuthenticationToken
+    if (AuthenticationUtils.isAnonymous(subject)
+        || AuthenticationUtils.isFromOneTimeTokenRealm(subject)) {
       return new EntityACLFactory().create();
     }
     return getOwnerACLFor((Principal) subject.getPrincipal());
diff --git a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java
index 1d87c4608e7be3ace4aca09eff4d5e0621cc6b9f..d7897450b2caaa7a70f20ead02ed1bb0c67e192d 100644
--- a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java
+++ b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java
@@ -245,8 +245,10 @@ public abstract class AbstractCaosDBServerResource extends ServerResource {
    * @param userInfo
    */
   private void addNameAndRealm(Element userInfo, Subject user) {
-    userInfo.setAttribute("username", ((Principal) user.getPrincipal()).getUsername());
-    userInfo.setAttribute("realm", ((Principal) user.getPrincipal()).getRealm());
+    if (!AuthenticationUtils.isAnonymous((Principal) user.getPrincipal())) {
+      userInfo.setAttribute("username", ((Principal) user.getPrincipal()).getUsername());
+      userInfo.setAttribute("realm", ((Principal) user.getPrincipal()).getRealm());
+    }
   }
 
   @Get
diff --git a/src/main/java/caosdb/server/resource/ScriptingResource.java b/src/main/java/caosdb/server/resource/ScriptingResource.java
index 715892b0e76c124947ea917d8625b5d2256a2caa..d3827b4544beb16fd9bbaf37dad795be0e36b129 100644
--- a/src/main/java/caosdb/server/resource/ScriptingResource.java
+++ b/src/main/java/caosdb/server/resource/ScriptingResource.java
@@ -210,11 +210,11 @@ public class ScriptingResource extends AbstractCaosDBServerResource {
 
   public Object generateAuthToken(String call) {
     String purpose = "scripting:" + call;
-    Object authtoken = OneTimeAuthenticationToken.generateForPurpose(purpose, getUser(), null);
+    Object authtoken = OneTimeAuthenticationToken.generateForPurpose(purpose, getUser());
     if (authtoken != null || isAnonymous()) {
       return authtoken;
     }
-    return SessionToken.generate(getUser(), null);
+    return SessionToken.generate(getUser());
   }
 
   public void checkExecutionPermission(Subject user, String call) {
diff --git a/src/main/java/caosdb/server/utils/Utils.java b/src/main/java/caosdb/server/utils/Utils.java
index 3be0ea6e9c1ad613a04bb8f5ad5c7b7ee13e2f88..d5bb0903de581597b23261e0bb87caa1e9ea7829 100644
--- a/src/main/java/caosdb/server/utils/Utils.java
+++ b/src/main/java/caosdb/server/utils/Utils.java
@@ -199,6 +199,7 @@ public class Utils {
     srand.nextBytes(bytes);
 
     // Encode to nice letters
+    // TODO use StringBuilder and iterate over filename.charArray
     String filename = (new Base32()).encodeToString(bytes);
     filename = filename.replaceAll("=+", "");
 
diff --git a/src/test/java/caosdb/server/authentication/AuthTokenTest.java b/src/test/java/caosdb/server/authentication/AuthTokenTest.java
index 504c402983c967366a0ec2ff28efc46f2c1f91df..088d8d0e8de1e062ce02f674d5ac56ff902e5631 100644
--- a/src/test/java/caosdb/server/authentication/AuthTokenTest.java
+++ b/src/test/java/caosdb/server/authentication/AuthTokenTest.java
@@ -85,14 +85,13 @@ public class AuthTokenTest {
 
   @Test
   public void testSessionToken() throws InterruptedException {
-    final String curry = "somecurry";
+    // Token 1 - wrong checksum, not expired
     final SessionToken t1 =
         new SessionToken(
             new Principal("somerealm", "someuser1"),
             System.currentTimeMillis(),
             60000,
             "345sdf56sdf",
-            curry,
             "wrong checksum",
             null,
             null);
@@ -100,34 +99,16 @@ public class AuthTokenTest {
     Assert.assertFalse(t1.isHashValid());
     Assert.assertFalse(t1.isValid());
 
-    final SessionToken t2 =
-        new SessionToken(
-            new Principal("somerealm", "someuser1"),
-            System.currentTimeMillis(),
-            60000,
-            "345sdf56sdf",
-            null,
-            "wrong checksum",
-            null,
-            null);
-    Assert.assertFalse(t2.isExpired());
-    Assert.assertFalse(t2.isHashValid());
-    Assert.assertFalse(t2.isValid());
-
+    // Token 3 - correct checksum, not expired
     final SessionToken t3 =
-        new SessionToken(new Principal("somerealm", "someuser2"), 60000, curry, null, null);
+        new SessionToken(new Principal("somerealm", "someuser2"), 60000, null, null);
     Assert.assertFalse(t3.isExpired());
     Assert.assertTrue(t3.isHashValid());
     Assert.assertTrue(t3.isValid());
 
-    final SessionToken t4 =
-        new SessionToken(new Principal("somerealm", "someuser2"), 60000, null, null, null);
-    Assert.assertFalse(t4.isExpired());
-    Assert.assertTrue(t4.isHashValid());
-    Assert.assertTrue(t4.isValid());
-
+    // Token 5 - correct checksum, soon to be expired
     final SessionToken t5 =
-        new SessionToken(new Principal("somerealm", "someuser3"), 2000, curry, null, null);
+        new SessionToken(new Principal("somerealm", "someuser3"), 2000, null, null);
     Assert.assertFalse(t5.isExpired());
     Assert.assertTrue(t5.isHashValid());
     Assert.assertTrue(t5.isValid());
@@ -137,96 +118,45 @@ public class AuthTokenTest {
     Assert.assertTrue(t5.isHashValid());
     Assert.assertFalse(t5.isValid());
 
+    // Token 6 - correct checksum, immediately expired
     final SessionToken t6 =
-        new SessionToken(new Principal("somerealm", "someuser3"), 0, null, null, null);
+        new SessionToken(new Principal("somerealm", "someuser3"), 0, null, null);
     Assert.assertTrue(t6.isExpired());
     Assert.assertTrue(t6.isHashValid());
     Assert.assertFalse(t6.isValid());
 
-    Assert.assertEquals(t1.toString(), SessionToken.parse(t1.toString(), curry).toString());
-    Assert.assertEquals(t2.toString(), SessionToken.parse(t2.toString(), curry).toString());
-    Assert.assertEquals(t3.toString(), SessionToken.parse(t3.toString(), curry).toString());
-    Assert.assertEquals(t4.toString(), SessionToken.parse(t4.toString(), curry).toString());
-    Assert.assertEquals(t5.toString(), SessionToken.parse(t5.toString(), curry).toString());
-    Assert.assertEquals(t6.toString(), SessionToken.parse(t6.toString(), curry).toString());
-    Assert.assertEquals(t1.toString(), SessionToken.parse(t1.toString(), null).toString());
-    Assert.assertEquals(t2.toString(), SessionToken.parse(t2.toString(), null).toString());
-    Assert.assertEquals(t3.toString(), SessionToken.parse(t3.toString(), null).toString());
-    Assert.assertEquals(t4.toString(), SessionToken.parse(t4.toString(), null).toString());
-    Assert.assertEquals(t5.toString(), SessionToken.parse(t5.toString(), null).toString());
-    Assert.assertEquals(t6.toString(), SessionToken.parse(t6.toString(), null).toString());
-
-    Assert.assertFalse(SessionToken.parse(t1.toString(), curry).isHashValid());
-    Assert.assertFalse(SessionToken.parse(t2.toString(), null).isHashValid());
-    Assert.assertTrue(SessionToken.parse(t3.toString(), curry).isHashValid());
-    Assert.assertTrue(SessionToken.parse(t4.toString(), null).isHashValid());
-    Assert.assertTrue(SessionToken.parse(t5.toString(), curry).isHashValid());
-    Assert.assertTrue(SessionToken.parse(t6.toString(), null).isHashValid());
-    Assert.assertFalse(SessionToken.parse(t1.toString(), null).isHashValid());
-    Assert.assertFalse(SessionToken.parse(t2.toString(), curry).isHashValid());
-    Assert.assertFalse(SessionToken.parse(t3.toString(), null).isHashValid());
-    Assert.assertFalse(SessionToken.parse(t4.toString(), curry).isHashValid());
-    Assert.assertFalse(SessionToken.parse(t5.toString(), null).isHashValid());
-    Assert.assertFalse(SessionToken.parse(t6.toString(), curry).isHashValid());
+    Assert.assertEquals(t1.toString(), SessionToken.parse(t1.toString()).toString());
+    Assert.assertEquals(t3.toString(), SessionToken.parse(t3.toString()).toString());
+    Assert.assertEquals(t5.toString(), SessionToken.parse(t5.toString()).toString());
+    Assert.assertEquals(t6.toString(), SessionToken.parse(t6.toString()).toString());
+
+    Assert.assertFalse(SessionToken.parse(t1.toString()).isHashValid());
+    Assert.assertTrue(SessionToken.parse(t3.toString()).isHashValid());
+    Assert.assertTrue(SessionToken.parse(t5.toString()).isHashValid());
+    Assert.assertTrue(SessionToken.parse(t6.toString()).isHashValid());
 
     Assert.assertFalse(
         AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t4), null)
-            .isExpired());
-    Assert.assertTrue(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t4), null)
-            .isHashValid());
-    Assert.assertTrue(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t4), null)
-            .isValid());
-    Assert.assertFalse(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t4), curry)
-            .isExpired());
-    Assert.assertFalse(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t4), curry)
-            .isHashValid());
-    Assert.assertFalse(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t4), curry)
-            .isValid());
-    Assert.assertFalse(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t3), null)
-            .isExpired());
-    Assert.assertFalse(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t3), null)
-            .isHashValid());
-    Assert.assertFalse(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t3), null)
-            .isValid());
-    Assert.assertFalse(
-        AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t3), curry)
+                AuthenticationUtils.createSessionTokenCookie(t3))
             .isExpired());
     Assert.assertTrue(
         AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t3), curry)
+                AuthenticationUtils.createSessionTokenCookie(t3))
             .isHashValid());
     Assert.assertTrue(
         AuthenticationUtils.parseSessionTokenCookie(
-                AuthenticationUtils.createSessionTokenCookie(t3), curry)
+                AuthenticationUtils.createSessionTokenCookie(t3))
             .isValid());
+
+    // TODO parse invalid tokens
   }
 
   @Test
   public void testOneTimeTokenSerialization() {
-    final String curry = null;
     final OneTimeAuthenticationToken t1 =
         new OneTimeAuthenticationToken(
             new Principal("somerealm", "someuser"),
             60000,
-            curry,
             new String[] {"permissions"},
             new String[] {"roles"},
             1L,
@@ -237,7 +167,7 @@ public class AuthTokenTest {
     Assert.assertTrue(t1.isValid());
 
     String serialized = t1.toString();
-    SelfValidatingAuthenticationToken parsed = OneTimeAuthenticationToken.parse(serialized, curry);
+    SelfValidatingAuthenticationToken parsed = OneTimeAuthenticationToken.parse(serialized);
 
     Assert.assertEquals(t1, parsed);
     Assert.assertEquals(serialized, parsed.toString());
@@ -250,12 +180,10 @@ public class AuthTokenTest {
 
   @Test(expected = AuthenticationException.class)
   public void testOneTimeTokenConsume() {
-    final String curry = null;
     final OneTimeAuthenticationToken t1 =
         new OneTimeAuthenticationToken(
             new Principal("somerealm", "someuser"),
             60000,
-            curry,
             new String[] {"permissions"},
             new String[] {"roles"},
             3L,
@@ -278,12 +206,10 @@ public class AuthTokenTest {
 
   @Test(expected = AuthenticationException.class)
   public void testOneTimeTokenConsumeByParsing() {
-    final String curry = null;
     final OneTimeAuthenticationToken t1 =
         new OneTimeAuthenticationToken(
             new Principal("somerealm", "someuser"),
             60000,
-            curry,
             new String[] {"permissions"},
             new String[] {"roles"},
             3L,
@@ -294,21 +220,18 @@ public class AuthTokenTest {
 
     String serialized = t1.toString();
     try {
-      SelfValidatingAuthenticationToken parsed1 =
-          OneTimeAuthenticationToken.parse(serialized, curry);
+      SelfValidatingAuthenticationToken parsed1 = OneTimeAuthenticationToken.parse(serialized);
       Assert.assertTrue(parsed1.isValid());
-      SelfValidatingAuthenticationToken parsed2 =
-          OneTimeAuthenticationToken.parse(serialized, curry);
+      SelfValidatingAuthenticationToken parsed2 = OneTimeAuthenticationToken.parse(serialized);
       Assert.assertTrue(parsed2.isValid());
-      SelfValidatingAuthenticationToken parsed3 =
-          OneTimeAuthenticationToken.parse(serialized, curry);
+      SelfValidatingAuthenticationToken parsed3 = OneTimeAuthenticationToken.parse(serialized);
       Assert.assertTrue(parsed3.isValid());
     } catch (AuthenticationException e) {
       Assert.fail(e.getMessage());
     }
 
     // throws
-    OneTimeAuthenticationToken.parse(serialized, curry);
+    OneTimeAuthenticationToken.parse(serialized);
     Assert.fail("4th parsing should throw");
   }
 
@@ -436,10 +359,12 @@ public class AuthTokenTest {
     Assert.assertTrue(tempFile.exists());
     try (BufferedReader reader = new BufferedReader(new FileReader(tempFile))) {
       OneTimeAuthenticationToken token =
-          (OneTimeAuthenticationToken)
-              SelfValidatingAuthenticationToken.parse(reader.readLine(), null);
+          (OneTimeAuthenticationToken) SelfValidatingAuthenticationToken.parse(reader.readLine());
       assertEquals("Token has anonymous username", "anonymous", token.getPrincipal().getUsername());
-      assertEquals("Token has anonymous realm", "anonymous", token.getPrincipal().getRealm());
+      assertEquals(
+          "Token has anonymous realm",
+          OneTimeAuthenticationToken.REALM_NAME,
+          token.getPrincipal().getRealm());
       assertArrayEquals(
           "Permissions array has been written and read",
           new String[] {"permission1"},
@@ -461,7 +386,7 @@ public class AuthTokenTest {
     anonymous.login(AnonymousAuthenticationToken.getInstance());
 
     OneTimeAuthenticationToken token =
-        OneTimeAuthenticationToken.generateForPurpose("for anonymous", anonymous, null);
+        OneTimeAuthenticationToken.generateForPurpose("for anonymous", anonymous);
     assertEquals("anonymous", token.getPrincipal().getUsername());
   }
 
@@ -471,8 +396,7 @@ public class AuthTokenTest {
     OneTimeAuthenticationToken token = OneTimeAuthenticationToken.generate(config);
 
     String serialized = token.toString();
-    SelfValidatingAuthenticationToken parsed =
-        SelfValidatingAuthenticationToken.parse(serialized, null);
+    SelfValidatingAuthenticationToken parsed = SelfValidatingAuthenticationToken.parse(serialized);
 
     SessionTokenRealm sessionTokenRealm = new SessionTokenRealm();
     Assert.assertTrue(sessionTokenRealm.supports(token));