diff --git a/src/main/java/caosdb/server/CaosAuthenticator.java b/src/main/java/caosdb/server/CaosAuthenticator.java
index 25f112aa52050a0b872b2ff83e95400ad4bd925e..9272b41ecf45158440da841415882ef5d7969d31 100644
--- a/src/main/java/caosdb/server/CaosAuthenticator.java
+++ b/src/main/java/caosdb/server/CaosAuthenticator.java
@@ -23,11 +23,10 @@
 package caosdb.server;
 
 import caosdb.server.accessControl.AuthenticationUtils;
-import caosdb.server.accessControl.OneTimeAuthenticationToken;
-import caosdb.server.accessControl.SessionToken;
 import caosdb.server.resource.DefaultResource;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationToken;
 import org.apache.shiro.subject.Subject;
 import org.restlet.Context;
 import org.restlet.Request;
@@ -48,12 +47,12 @@ public class CaosAuthenticator extends Authenticator {
   protected boolean authenticate(final Request request, final Response response) {
     final Subject subject = SecurityUtils.getSubject();
 
-    return attemptOneTimeTokenLogin(subject, request) || attemptSessionValidation(subject, request);
+    return attemptSessionValidation(subject, request);
   }
 
   private static boolean attemptSessionValidation(final Subject subject, final Request request) {
     try {
-      final SessionToken sessionToken =
+      final AuthenticationToken sessionToken =
           AuthenticationUtils.parseSessionTokenCookie(
               request.getCookies().getFirst(AuthenticationUtils.SESSION_TOKEN_COOKIE), null);
 
@@ -72,31 +71,6 @@ public class CaosAuthenticator extends Authenticator {
     return subject.isAuthenticated();
   }
 
-  private static boolean attemptOneTimeTokenLogin(final Subject subject, final Request request) {
-    try {
-      OneTimeAuthenticationToken oneTimeToken = null;
-
-      // try and parse from the query segment of the uri
-      oneTimeToken =
-          AuthenticationUtils.parseOneTimeTokenQuerySegment(
-              request.getResourceRef().getQueryAsForm().getFirstValue("AuthToken"), null);
-
-      // try and parse from cookie
-      if (oneTimeToken == null) {
-        oneTimeToken =
-            AuthenticationUtils.parseOneTimeTokenCookie(
-                request.getCookies().getFirst(AuthenticationUtils.ONE_TIME_TOKEN_COOKIE), null);
-      }
-
-      if (oneTimeToken != null) {
-        subject.login(oneTimeToken);
-      }
-    } catch (final AuthenticationException e) {
-      logger.info("LOGIN_FAILED", e);
-    }
-    return subject.isAuthenticated();
-  }
-
   @Override
   protected int unauthenticated(final Request request, final Response response) {
     final DefaultResource defaultResource =
diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java
index 21685533b1f8c3ded743caf9c9c890c1f715cf75..ca1e64feec699407b4e35f642522f599440184fd 100644
--- a/src/main/java/caosdb/server/CaosDBServer.java
+++ b/src/main/java/caosdb/server/CaosDBServer.java
@@ -24,8 +24,6 @@ import caosdb.server.accessControl.AuthenticationUtils;
 import caosdb.server.accessControl.CaosDBAuthorizingRealm;
 import caosdb.server.accessControl.CaosDBDefaultRealm;
 import caosdb.server.accessControl.OneTimeAuthenticationToken;
-import caosdb.server.accessControl.OneTimeTokenRealm;
-import caosdb.server.accessControl.Principal;
 import caosdb.server.accessControl.SessionToken;
 import caosdb.server.accessControl.SessionTokenRealm;
 import caosdb.server.database.BackendTransaction;
@@ -229,12 +227,11 @@ public class CaosDBServer extends Application {
     final Section mainSec = config.addSection("main");
     mainSec.put("CaosDB", CaosDBDefaultRealm.class.getCanonicalName());
     mainSec.put("SessionTokenValidator", SessionTokenRealm.class.getCanonicalName());
-    mainSec.put("OneTimeTokenValidator", OneTimeTokenRealm.class.getCanonicalName());
     mainSec.put("CaosDBAuthorizingRealm", CaosDBAuthorizingRealm.class.getCanonicalName());
     mainSec.put("AnonymousRealm", AnonymousRealm.class.getCanonicalName());
     mainSec.put(
         "securityManager.realms",
-        "$CaosDB, $SessionTokenValidator, $OneTimeTokenValidator, $CaosDBAuthorizingRealm, $AnonymousRealm");
+        "$CaosDB, $SessionTokenValidator, $CaosDBAuthorizingRealm, $AnonymousRealm");
 
     // disable shiro's default session management. We have quasi-stateless
     // sessions
@@ -564,8 +561,7 @@ public class CaosDBServer extends Application {
             final Subject subject = SecurityUtils.getSubject();
             if (subject.isAuthenticated()
                 && subject.getPrincipal() != AuthenticationUtils.ANONYMOUS_USER.getPrincipal()) {
-              final SessionToken sessionToken =
-                  SessionToken.generate((Principal) subject.getPrincipal(), null);
+              final SessionToken sessionToken = SessionToken.generate(subject, null);
 
               // set session token cookie (httpOnly, secure cookie which
               // is used to recognize a user session)
diff --git a/src/main/java/caosdb/server/accessControl/AnonymousAuthenticationToken.java b/src/main/java/caosdb/server/accessControl/AnonymousAuthenticationToken.java
index cd3f86f61eb66759b3eb7d0c91c29dc23637000b..f3f62af2af319d342977a7fe2524b353f8e7adab 100644
--- a/src/main/java/caosdb/server/accessControl/AnonymousAuthenticationToken.java
+++ b/src/main/java/caosdb/server/accessControl/AnonymousAuthenticationToken.java
@@ -28,7 +28,7 @@ public class AnonymousAuthenticationToken implements AuthenticationToken {
 
   private static final long serialVersionUID = 1424325396819592888L;
   private static final AnonymousAuthenticationToken INSTANCE = new AnonymousAuthenticationToken();
-  public static final Object PRINCIPAL = new Object();
+  public static final Principal PRINCIPAL = new Principal("anonymous", "anonymous");
 
   private AnonymousAuthenticationToken() {}
 
@@ -37,7 +37,7 @@ public class AnonymousAuthenticationToken implements AuthenticationToken {
   }
 
   @Override
-  public Object getPrincipal() {
+  public Principal getPrincipal() {
     return PRINCIPAL;
   }
 
diff --git a/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java b/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java
index 6e0fd5370ffcc2435067d68b3f2f810819ae9fbb..4a52c50196cd61242fd15e94409e8581eabda12a 100644
--- a/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java
+++ b/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java
@@ -35,6 +35,7 @@ import java.sql.Timestamp;
 import java.util.Collection;
 import java.util.LinkedList;
 import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.subject.Subject;
 import org.restlet.data.Cookie;
 import org.restlet.data.CookieSetting;
 import org.slf4j.Logger;
@@ -87,11 +88,8 @@ public class AuthenticationUtils {
     return null;
   }
 
-  public static CookieSetting createOneTimeTokenCookie(final OneTimeAuthenticationToken token) {
-    return createTokenCookie(AuthenticationUtils.ONE_TIME_TOKEN_COOKIE, token);
-  }
-
-  public static CookieSetting createSessionTokenCookie(final SessionToken token) {
+  public static CookieSetting createSessionTokenCookie(
+      final SelfValidatingAuthenticationToken token) {
     return createTokenCookie(AuthenticationUtils.SESSION_TOKEN_COOKIE, token);
   }
 
@@ -103,12 +101,13 @@ public class AuthenticationUtils {
    * @return A new SessionToken
    * @see {@link AuthenticationUtils#createSessionTokenCookie(SessionToken)}, {@link SessionToken}
    */
-  public static SessionToken parseSessionTokenCookie(final Cookie cookie, final String curry) {
+  public static SelfValidatingAuthenticationToken parseSessionTokenCookie(
+      final Cookie cookie, final String curry) {
     if (cookie != null) {
       final String tokenString = URLDecodeWithUTF8(cookie.getValue());
       if (tokenString != null && !tokenString.equals("")) {
         try {
-          return SessionToken.parse(tokenString, curry);
+          return SelfValidatingAuthenticationToken.parse(tokenString, curry);
         } catch (final Exception e) {
           logger.warn("AUTHTOKEN_PARSING_FAILED", e);
         }
@@ -117,34 +116,6 @@ public class AuthenticationUtils {
     return null;
   }
 
-  private static OneTimeAuthenticationToken parseOneTimeToken(
-      final String tokenString, final String curry) {
-    if (tokenString != null && !tokenString.equals("")) {
-      try {
-        return OneTimeAuthenticationToken.parse(tokenString, curry);
-      } catch (final Exception e) {
-        logger.warn("AUTHTOKEN_PARSING_FAILED", e);
-      }
-    }
-    return null;
-  }
-
-  public static OneTimeAuthenticationToken parseOneTimeTokenQuerySegment(
-      final String tokenString, final String curry) {
-    if (tokenString != null) {
-      return parseOneTimeToken(URLDecodeWithUTF8(tokenString), curry);
-    }
-    return null;
-  }
-
-  public static OneTimeAuthenticationToken parseOneTimeTokenCookie(
-      final Cookie cookie, final String curry) {
-    if (cookie != null) {
-      return parseOneTimeToken(URLDecodeWithUTF8(cookie.getValue()), curry);
-    }
-    return null;
-  }
-
   /**
    * Create a session timeout cookie. The value is a plain UTC timestamp which tells the user how
    * long his session will stay active. This cookie will be ignored by the server and carries only
@@ -180,6 +151,7 @@ public class AuthenticationUtils {
     return null;
   }
 
+  // TODO move
   public static boolean isResponsibleAgentExistent(final ResponsibleAgent agent) {
     // 1) check OWNER, OTHER
     if (Role.OTHER_ROLE.equals(agent) || Role.OWNER_ROLE.equals(agent)) {
@@ -227,4 +199,8 @@ public class AuthenticationUtils {
         false,
         false);
   }
+
+  public static Collection<String> getRoles(Subject user) {
+    return new CaosDBAuthorizingRealm().doGetAuthorizationInfo(user.getPrincipals()).getRoles();
+  }
 }
diff --git a/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java b/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java
index 5cfa425ac235405a0c861e54c9d97ae8ffab58f5..d715acf9c9cadebf9e5d7dde7b8ab3f3685fe231 100644
--- a/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java
+++ b/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java
@@ -22,9 +22,7 @@
  */
 package caosdb.server.accessControl;
 
-import com.google.common.base.Objects;
-import java.util.Arrays;
-import java.util.List;
+import java.util.Collection;
 import java.util.Set;
 import org.apache.shiro.authc.AuthenticationInfo;
 import org.apache.shiro.authc.AuthenticationToken;
@@ -32,100 +30,47 @@ import org.apache.shiro.authz.AuthorizationInfo;
 import org.apache.shiro.authz.SimpleAuthorizationInfo;
 import org.apache.shiro.realm.AuthorizingRealm;
 import org.apache.shiro.subject.PrincipalCollection;
-import org.apache.shiro.subject.SimplePrincipalCollection;
 
 public class CaosDBAuthorizingRealm extends AuthorizingRealm {
 
-  private static class PermissionPrincipalCollection extends SimplePrincipalCollection {
-
-    private final List<String> permissions;
-
-    public PermissionPrincipalCollection(
-        final PrincipalCollection principals, final String[] permissions) {
-      super(principals);
-      this.permissions = Arrays.asList(permissions);
-    }
-
-    private static final long serialVersionUID = 5585425107072564933L;
-
-    @Override
-    public boolean equals(final Object obj) {
-      if (obj == this) {
-        return true;
-      } else if (obj instanceof PermissionPrincipalCollection) {
-        final PermissionPrincipalCollection that = (PermissionPrincipalCollection) obj;
-        return Objects.equal(that.permissions, this.permissions) && super.equals(that);
-      } else {
-        return false;
-      }
-    }
+  private static final CaosDBRolePermissionResolver role_permission_resolver =
+      new CaosDBRolePermissionResolver();
 
-    @Override
-    public int hashCode() {
-      return super.hashCode() + 28 * this.permissions.hashCode();
-    }
+  public Collection<String> getSessionRoles(SelfValidatingAuthenticationToken token) {
+    return token.getRoles();
   }
 
-  static class PermissionAuthenticationInfo implements AuthenticationInfo {
-
-    private static final long serialVersionUID = -3714484164124767976L;
-    private final PermissionPrincipalCollection principalCollection;
-
-    public PermissionAuthenticationInfo(
-        final PrincipalCollection principals, final String... permissions) {
-      this.principalCollection = new PermissionPrincipalCollection(principals, permissions);
-    }
-
-    @Override
-    public PrincipalCollection getPrincipals() {
-      return this.principalCollection;
-    }
-
-    @Override
-    public Object getCredentials() {
-      return null;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-      if (obj == this) {
-        return true;
-      } else if (obj instanceof PermissionAuthenticationInfo) {
-        final PermissionAuthenticationInfo that = (PermissionAuthenticationInfo) obj;
-        return Objects.equal(that.principalCollection, this.principalCollection);
-      } else {
-        return false;
-      }
-    }
-
-    @Override
-    public int hashCode() {
-      return this.principalCollection.hashCode();
-    }
+  public Collection<String> getSessionPermissions(SelfValidatingAuthenticationToken token) {
+    return token.getPermissions();
   }
 
-  private static final CaosDBRolePermissionResolver role_permission_resolver =
-      new CaosDBRolePermissionResolver();
-
   @Override
   protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principals) {
-    if (principals instanceof PermissionPrincipalCollection) {
-      // the PrincialsCollection carries the permissions.
-      final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
-      info.addStringPermissions(((PermissionPrincipalCollection) principals).permissions);
-      return info;
-    }
-
     final SimpleAuthorizationInfo authzInfo = new SimpleAuthorizationInfo();
+    Object principal = principals.getPrimaryPrincipal();
+
+    if (principal instanceof SelfValidatingAuthenticationToken) {
+      Collection<String> sessionPermissions =
+          getSessionPermissions((SelfValidatingAuthenticationToken) principal);
+
+      Collection<String> sessionRoles =
+          getSessionRoles((SelfValidatingAuthenticationToken) principal);
+
+      authzInfo.addRoles(sessionRoles);
+      authzInfo.addStringPermissions(sessionPermissions);
+    }
 
     // find all roles which are associated with this principal in this
     // realm.
-    final Set<String> roles = UserSources.resolve(principals);
-    if (roles != null) {
-      authzInfo.setRoles(roles);
+    final Set<String> principalRoles =
+        UserSources.resolve((Principal) principals.getPrimaryPrincipal());
+    if (principalRoles != null) {
+      authzInfo.addRoles(principalRoles);
+    }
 
-      // find all permissions which are associated with these roles.
-      authzInfo.addObjectPermission(role_permission_resolver.resolvePermissionsInRole(roles));
+    if (authzInfo.getRoles() != null) {
+      authzInfo.addObjectPermission(
+          role_permission_resolver.resolvePermissionsInRole(authzInfo.getRoles()));
     }
 
     return authzInfo;
diff --git a/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java b/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java
index 0a0f71d654ec056e58b9d60f547e73d8624e2873..67e7be5e3171d4d967f7c83335e0512d8a8ac92e 100644
--- a/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java
+++ b/src/main/java/caosdb/server/accessControl/OneTimeAuthenticationToken.java
@@ -36,16 +36,11 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 import org.apache.shiro.subject.Subject;
 import org.eclipse.jetty.util.ajax.JSON;
 
 public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToken {
 
-  private static final transient String PEPPER = java.util.UUID.randomUUID().toString();
-  private final String[] permissions;
-  private String[] roles;
-
   public OneTimeAuthenticationToken(
       final Principal principal,
       final long date,
@@ -55,109 +50,38 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
       final String checksum,
       final String[] permissions,
       final String[] roles) {
-    super(principal, date, timeout, salt, curry, checksum);
-    this.permissions = permissions;
-    this.roles = roles;
+    super(principal, date, timeout, salt, curry, checksum, permissions, roles);
   }
 
   public OneTimeAuthenticationToken(
       final Principal principal,
-      final long date,
       final long timeout,
-      final String salt,
       final String curry,
       final String[] permissions,
       final String[] roles) {
-    this(
-        principal,
-        date,
-        timeout,
-        salt,
-        curry,
-        calcChecksum(
-            principal.getRealm(),
-            principal.getUsername(),
-            date,
-            timeout,
-            salt,
-            curry,
-            calcChecksum((Object[]) permissions),
-            calcChecksum((Object[]) roles),
-            PEPPER),
-        permissions,
-        roles);
+    super(principal, timeout, curry, permissions, roles);
   }
 
   private static final long serialVersionUID = -1072740888045267613L;
 
-  public String[] getPermissions() {
-    return this.permissions;
-  }
-
-  public String[] getRoles() {
-    return this.roles;
-  }
-
-  @Override
-  public String calcChecksum() {
-    return calcChecksum(
-        this.principal.getRealm(),
-        this.principal.getUsername(),
-        this.date,
-        this.timeout,
-        this.salt,
-        this.curry,
-        calcChecksum((Object[]) this.permissions),
-        calcChecksum((Object[]) this.roles),
-        PEPPER);
-  }
-
-  @Override
-  public String toString() {
-    return JSON.toString(
-        new Object[] {
-          this.principal.getRealm(),
-          this.principal.getUsername(),
-          this.date,
-          this.timeout,
-          this.salt,
-          this.permissions,
-          this.roles,
-          this.checksum
-        });
-  }
-
-  private static String[] toStringArray(final Object[] array) {
-    final String[] ret = new String[array.length];
-    for (int i = 0; i < ret.length; i++) {
-      ret[i] = (String) array[i];
-    }
-    return ret;
-  }
-
-  public static OneTimeAuthenticationToken parse(final String token, final String curry) {
-    final Object[] array = (Object[]) JSON.parse(token);
-    final Principal principal = new Principal((String) array[0], (String) array[1]);
-    final long date = (Long) array[2];
-    final long timeout = (Long) array[3];
-    final String salt = (String) array[4];
-    final String[] permissions = toStringArray((Object[]) array[5]);
-    final String[] roles = toStringArray((Object[]) array[6]);
-    final String checksum = (String) array[7];
+  public static OneTimeAuthenticationToken parse(final Object[] array, final String curry) {
+    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]);
+    final long date = (Long) array[5];
+    final long timeout = (Long) array[6];
+    final String salt = (String) array[7];
+    final String checksum = (String) array[8];
     return new OneTimeAuthenticationToken(
         principal, date, timeout, salt, curry, checksum, permissions, roles);
   }
 
-  public static OneTimeAuthenticationToken generate(
+  private static OneTimeAuthenticationToken generate(
       final Principal principal, final String curry, final String[] permissions, String[] roles) {
-    return new OneTimeAuthenticationToken(
-        principal,
-        System.currentTimeMillis(),
-        Long.parseLong(CaosDBServer.getServerProperty(ServerProperties.KEY_ACTIVATION_TIMEOUT_MS)),
-        UUID.randomUUID().toString(),
-        curry,
-        permissions,
-        roles);
+    int timeout =
+        Integer.parseInt(
+            CaosDBServer.getServerProperty(ServerProperties.KEY_ACTIVATION_TIMEOUT_MS));
+    return new OneTimeAuthenticationToken(principal, timeout, curry, permissions, roles);
   }
 
   public static List<Config> loadConfig(InputStream input) throws Exception {
@@ -184,7 +108,7 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
   }
 
   public static OneTimeAuthenticationToken generate(Config c) {
-    return generate(c, new Principal("anonymous", "anonymous"), null);
+    return generate(c, AnonymousAuthenticationToken.PRINCIPAL, null);
   }
 
   public static OneTimeAuthenticationToken generateForPurpose(
@@ -287,4 +211,35 @@ public class OneTimeAuthenticationToken extends SelfValidatingAuthenticationToke
       init(f);
     }
   }
+
+  @Override
+  public String calcChecksum(String pepper) {
+    return calcChecksum(
+        "O",
+        this.getRealm(),
+        this.getUsername(),
+        this.date,
+        this.timeout,
+        this.salt,
+        this.curry,
+        calcChecksum((Object[]) this.permissions),
+        calcChecksum((Object[]) this.roles),
+        pepper);
+  }
+
+  @Override
+  public String toString() {
+    return JSON.toString(
+        new Object[] {
+          "O",
+          this.getRealm(),
+          this.getUsername(),
+          this.roles,
+          this.permissions,
+          this.date,
+          this.timeout,
+          this.salt,
+          this.checksum
+        });
+  }
 }
diff --git a/src/main/java/caosdb/server/accessControl/OneTimeTokenRealm.java b/src/main/java/caosdb/server/accessControl/OneTimeTokenRealm.java
index 468a8d8d212ca5546f1940a4b3de38c1da50b3d8..1f7d4da4a45a75368fc0d76ae35ad06ad80da92e 100644
--- a/src/main/java/caosdb/server/accessControl/OneTimeTokenRealm.java
+++ b/src/main/java/caosdb/server/accessControl/OneTimeTokenRealm.java
@@ -1,53 +1,55 @@
-/*
- * ** header v3.0
- * This file is a part of the CaosDB Project.
- *
- * Copyright (C) 2018 Research Group Biomedical Physics,
- * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * ** end header
- */
-package caosdb.server.accessControl;
-
-import caosdb.server.accessControl.CaosDBAuthorizingRealm.PermissionAuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
-
-public class OneTimeTokenRealm extends SessionTokenRealm {
-
-  @Override
-  protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token)
-      throws AuthenticationException {
-
-    final AuthenticationInfo info = super.doGetAuthenticationInfo(token);
-    if (info != null) {
-      return new PermissionAuthenticationInfo(
-          info.getPrincipals(), ((OneTimeAuthenticationToken) token).getPermissions());
-    }
-
-    return null;
-  }
-
-  public OneTimeTokenRealm() {
-    setAuthenticationTokenClass(OneTimeAuthenticationToken.class);
-    setCredentialsMatcher(new AllowAllCredentialsMatcher());
-    setCachingEnabled(false);
-    setAuthenticationCachingEnabled(false);
-    // setAuthorizationCachingEnabled(false);
-  }
-}
+/// *
+// * ** header v3.0
+// * This file is a part of the CaosDB Project.
+// *
+// * Copyright (C) 2018 Research Group Biomedical Physics,
+// * Max-Planck-Institute for Dynamics and Self-Organization Göttingen
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU Affero General Public License as
+// * published by the Free Software Foundation, either version 3 of the
+// * License, or (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// * GNU Affero General Public License for more details.
+// *
+// * You should have received a copy of the GNU Affero General Public License
+// * along with this program. If not, see <https://www.gnu.org/licenses/>.
+// *
+// * ** end header
+// */
+// package caosdb.server.accessControl;
+//
+// import caosdb.server.accessControl.CaosDBAuthorizingRealm.PermissionAuthenticationInfo;
+// import org.apache.shiro.authc.AuthenticationException;
+// import org.apache.shiro.authc.AuthenticationInfo;
+// import org.apache.shiro.authc.AuthenticationToken;
+// import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
+//
+// public class OneTimeTokenRealm extends SessionTokenRealm {
+//
+//  @Override
+//  protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token)
+//      throws AuthenticationException {
+//
+//    final AuthenticationInfo info = super.doGetAuthenticationInfo(token);
+//    if (info != null) {
+//      return new PermissionAuthenticationInfo(
+//          info.getPrincipals(),
+//          ((OneTimeAuthenticationToken) token).getPermissions(),
+//          ((OneTimeAuthenticationToken) token).getRoles());
+//    }
+//
+//    return null;
+//  }
+//
+//  public OneTimeTokenRealm() {
+//    setAuthenticationTokenClass(OneTimeAuthenticationToken.class);
+//    setCredentialsMatcher(new AllowAllCredentialsMatcher());
+//    setCachingEnabled(false);
+//    setAuthenticationCachingEnabled(false);
+//    // setAuthorizationCachingEnabled(false);
+//  }
+// }
diff --git a/src/main/java/caosdb/server/accessControl/Principal.java b/src/main/java/caosdb/server/accessControl/Principal.java
index 3183d864bd5baecc4429cf22fc0ab3ca75d8ca15..6a95dd79eccd50c9358928909822af67056102db 100644
--- a/src/main/java/caosdb/server/accessControl/Principal.java
+++ b/src/main/java/caosdb/server/accessControl/Principal.java
@@ -47,6 +47,11 @@ public class Principal implements ResponsibleAgent {
     this(split[0], split[1]);
   }
 
+  public Principal(Principal principal) {
+    this.username = principal.username;
+    this.realm = principal.realm;
+  }
+
   public String getRealm() {
     return this.realm;
   }
diff --git a/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java b/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java
index 079f592ea7911f974bf4a64c9c5f1674e64a09a5..7d4cd846b5226e61856703c137310fd765643a4b 100644
--- a/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java
+++ b/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java
@@ -23,17 +23,35 @@
 package caosdb.server.accessControl;
 
 import caosdb.server.utils.Utils;
+import java.util.Arrays;
+import java.util.Collection;
 import org.apache.shiro.authc.AuthenticationToken;
+import org.eclipse.jetty.util.ajax.JSON;
 
-public abstract class SelfValidatingAuthenticationToken implements AuthenticationToken {
+public abstract class SelfValidatingAuthenticationToken extends Principal
+    implements AuthenticationToken {
 
+  protected static final transient String PEPPER = Utils.getUID();
   private static final long serialVersionUID = -7212039848895531161L;
   protected final long date;
   protected final long timeout;
   protected final String checksum;
-  protected final Principal principal;
   protected final String curry;
   protected final String salt;
+  protected final String[] permissions;
+  protected final String[] roles;
+
+  public Collection<String> getPermissions() {
+    return Arrays.asList(this.permissions);
+  }
+
+  public Collection<String> getRoles() {
+    return Arrays.asList(this.roles);
+  }
+
+  public static final String getFreshSalt() {
+    return Utils.getUID();
+  }
 
   public SelfValidatingAuthenticationToken(
       final Principal principal,
@@ -41,34 +59,59 @@ public abstract class SelfValidatingAuthenticationToken implements Authenticatio
       final long timeout,
       final String salt,
       final String curry,
-      final String checksum) {
-    this.date = date;
-    this.timeout = timeout;
-    this.principal = principal;
-    this.salt = salt;
-    this.curry = curry;
-    this.checksum = checksum;
+      final String checksum,
+      final String[] permissions,
+      final String[] roles) {
+    this(principal, date, timeout, salt, curry, permissions, roles, checksum, false);
   }
 
-  public SelfValidatingAuthenticationToken(
+  private SelfValidatingAuthenticationToken(
       final Principal principal,
       final long date,
       final long timeout,
       final String salt,
-      final String curry) {
+      final String curry,
+      final String[] permissions,
+      final String[] roles,
+      String checksum,
+      boolean calcChecksum) {
+    super(principal);
     this.date = date;
     this.timeout = timeout;
-    this.principal = principal;
     this.salt = salt;
     this.curry = curry;
-    this.checksum = calcChecksum();
+    this.permissions = permissions != null ? permissions : new String[] {};
+    this.roles = roles != null ? roles : new String[] {};
+    this.checksum = checksum == null && calcChecksum ? calcChecksum() : checksum;
   }
 
-  @Override
-  public Principal getPrincipal() {
-    return this.principal;
+  public SelfValidatingAuthenticationToken(
+      final Principal principal,
+      final long timeout,
+      final String curry,
+      final String[] permissions,
+      final String[] roles) {
+    this(
+        principal,
+        System.currentTimeMillis(),
+        timeout,
+        getFreshSalt(),
+        curry,
+        permissions,
+        roles,
+        null,
+        true);
+  }
+
+  public String calcChecksum() {
+    return calcChecksum(PEPPER);
   }
 
+  @Override
+  public abstract String toString();
+
+  public abstract String calcChecksum(String pepper);
+
   @Override
   public Object getCredentials() {
     return null;
@@ -95,8 +138,6 @@ public abstract class SelfValidatingAuthenticationToken implements Authenticatio
     return !isExpired() && isHashValid();
   }
 
-  public abstract String calcChecksum();
-
   protected static String calcChecksum(final Object... fields) {
     final StringBuilder sb = new StringBuilder();
     for (final Object field : fields) {
@@ -107,4 +148,27 @@ public abstract class SelfValidatingAuthenticationToken implements Authenticatio
     }
     return Utils.sha512(sb.toString(), null, 1);
   }
+
+  protected static String[] toStringArray(final Object[] array) {
+    final String[] ret = new String[array.length];
+    for (int i = 0; i < ret.length; i++) {
+      ret[i] = (String) array[i];
+    }
+    return ret;
+  }
+
+  public static SelfValidatingAuthenticationToken parse(String token, String curry) {
+    Object[] array = (Object[]) JSON.parse(token);
+    switch (array[0].toString()) {
+      case "O":
+        return OneTimeAuthenticationToken.parse(array, curry);
+      default:
+        return SessionToken.parse(array, curry);
+    }
+  }
+
+  @Override
+  public SelfValidatingAuthenticationToken getPrincipal() {
+    return this;
+  }
 }
diff --git a/src/main/java/caosdb/server/accessControl/SessionToken.java b/src/main/java/caosdb/server/accessControl/SessionToken.java
index 273bd50ba7c4ef89fecd0e2b9b8817acbf6d9efa..695e4639c065a2b0ee2d31f05e3dce36cf3a54d3 100644
--- a/src/main/java/caosdb/server/accessControl/SessionToken.java
+++ b/src/main/java/caosdb/server/accessControl/SessionToken.java
@@ -24,86 +24,96 @@ package caosdb.server.accessControl;
 
 import caosdb.server.CaosDBServer;
 import caosdb.server.ServerProperties;
+import org.apache.shiro.subject.Subject;
 import org.eclipse.jetty.util.ajax.JSON;
 
 public class SessionToken extends SelfValidatingAuthenticationToken {
 
-  /**
-   * Cryptographic pepper. Generated when class is loaded and used until the server reboots. Hence
-   * all SessionTokens invalidate when the server reboots.
-   */
-  private static final transient String PEPPER = java.util.UUID.randomUUID().toString();
-
-  public static final String SEP = ":";
-
   public SessionToken(
       final Principal principal,
       final long date,
       final long timeout,
       final String salt,
       final String curry,
-      final String checksum) {
-    super(principal, date, timeout, salt, curry, checksum);
+      final String checksum,
+      final String[] permissions,
+      final String[] roles) {
+    super(principal, date, timeout, salt, curry, checksum, permissions, roles);
   }
 
   public SessionToken(
       final Principal principal,
-      final long date,
       final long timeout,
-      final String salt,
-      final String curry) {
-    super(principal, date, timeout, salt, curry);
+      final String curry,
+      final String[] permissions,
+      final String[] roles) {
+    super(principal, timeout, curry, permissions, roles);
   }
 
   private static final long serialVersionUID = 5887135104218573761L;
 
+  public static SessionToken parse(final Object[] array, final String curry) {
+    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]);
+    final long date = (Long) array[5];
+    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);
+  }
+
+  private static SessionToken generate(
+      final Principal principal,
+      final String curry,
+      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);
+  }
+
+  public static SessionToken generate(Subject subject, String curry) {
+    String[] permissions = new String[] {};
+    String[] roles = new String[] {};
+    if (subject.getPrincipal() instanceof SelfValidatingAuthenticationToken) {
+      SelfValidatingAuthenticationToken p =
+          (SelfValidatingAuthenticationToken) subject.getPrincipal();
+      permissions = p.getPermissions().toArray(permissions);
+      roles = p.getRoles().toArray(roles);
+    }
+    return generate((Principal) subject.getPrincipal(), curry, permissions, roles);
+  }
+
   @Override
-  public String calcChecksum() {
+  public String calcChecksum(String pepper) {
     return calcChecksum(
+        "S",
+        this.getRealm(),
+        this.getUsername(),
         this.date,
         this.timeout,
-        this.principal.getRealm(),
-        this.principal.getUsername(),
-        PEPPER,
         this.salt,
-        this.curry);
+        this.curry,
+        calcChecksum((Object[]) this.permissions),
+        calcChecksum((Object[]) this.roles),
+        pepper);
   }
 
   @Override
   public String toString() {
     return JSON.toString(
         new Object[] {
-          this.principal.getRealm(),
-          this.principal.getUsername(),
+          "S",
+          this.getRealm(),
+          this.getUsername(),
+          this.roles,
+          this.permissions,
           this.date,
           this.timeout,
           this.salt,
           this.checksum
         });
   }
-
-  public static SessionToken parse(final String token, final String curry) {
-    final Object[] array = (Object[]) JSON.parse(token);
-    final Principal principal = new Principal((String) array[0], (String) array[1]);
-    final long date = (Long) array[2];
-    final long timeout = (Long) array[3];
-    final String salt = (String) array[4];
-    final String checksum = (String) array[5];
-    return new SessionToken(principal, date, timeout, salt, curry, checksum);
-  }
-
-  public static SessionToken generate(final Principal principal, final String curry) {
-    final SessionToken ret =
-        new SessionToken(
-            principal,
-            System.currentTimeMillis(),
-            Long.parseLong(
-                CaosDBServer.getServerProperty(ServerProperties.KEY_SESSION_TIMEOUT_MS).trim()),
-            java.util.UUID.randomUUID().toString(),
-            curry);
-    if (!ret.isValid()) {
-      throw new RuntimeException("SessionToken not valid!");
-    }
-    return ret;
-  }
 }
diff --git a/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java b/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java
index 6ee72d0295153051e5ad31a6fd0fa092ab53d6e3..ff7e59b6ea4575a3ad95264c4f3dfbbcde41b78b 100644
--- a/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java
+++ b/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java
@@ -37,7 +37,7 @@ public class SessionTokenRealm extends AuthenticatingRealm {
         (SelfValidatingAuthenticationToken) token;
 
     if (sessionToken.isValid()) {
-      return new SimpleAuthenticationInfo(sessionToken.getPrincipal(), null, getName());
+      return new SimpleAuthenticationInfo(sessionToken, null, getName());
     }
     return null;
   }
diff --git a/src/main/java/caosdb/server/accessControl/UserSources.java b/src/main/java/caosdb/server/accessControl/UserSources.java
index d0f707ebaaec8aa97e9b87d760fc0631cbd2f72a..b684570748412fa3cc8bea64c94a110726badac0 100644
--- a/src/main/java/caosdb/server/accessControl/UserSources.java
+++ b/src/main/java/caosdb/server/accessControl/UserSources.java
@@ -37,7 +37,6 @@ import java.util.HashSet;
 import java.util.Set;
 import org.apache.shiro.authc.AuthenticationException;
 import org.apache.shiro.config.Ini;
-import org.apache.shiro.subject.PrincipalCollection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -129,13 +128,16 @@ public class UserSources extends HashMap<String, UserSource> {
    * @return
    */
   public static Set<String> resolve(String realm, final String username) {
-
     if (realm == null) {
       realm = guessRealm(username);
     }
 
+    UserSource userSource = instance.get(realm);
+    if (userSource == null) {
+      return null;
+    }
     // find all roles that are associated with this principal in this realm
-    final Set<String> ret = instance.get(realm).resolveRolesForUsername(username);
+    final Set<String> ret = userSource.resolveRolesForUsername(username);
 
     return ret;
   }
@@ -168,16 +170,15 @@ public class UserSources extends HashMap<String, UserSource> {
     return instance.map.getSectionProperty(Ini.DEFAULT_SECTION_NAME, KEY_DEFAULT_REALM);
   }
 
-  public static Set<String> resolve(final PrincipalCollection principals) {
-    if (principals.getPrimaryPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal()) {
+  public static Set<String> resolve(final Principal principal) {
+    if (principal == AuthenticationUtils.ANONYMOUS_USER.getPrincipal()) {
       // anymous has one role
       Set<String> roles = new HashSet<>();
       roles.add(ANONYMOUS_ROLE);
       return roles;
     }
 
-    Principal primaryPrincipal = (Principal) principals.getPrimaryPrincipal();
-    return resolve(primaryPrincipal.getRealm(), primaryPrincipal.getUsername());
+    return resolve(principal.getRealm(), principal.getUsername());
   }
 
   public static boolean isRoleExisting(final String role) {
diff --git a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java
index ea4e65f0a60d72cb5da6cb03b2cec44848dbc3c6..013501a0f39b24638c27a162e24015c168f13f3e 100644
--- a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java
+++ b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java
@@ -29,7 +29,6 @@ import static java.net.URLDecoder.decode;
 import caosdb.server.CaosDBException;
 import caosdb.server.accessControl.AuthenticationUtils;
 import caosdb.server.accessControl.Principal;
-import caosdb.server.accessControl.UserSources;
 import caosdb.server.database.backend.implementation.MySQL.ConnectionException;
 import caosdb.server.entity.Message;
 import caosdb.server.utils.ServerMessages;
@@ -231,7 +230,7 @@ public abstract class AbstractCaosDBServerResource extends ServerResource {
    * @param user
    */
   private void addRoles(Element userInfo, Subject user) {
-    Collection<String> roles = UserSources.resolve(user.getPrincipals());
+    Collection<String> roles = AuthenticationUtils.getRoles(user);
     if (roles == null) return;
     Element rs = new Element("Roles");
     for (String role : roles) {
diff --git a/src/main/java/caosdb/server/resource/ScriptingResource.java b/src/main/java/caosdb/server/resource/ScriptingResource.java
index 75baec81a1641748fbf27e300e7d01cc37beb63d..68e2203e9e24a8332a3629db82dce09a0abc552e 100644
--- a/src/main/java/caosdb/server/resource/ScriptingResource.java
+++ b/src/main/java/caosdb/server/resource/ScriptingResource.java
@@ -26,7 +26,6 @@ package caosdb.server.resource;
 
 import caosdb.server.FileSystem;
 import caosdb.server.accessControl.OneTimeAuthenticationToken;
-import caosdb.server.accessControl.Principal;
 import caosdb.server.accessControl.SessionToken;
 import caosdb.server.accessControl.UserSources;
 import caosdb.server.entity.FileProperties;
@@ -215,7 +214,7 @@ public class ScriptingResource extends AbstractCaosDBServerResource {
     if (authtoken != null || isAnonymous()) {
       return authtoken;
     }
-    return SessionToken.generate((Principal) getUser().getPrincipal(), null);
+    return SessionToken.generate(getUser(), null);
   }
 
   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 6c48906a40fd299379e91446516a9c0325200f81..3be0ea6e9c1ad613a04bb8f5ad5c7b7ee13e2f88 100644
--- a/src/main/java/caosdb/server/utils/Utils.java
+++ b/src/main/java/caosdb/server/utils/Utils.java
@@ -33,7 +33,6 @@ import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.text.DecimalFormat;
-import java.util.Random;
 import java.util.Scanner;
 import java.util.regex.Pattern;
 import org.apache.commons.codec.binary.Base32;
@@ -45,9 +44,6 @@ import org.jdom2.output.XMLOutputter;
 /** Utility functions. */
 public class Utils {
 
-  /** Random number generator initialized with the system time and used for generating UIDs. */
-  private static Random rand = new Random(System.currentTimeMillis());
-
   /** Secure random number generator, for secret random numbers. */
   private static final SecureRandom srand = new SecureRandom();
 
@@ -185,9 +181,7 @@ public class Utils {
    * @return The UID as a String.
    */
   public static String getUID() {
-    synchronized (rand) {
-      return Long.toHexString(rand.nextLong()) + Long.toHexString(rand.nextLong());
-    }
+    return Long.toHexString(srand.nextLong()) + Long.toHexString(srand.nextLong());
   }
 
   /**
diff --git a/src/test/java/caosdb/server/authentication/AuthTokenTest.java b/src/test/java/caosdb/server/authentication/AuthTokenTest.java
index 288b405c6910eaf30aafb266383d11a4b8b4be35..442e7d2196cbac2691b0196b6830c780624f064f 100644
--- a/src/test/java/caosdb/server/authentication/AuthTokenTest.java
+++ b/src/test/java/caosdb/server/authentication/AuthTokenTest.java
@@ -26,17 +26,34 @@ import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 import caosdb.server.CaosDBServer;
+import caosdb.server.accessControl.AnonymousAuthenticationToken;
 import caosdb.server.accessControl.AuthenticationUtils;
 import caosdb.server.accessControl.OneTimeAuthenticationToken;
 import caosdb.server.accessControl.OneTimeAuthenticationToken.Config;
 import caosdb.server.accessControl.Principal;
+import caosdb.server.accessControl.SelfValidatingAuthenticationToken;
 import caosdb.server.accessControl.SessionToken;
+import caosdb.server.database.BackendTransaction;
+import caosdb.server.database.backend.interfaces.RetrievePasswordValidatorImpl;
+import caosdb.server.database.backend.interfaces.RetrievePermissionRulesImpl;
+import caosdb.server.database.backend.interfaces.RetrieveRoleImpl;
+import caosdb.server.database.backend.interfaces.RetrieveUserImpl;
+import caosdb.server.resource.TestScriptingResource.RetrievePasswordValidator;
+import caosdb.server.resource.TestScriptingResource.RetrievePermissionRules;
+import caosdb.server.resource.TestScriptingResource.RetrieveRole;
+import caosdb.server.resource.TestScriptingResource.RetrieveUser;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.Map;
 import org.apache.commons.io.input.CharSequenceInputStream;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.config.IniSecurityManagerFactory;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.Factory;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -48,6 +65,23 @@ public class AuthTokenTest {
     CaosDBServer.initServerProperties();
   }
 
+  @BeforeClass
+  public static void setupShiro() throws IOException {
+    BackendTransaction.setImpl(RetrieveRoleImpl.class, RetrieveRole.class);
+    BackendTransaction.setImpl(RetrievePermissionRulesImpl.class, RetrievePermissionRules.class);
+    BackendTransaction.setImpl(RetrieveUserImpl.class, RetrieveUser.class);
+    BackendTransaction.setImpl(
+        RetrievePasswordValidatorImpl.class, RetrievePasswordValidator.class);
+
+    CaosDBServer.initServerProperties();
+    Ini config = CaosDBServer.getShiroConfig();
+    final Factory<SecurityManager> factory = new IniSecurityManagerFactory(config);
+
+    final SecurityManager securityManager = factory.getInstance();
+
+    SecurityUtils.setSecurityManager(securityManager);
+  }
+
   @Test
   public void testSessionToken() throws InterruptedException {
     final String curry = "somecurry";
@@ -58,7 +92,9 @@ public class AuthTokenTest {
             60000,
             "345sdf56sdf",
             curry,
-            "wrong checksum");
+            "wrong checksum",
+            null,
+            null);
     Assert.assertFalse(t1.isExpired());
     Assert.assertFalse(t1.isHashValid());
     Assert.assertFalse(t1.isValid());
@@ -70,40 +106,27 @@ public class AuthTokenTest {
             60000,
             "345sdf56sdf",
             null,
-            "wrong checksum");
+            "wrong checksum",
+            null,
+            null);
     Assert.assertFalse(t2.isExpired());
     Assert.assertFalse(t2.isHashValid());
     Assert.assertFalse(t2.isValid());
 
     final SessionToken t3 =
-        new SessionToken(
-            new Principal("somerealm", "someuser2"),
-            System.currentTimeMillis(),
-            60000,
-            "72723gsdg",
-            curry);
+        new SessionToken(new Principal("somerealm", "someuser2"), 60000, curry, null, null);
     Assert.assertFalse(t3.isExpired());
     Assert.assertTrue(t3.isHashValid());
     Assert.assertTrue(t3.isValid());
 
     final SessionToken t4 =
-        new SessionToken(
-            new Principal("somerealm", "someuser2"),
-            System.currentTimeMillis(),
-            60000,
-            "72723gsdg",
-            null);
+        new SessionToken(new Principal("somerealm", "someuser2"), 60000, null, null, null);
     Assert.assertFalse(t4.isExpired());
     Assert.assertTrue(t4.isHashValid());
     Assert.assertTrue(t4.isValid());
 
     final SessionToken t5 =
-        new SessionToken(
-            new Principal("somerealm", "someuser3"),
-            System.currentTimeMillis(),
-            2000,
-            "23sdfsg34",
-            curry);
+        new SessionToken(new Principal("somerealm", "someuser3"), 2000, curry, null, null);
     Assert.assertFalse(t5.isExpired());
     Assert.assertTrue(t5.isHashValid());
     Assert.assertTrue(t5.isValid());
@@ -114,12 +137,7 @@ public class AuthTokenTest {
     Assert.assertFalse(t5.isValid());
 
     final SessionToken t6 =
-        new SessionToken(
-            new Principal("somerealm", "someuser3"),
-            System.currentTimeMillis(),
-            0,
-            "23sdfsg34",
-            null);
+        new SessionToken(new Principal("somerealm", "someuser3"), 0, null, null, null);
     Assert.assertTrue(t6.isExpired());
     Assert.assertTrue(t6.isHashValid());
     Assert.assertFalse(t6.isValid());
@@ -206,9 +224,7 @@ public class AuthTokenTest {
     final OneTimeAuthenticationToken t1 =
         new OneTimeAuthenticationToken(
             new Principal("somerealm", "someuser"),
-            System.currentTimeMillis(),
-            60000L,
-            "sdfh37456sd",
+            60000,
             curry,
             new String[] {"permissions"},
             new String[] {"roles"});
@@ -307,13 +323,33 @@ public class AuthTokenTest {
     OneTimeAuthenticationToken.init(new CharSequenceInputStream(testYaml, "utf-8"));
     Assert.assertTrue(tempFile.exists());
     try (BufferedReader reader = new BufferedReader(new FileReader(tempFile))) {
-      OneTimeAuthenticationToken token = OneTimeAuthenticationToken.parse(reader.readLine(), null);
+      OneTimeAuthenticationToken token =
+          (OneTimeAuthenticationToken)
+              SelfValidatingAuthenticationToken.parse(reader.readLine(), null);
       assertEquals("Token has anonymous username", "anonymous", token.getPrincipal().getUsername());
       assertEquals("Token has anonymous realm", "anonymous", token.getPrincipal().getRealm());
       assertArrayEquals(
           "Permissions array has been written and read",
           new String[] {"permission1"},
-          token.getPermissions());
+          token.getPermissions().toArray());
     }
   }
+
+  @Test
+  public void testOneTimeTokenForAnonymous() throws Exception {
+    StringBuilder testYaml = new StringBuilder();
+    testYaml.append("purpose: for anonymous\n");
+    testYaml.append("roles: [ role1 ]\n");
+    testYaml.append("permissions:\n");
+    testYaml.append("  - permission1\n");
+
+    OneTimeAuthenticationToken.init(new CharSequenceInputStream(testYaml, "utf-8"));
+
+    Subject anonymous = SecurityUtils.getSubject();
+    anonymous.login(AnonymousAuthenticationToken.getInstance());
+
+    OneTimeAuthenticationToken token =
+        OneTimeAuthenticationToken.generateForPurpose("for anonymous", anonymous, null);
+    assertEquals("anonymous", token.getPrincipal().getUsername());
+  }
 }
diff --git a/src/test/java/caosdb/server/resource/TestScriptingResource.java b/src/test/java/caosdb/server/resource/TestScriptingResource.java
index b9797eb85ef779a2b957f65a5c96b56787d48421..ddf915fb2bc8f9401c630339b274404ab37545af 100644
--- a/src/test/java/caosdb/server/resource/TestScriptingResource.java
+++ b/src/test/java/caosdb/server/resource/TestScriptingResource.java
@@ -29,7 +29,6 @@ import caosdb.server.accessControl.AuthenticationUtils;
 import caosdb.server.accessControl.CredentialsValidator;
 import caosdb.server.accessControl.Principal;
 import caosdb.server.accessControl.Role;
-import caosdb.server.accessControl.SessionToken;
 import caosdb.server.database.BackendTransaction;
 import caosdb.server.database.access.Access;
 import caosdb.server.database.backend.interfaces.RetrievePasswordValidatorImpl;
@@ -201,12 +200,6 @@ public class TestScriptingResource {
 
   @Test
   public void testUnsupportedMediaType() {
-    Subject user = SecurityUtils.getSubject();
-    if (user.isAuthenticated()) {
-      user.logout();
-    }
-    SessionToken t = SessionToken.generate(new Principal("CaosDB", "user"), null);
-    user.login(t);
     Representation entity = new StringRepresentation("asdf");
     entity.setMediaType(MediaType.TEXT_ALL);
     Request request = new Request(Method.POST, "../test", entity);