diff --git a/regapp-idty/src/main/java/edu/kit/scc/webreg/service/attribute/release/AttributeBuilder.java b/regapp-idty/src/main/java/edu/kit/scc/webreg/service/attribute/release/AttributeBuilder.java
index 998cf37f2c890e5c57ab15d7baed1ed85ee3cb89..7f4321e729e996b44449a54bbf3d217f9ab90543 100644
--- a/regapp-idty/src/main/java/edu/kit/scc/webreg/service/attribute/release/AttributeBuilder.java
+++ b/regapp-idty/src/main/java/edu/kit/scc/webreg/service/attribute/release/AttributeBuilder.java
@@ -67,6 +67,10 @@ public class AttributeBuilder {
 		setStringListValue(attributeRelease, name, attributeResolver.resolveStringListValue(identity, name));
 	}
 
+	public void addStringListAttribute(AttributeReleaseEntity attributeRelease, String name, List<String> stringList) {
+		setStringListValue(attributeRelease, name, stringList);
+	}
+
 	public void deleteValue(ValueEntity value) {
 		value.getAttributeRelease().setChanged(true);
 		value.getAttributeRelease().getValues().remove(value);
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthResponse.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1930221d16e6dbdccc45799a0bf1e3eb16de3a3
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthResponse.java
@@ -0,0 +1,51 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFAAuthResponse implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String version;
+	
+	@JsonProperty("jsonrpc")
+	private String jsonRpc;
+	
+	private EduMFAAuthResult result;
+	
+	private Integer id;
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getJsonRpc() {
+		return jsonRpc;
+	}
+	
+	public void setJsonRpc(String jsonRpc) {
+		this.jsonRpc = jsonRpc;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public EduMFAAuthResult getResult() {
+		return result;
+	}
+
+	public void setResult(EduMFAAuthResult result) {
+		this.result = result;
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthResult.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdb54cba0001dd3907060ab4b9e10f957531bba9
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthResult.java
@@ -0,0 +1,27 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAAuthResult implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+	
+	private boolean status;
+	private EduMFAAuthTokenValue value;
+
+	public boolean isStatus() {
+		return status;
+	}
+
+	public void setStatus(boolean status) {
+		this.status = status;
+	}
+
+	public EduMFAAuthTokenValue getValue() {
+		return value;
+	}
+
+	public void setValue(EduMFAAuthTokenValue value) {
+		this.value = value;
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthTokenValue.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthTokenValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..e328dc1ab32dc281730435054b4deebaa2fa631c
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAAuthTokenValue.java
@@ -0,0 +1,18 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAAuthTokenValue implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+	
+	private String token;
+
+	public String getToken() {
+		return token;
+	}
+
+	public void setToken(String token) {
+		this.token = token;
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAConnection.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAConnection.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbc2e51acc6411e1816e8db3bb8edf369d1fbfec
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAConnection.java
@@ -0,0 +1,523 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpHost;
+import org.apache.http.NameValuePair;
+import org.apache.http.ParseException;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.TrustAllStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import edu.kit.scc.webreg.service.twofa.TwoFaException;
+
+public class EduMFAConnection {
+
+	private static final Logger logger = LoggerFactory.getLogger(EduMFAConnection.class);
+	
+	private Map<String, String> configMap;
+
+	private EduMFAResultParser resultParser;
+	
+	private URI uri;
+	private HttpHost targetHost;
+	private RequestConfig config;
+	private CloseableHttpClient httpClient;
+	private HttpClientContext context;
+	
+	private String adminUsername, adminPassword, adminSession;
+	
+	public EduMFAConnection(Map<String, String> configMap) throws TwoFaException {
+		super();
+		this.configMap = configMap;
+		resultParser = new EduMFAResultParser();
+		init();
+	}
+	
+	public void close() {
+		try {
+			httpClient.close();
+		} catch (IOException e) {
+		}
+	}
+	
+	protected void init() throws TwoFaException {
+		try {
+			uri = new URI(configMap.get("url"));
+		} catch (URISyntaxException e) {
+			throw new TwoFaException(e);
+		}
+		targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
+
+		context = HttpClientContext.create();
+
+		config = RequestConfig.custom()
+			    .setSocketTimeout(30000)
+			    .setConnectTimeout(30000)
+			    .build();
+		try {
+			httpClient = HttpClients.custom()
+					.setDefaultRequestConfig(config)
+			        .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, TrustAllStrategy.INSTANCE).build())
+			        .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+					.build();
+		} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
+			throw new TwoFaException(e);
+		}
+
+		adminUsername = configMap.get("username");
+		adminPassword = configMap.get("password");
+	}
+
+	public EduMFASimpleResponse checkToken(String token) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/validate/check");
+			
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			else
+				throw new TwoFaException("userId missing in config map");
+			
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			
+			nvps.add(new BasicNameValuePair("pass", token));
+			
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("checkToken response: {}", responseString);
+			    
+			    return resultParser.parseSimpleResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}
+	}
+	
+	public EduMFASimpleResponse checkSpecificToken(String serial, String token) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/validate/check");
+			
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+		    nvps.add(new BasicNameValuePair("serial", serial));
+			nvps.add(new BasicNameValuePair("pass", token));
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+		    if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("checkSpecificToken response: {}", responseString);
+			    
+			    return resultParser.parseSimpleResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}
+	}
+	
+	public EduMFAInitAuthenticatorTokenResponse createAuthenticatorToken() throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/init");
+			httpPost.addHeader("Authorization", adminSession);
+			
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			nvps.add(new BasicNameValuePair("session", adminSession));
+			nvps.add(new BasicNameValuePair("type", "totp"));
+			nvps.add(new BasicNameValuePair("otplen", "6"));
+			nvps.add(new BasicNameValuePair("genkey", "1"));
+			nvps.add(new BasicNameValuePair("hashlib", "sha1"));
+			nvps.add(new BasicNameValuePair("timeStep", "30"));
+			nvps.add(new BasicNameValuePair("description", "INIT,DELABLE,BWIDM,TS " + formatDate() + ","));
+
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			else
+				throw new TwoFaException("userId missing in config map");
+
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("createAuthenticatorToken response: {}", responseString);
+			    
+			    return resultParser.parseInitAuthenticatorTokenResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFAInitAuthenticatorTokenResponse createYubicoToken(String yubi) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/init");
+			httpPost.addHeader("Authorization", adminSession);
+			
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			nvps.add(new BasicNameValuePair("type", "yubico"));
+			nvps.add(new BasicNameValuePair("yubico.tokenid", yubi));
+			nvps.add(new BasicNameValuePair("description", "This is a description"));
+
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			else
+				throw new TwoFaException("userId missing in config map");
+
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("createYubicoToken response: {}", responseString);
+			    
+			    return resultParser.parseInitAuthenticatorTokenResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+
+	public EduMFAInitPaperTanTokenResponse createPaperTanList() throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/init");
+			httpPost.addHeader("Authorization", adminSession);
+			
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			nvps.add(new BasicNameValuePair("type", "paper"));
+			nvps.add(new BasicNameValuePair("description", "This is a description"));
+
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			else
+				throw new TwoFaException("userId missing in config map");
+
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("createPaperTanList response: {}", responseString);
+			    
+			    return resultParser.parseInitPaperTanTokenResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFASetFieldResult initToken(String serial) throws TwoFaException {
+		return setTokenDescription(serial, "ACTIVE,DELABLE,TS " + formatDate() + ",");
+	}
+	
+	public EduMFASetFieldResult setTokenDescription(String serial, String description) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/set/" + serial);
+			httpPost.addHeader("Authorization", adminSession);
+
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			nvps.add(new BasicNameValuePair("description", description));
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("setTokenField response: {}", responseString);
+
+			    return resultParser.parseSetFieldResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+
+	public EduMFASetFieldResult setTokenField(String serial, String key, String value) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/info/" + serial + "/" + key);
+			httpPost.addHeader("Authorization", adminSession);
+
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			nvps.add(new BasicNameValuePair("value", value));
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("setTokenField response: {}", responseString);
+
+			    return resultParser.parseSetFieldResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFASimpleResponse disableToken(String serial) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/disable");
+			httpPost.addHeader("Authorization", adminSession);
+
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			nvps.add(new BasicNameValuePair("serial", serial));
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("disableToken response: {}", responseString);
+
+			    return resultParser.parseSimpleResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFASimpleResponse enableToken(String serial) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/enable");
+			httpPost.addHeader("Authorization", adminSession);
+
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			nvps.add(new BasicNameValuePair("serial", serial));
+			httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("enableToken response: {}", responseString);
+
+			    return resultParser.parseSimpleResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFASimpleResponse deleteToken(String serial) throws TwoFaException {
+		try {
+			HttpDelete httpDelete = new HttpDelete(configMap.get("url") + "/token/" + serial);
+			httpDelete.addHeader("Authorization", adminSession);
+
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpDelete, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("deleteToken response: {}", responseString);
+
+			    return resultParser.parseSimpleResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+
+	public EduMFASimpleResponse resetFailcounter(String serial) throws TwoFaException {
+		try {
+			HttpPost httpPost = new HttpPost(configMap.get("url") + "/token/reset/" + serial);
+			httpPost.addHeader("Authorization", adminSession);
+
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("resetFailcounter response: {}", responseString);
+
+			    return resultParser.parseSimpleResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFAShowUserResponse getTokenList() throws TwoFaException {
+
+		try {
+			HttpGet httpGet = new HttpGet(configMap.get("url") + "/token");
+			httpGet.addHeader("Authorization", adminSession);
+
+			List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+			if (configMap.containsKey("userId"))
+			    nvps.add(new BasicNameValuePair("user", configMap.get("userId")));
+			else
+				throw new TwoFaException("userId missing in config map");
+
+			if (configMap.containsKey("realm"))
+				nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
+			
+			URI uri = new URIBuilder(httpGet.getURI())
+				      .addParameters(nvps)
+				      .build();
+			httpGet.setURI(uri);
+			
+			CloseableHttpResponse response = httpClient.execute(targetHost, httpGet, context);
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("getTokenList response: {}", responseString);
+			    
+			    return resultParser.parseShowUserResponse(responseString);
+
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException | URISyntaxException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFAAuthResponse requestAdminSession() throws TwoFaException {
+        try {
+    		HttpPost httpPost = new HttpPost(configMap.get("url") + "/auth");
+
+    		List<NameValuePair> nvps = new ArrayList <NameValuePair>();
+    		nvps.add(new BasicNameValuePair("username", adminUsername));
+    		nvps.add(new BasicNameValuePair("password", adminPassword));
+    		httpPost.setEntity(new UrlEncodedFormEntity(nvps));
+
+    		adminSession = null;
+
+    		CloseableHttpResponse response = httpClient.execute(targetHost, httpPost, context);
+			
+			try {
+			    HttpEntity entity = response.getEntity();
+			    String responseString = EntityUtils.toString(entity);
+			    if (logger.isTraceEnabled())
+			    	logger.trace("requestAdminSession response: {}", responseString);
+			    
+			    EduMFAAuthResponse authResponse = resultParser.parseAuthResponse(responseString);
+			    adminSession = authResponse.getResult().getValue().getToken();
+			    return authResponse;
+			} finally {
+				response.close();
+			}
+		} catch (ParseException | IOException e) {
+			throw new TwoFaException(e);
+		}
+	}
+
+	protected List<?> getDataList(Map<?, ?> valueMap) {
+        logger.debug("data: " + valueMap.get("data").getClass().toString());
+        if (valueMap.get("data") instanceof List<?>) {
+        	List<?> dataList = (List<?>) valueMap.get("data");
+        	return dataList;
+        }
+        else {
+        	return null;
+        }
+	}
+	
+	protected String formatDate() {
+		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm");
+		return formatter.format(new Date());
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListResponse.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..6dc51540173bebf8b28f9c053e5245cb449954c6
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListResponse.java
@@ -0,0 +1,51 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFAGetBackupTanListResponse implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String version;
+	
+	@JsonProperty("jsonrpc")
+	private String jsonRpc;
+	
+	private EduMFAGetBackupTanListResult result;
+	
+	private Integer id;
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getJsonRpc() {
+		return jsonRpc;
+	}
+	
+	public void setJsonRpc(String jsonRpc) {
+		this.jsonRpc = jsonRpc;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public EduMFAGetBackupTanListResult getResult() {
+		return result;
+	}
+
+	public void setResult(EduMFAGetBackupTanListResult result) {
+		this.result = result;
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListResult.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..96cd7097ee5dce5e839c3d13105ef1656bd59290
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListResult.java
@@ -0,0 +1,28 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAGetBackupTanListResult implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private boolean status;
+	private EduMFAGetBackupTanListValue value;
+
+	public boolean isStatus() {
+		return status;
+	}
+
+	public void setStatus(boolean status) {
+		this.status = status;
+	}
+
+	public EduMFAGetBackupTanListValue getValue() {
+		return value;
+	}
+
+	public void setValue(EduMFAGetBackupTanListValue value) {
+		this.value = value;
+	}
+
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListValue.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..527ea342c503209cac2378d9f627076c590beb78
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAGetBackupTanListValue.java
@@ -0,0 +1,46 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class EduMFAGetBackupTanListValue implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private Map<String, String> otp;
+	private String serial;
+	private String type;
+	private boolean result;
+
+	public Map<String, String> getOtp() {
+		return otp;
+	}
+	
+	public void setOtp(Map<String, String> otp) {
+		this.otp = otp;
+	}
+
+	public String getSerial() {
+		return serial;
+	}
+
+	public void setSerial(String serial) {
+		this.serial = serial;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public void setType(String type) {
+		this.type = type;
+	}
+
+	public boolean isResult() {
+		return result;
+	}
+
+	public void setResult(boolean result) {
+		this.result = result;
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenDetail.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenDetail.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c9d4888a78be56af8b9d7669fbb6b93edb34695
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenDetail.java
@@ -0,0 +1,37 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAInitAuthenticatorTokenDetail implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private EduMFAInitAuthenticatorTokenOtpKey googleurl;
+	private String serial;
+	private EduMFAInitAuthenticatorTokenOtpKey otpkey;
+	
+	public EduMFAInitAuthenticatorTokenOtpKey getGoogleurl() {
+		return googleurl;
+	}
+	
+	public void setGoogleurl(EduMFAInitAuthenticatorTokenOtpKey googleurl) {
+		this.googleurl = googleurl;
+	}
+
+	public String getSerial() {
+		return serial;
+	}
+
+	public void setSerial(String serial) {
+		this.serial = serial;
+	}
+
+	public EduMFAInitAuthenticatorTokenOtpKey getOtpkey() {
+		return otpkey;
+	}
+
+	public void setOtpkey(EduMFAInitAuthenticatorTokenOtpKey otpkey) {
+		this.otpkey = otpkey;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenOtpKey.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenOtpKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f3e9b5c24200aaf592a36940879dcbe2019b9cd
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenOtpKey.java
@@ -0,0 +1,46 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAInitAuthenticatorTokenOtpKey implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String img;
+	private String order;
+	private String value;
+	private String description;
+
+	public String getImg() {
+		return img;
+	}
+
+	public void setImg(String img) {
+		this.img = img;
+	}
+
+	public String getOrder() {
+		return order;
+	}
+	
+	public void setOrder(String order) {
+		this.order = order;
+	}
+	
+	public String getValue() {
+		return value;
+	}
+	
+	public void setValue(String value) {
+		this.value = value;
+	}
+	
+	public String getDescription() {
+		return description;
+	}
+	
+	public void setDescription(String description) {
+		this.description = description;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenResponse.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b072fec55f5b00a165e7edbd8c088c62f5f84ac
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitAuthenticatorTokenResponse.java
@@ -0,0 +1,62 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFAInitAuthenticatorTokenResponse implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String version;
+	
+	@JsonProperty("jsonrpc")
+	private String jsonRpc;
+	
+	private EduMFAResult result;
+	
+	private EduMFAInitAuthenticatorTokenDetail detail;
+	
+	private Integer id;
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getJsonRpc() {
+		return jsonRpc;
+	}
+	
+	public void setJsonRpc(String jsonRpc) {
+		this.jsonRpc = jsonRpc;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public EduMFAResult getResult() {
+		return result;
+	}
+
+	public void setResult(EduMFAResult result) {
+		this.result = result;
+	}
+
+	public EduMFAInitAuthenticatorTokenDetail getDetail() {
+		return detail;
+	}
+
+	public void setDetail(EduMFAInitAuthenticatorTokenDetail detail) {
+		this.detail = detail;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitPaperTanTokenDetail.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitPaperTanTokenDetail.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b433ff3a4cabf0ef608c2785eda377f38b34b0c
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitPaperTanTokenDetail.java
@@ -0,0 +1,47 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class EduMFAInitPaperTanTokenDetail implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private EduMFAInitAuthenticatorTokenOtpKey googleurl;
+	private String serial;
+	private EduMFAInitAuthenticatorTokenOtpKey otpkey;
+	private Map<String, String> otps;
+
+	public EduMFAInitAuthenticatorTokenOtpKey getGoogleurl() {
+		return googleurl;
+	}
+	
+	public void setGoogleurl(EduMFAInitAuthenticatorTokenOtpKey googleurl) {
+		this.googleurl = googleurl;
+	}
+
+	public String getSerial() {
+		return serial;
+	}
+
+	public void setSerial(String serial) {
+		this.serial = serial;
+	}
+
+	public EduMFAInitAuthenticatorTokenOtpKey getOtpkey() {
+		return otpkey;
+	}
+
+	public void setOtpkey(EduMFAInitAuthenticatorTokenOtpKey otpkey) {
+		this.otpkey = otpkey;
+	}
+
+	public Map<String, String> getOtps() {
+		return otps;
+	}
+
+	public void setOtps(Map<String, String> otps) {
+		this.otps = otps;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitPaperTanTokenResponse.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitPaperTanTokenResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..7bf91a79f2ff32838f332f5b4f0242b6005724a8
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAInitPaperTanTokenResponse.java
@@ -0,0 +1,62 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFAInitPaperTanTokenResponse implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String version;
+	
+	@JsonProperty("jsonrpc")
+	private String jsonRpc;
+	
+	private EduMFAResult result;
+	
+	private EduMFAInitPaperTanTokenDetail detail;
+	
+	private Integer id;
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getJsonRpc() {
+		return jsonRpc;
+	}
+	
+	public void setJsonRpc(String jsonRpc) {
+		this.jsonRpc = jsonRpc;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public EduMFAResult getResult() {
+		return result;
+	}
+
+	public void setResult(EduMFAResult result) {
+		this.result = result;
+	}
+
+	public EduMFAInitPaperTanTokenDetail getDetail() {
+		return detail;
+	}
+
+	public void setDetail(EduMFAInitPaperTanTokenDetail detail) {
+		this.detail = detail;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResult.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6ea12c5c8b49c9aef051fa45d0d6fb2d16d5716
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResult.java
@@ -0,0 +1,28 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAResult implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+	
+	private boolean status;
+	private boolean value;
+
+	public boolean isStatus() {
+		return status;
+	}
+
+	public void setStatus(boolean status) {
+		this.status = status;
+	}
+
+	public boolean isValue() {
+		return value;
+	}
+
+	public void setValue(boolean value) {
+		this.value = value;
+	}
+
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResultParser.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResultParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..bb179ffd167ab455ebc45605d5364637715b5194
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResultParser.java
@@ -0,0 +1,86 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import edu.kit.scc.webreg.service.twofa.TwoFaException;
+
+public class EduMFAResultParser {
+
+	private ObjectMapper om;
+	
+	public EduMFAResultParser() {
+		om = new ObjectMapper();
+		om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+	}
+	
+	public EduMFASimpleResponse parseSimpleResponse(String responseString) throws TwoFaException {
+		try {
+			EduMFASimpleResponse response = om.readValue(responseString, EduMFASimpleResponse.class);
+			return response;
+		} catch (IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+
+	public EduMFAAuthResponse parseAuthResponse(String responseString) throws TwoFaException {
+		try {
+			EduMFAAuthResponse response = om.readValue(responseString, EduMFAAuthResponse.class);
+			return response;
+		} catch (IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+
+	public EduMFAShowUserResponse parseShowUserResponse(String responseString) throws TwoFaException {
+		try {
+			EduMFAShowUserResponse response = om.readValue(responseString, EduMFAShowUserResponse.class);
+			return response;
+		} catch (IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+
+	public EduMFAInitAuthenticatorTokenResponse parseInitAuthenticatorTokenResponse(String responseString) throws TwoFaException {
+		try {
+			EduMFAInitAuthenticatorTokenResponse response = 
+					om.readValue(responseString, EduMFAInitAuthenticatorTokenResponse.class);
+			return response;
+		} catch (IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}	
+
+	public EduMFAInitPaperTanTokenResponse parseInitPaperTanTokenResponse(String responseString) throws TwoFaException {
+		try {
+			EduMFAInitPaperTanTokenResponse response = 
+					om.readValue(responseString, EduMFAInitPaperTanTokenResponse.class);
+			return response;
+		} catch (IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}	
+	
+	public EduMFAGetBackupTanListResponse parseGetBackupTanListResponse(String responseString) throws TwoFaException {
+		try {
+			EduMFAGetBackupTanListResponse response = 
+					om.readValue(responseString, EduMFAGetBackupTanListResponse.class);
+			return response;
+		} catch (IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+	
+	public EduMFASetFieldResult parseSetFieldResponse(String responseString) throws TwoFaException {
+		try {
+			EduMFASetFieldResult response = 
+					om.readValue(responseString, EduMFASetFieldResult.class);
+			return response;
+		} catch (IOException e) {
+			throw new TwoFaException(e);
+		}		
+	}
+
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResultSet.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResultSet.java
new file mode 100644
index 0000000000000000000000000000000000000000..b54d53995dd8ec48c219b66e03a1272b13ad9afa
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAResultSet.java
@@ -0,0 +1,45 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAResultSet implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private Integer tokens;
+	private Integer pages;
+	private Integer pagesize;
+	private Integer page;
+
+	public Integer getTokens() {
+		return tokens;
+	}
+	
+	public void setTokens(Integer tokens) {
+		this.tokens = tokens;
+	}
+	
+	public Integer getPages() {
+		return pages;
+	}
+	
+	public void setPages(Integer pages) {
+		this.pages = pages;
+	}
+	
+	public Integer getPagesize() {
+		return pagesize;
+	}
+	
+	public void setPagesize(Integer pagesize) {
+		this.pagesize = pagesize;
+	}
+	
+	public Integer getPage() {
+		return page;
+	}
+	
+	public void setPage(Integer page) {
+		this.page = page;
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASetFieldResponse.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASetFieldResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..28966b3ea4b7467dcc070feb76a4e949558bb605
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASetFieldResponse.java
@@ -0,0 +1,52 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFASetFieldResponse implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String version;
+	
+	@JsonProperty("jsonrpc")
+	private String jsonRpc;
+	
+	private EduMFASetFieldResult result;
+	
+	private Integer id;
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getJsonRpc() {
+		return jsonRpc;
+	}
+	
+	public void setJsonRpc(String jsonRpc) {
+		this.jsonRpc = jsonRpc;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public EduMFASetFieldResult getResult() {
+		return result;
+	}
+
+	public void setResult(EduMFASetFieldResult result) {
+		this.result = result;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASetFieldResult.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASetFieldResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..f66f89c112621a621ec36544190919169b897b8b
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASetFieldResult.java
@@ -0,0 +1,28 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class EduMFASetFieldResult implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private boolean status;
+	private Map<String, Object> value;
+
+	public boolean isStatus() {
+		return status;
+	}
+
+	public void setStatus(boolean status) {
+		this.status = status;
+	}
+
+	public Map<String, Object> getValue() {
+		return value;
+	}
+
+	public void setValue(Map<String, Object> value) {
+		this.value = value;
+	}
+}
\ No newline at end of file
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAShowUserResponse.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAShowUserResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe1bb8dd63618854387c519aa9ebaec040885eee
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAShowUserResponse.java
@@ -0,0 +1,52 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFAShowUserResponse implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String version;
+	
+	@JsonProperty("jsonrpc")
+	private String jsonRpc;
+	
+	private EduMFAValueResult result;
+	
+	private Integer id;
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getJsonRpc() {
+		return jsonRpc;
+	}
+	
+	public void setJsonRpc(String jsonRpc) {
+		this.jsonRpc = jsonRpc;
+	}
+
+	public EduMFAValueResult getResult() {
+		return result;
+	}
+	
+	public void setResult(EduMFAValueResult result) {
+		this.result = result;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASimpleResponse.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASimpleResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..25bb97b61b1e1dc31b53d3499280eb073a33d854
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFASimpleResponse.java
@@ -0,0 +1,52 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFASimpleResponse implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private String version;
+	
+	@JsonProperty("jsonrpc")
+	private String jsonRpc;
+	
+	private EduMFAResult result;
+	
+	private Integer id;
+
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public String getJsonRpc() {
+		return jsonRpc;
+	}
+	
+	public void setJsonRpc(String jsonRpc) {
+		this.jsonRpc = jsonRpc;
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public EduMFAResult getResult() {
+		return result;
+	}
+
+	public void setResult(EduMFAResult result) {
+		this.result = result;
+	}
+	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAToken.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAToken.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb21cfbfd1d39ddf9532c60a710b6cc1505a1738
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAToken.java
@@ -0,0 +1,115 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class EduMFAToken implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+		
+	private Boolean active;
+	private String count;
+	private String otplen;
+
+	@JsonProperty(value = "count_window")
+	private String countWindow;
+	
+	private String description;
+	private String serial;
+	private String tokentype;
+	private String maxfail;
+	private String failcount;
+	
+	@JsonProperty(value = "user_id")
+	private String userId;
+	private String username;
+	
+	public Boolean getActive() {
+		return active;
+	}
+	
+	public void setActive(Boolean active) {
+		this.active = active;
+	}
+	
+	public String getCount() {
+		return count;
+	}
+	
+	public void setCount(String count) {
+		this.count = count;
+	}
+	
+	public String getCountWindow() {
+		return countWindow;
+	}
+	
+	public void setCountWindow(String countWindow) {
+		this.countWindow = countWindow;
+	}
+	
+	public String getDescription() {
+		return description;
+	}
+	
+	public void setDescription(String description) {
+		this.description = description;
+	}
+	
+	public String getSerial() {
+		return serial;
+	}
+	
+	public void setSerial(String serial) {
+		this.serial = serial;
+	}
+	
+	public String getTokentype() {
+		return tokentype;
+	}
+	
+	public void setTokentype(String tokentype) {
+		this.tokentype = tokentype;
+	}
+	
+	public String getUserId() {
+		return userId;
+	}
+	
+	public void setUserId(String userId) {
+		this.userId = userId;
+	}
+	
+	public String getUsername() {
+		return username;
+	}
+	
+	public void setUsername(String username) {
+		this.username = username;
+	}
+
+	public String getOtplen() {
+		return otplen;
+	}
+
+	public void setOtplen(String otplen) {
+		this.otplen = otplen;
+	}
+
+	public String getMaxfail() {
+		return maxfail;
+	}
+
+	public void setMaxfail(String maxfail) {
+		this.maxfail = maxfail;
+	}
+
+	public String getFailcount() {
+		return failcount;
+	}
+
+	public void setFailcount(String failcount) {
+		this.failcount = failcount;
+	}	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFATokenManager.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFATokenManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b35e2a54928ddcf9bc52792cf518c1c330ee613
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFATokenManager.java
@@ -0,0 +1,358 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import edu.kit.scc.webreg.audit.TokenAuditor;
+import edu.kit.scc.webreg.entity.identity.IdentityEntity;
+import edu.kit.scc.webreg.service.twofa.AbstractTwoFaManager;
+import edu.kit.scc.webreg.service.twofa.TwoFaException;
+import edu.kit.scc.webreg.service.twofa.token.GenericTwoFaToken;
+import edu.kit.scc.webreg.service.twofa.token.HmacToken;
+import edu.kit.scc.webreg.service.twofa.token.HmacTokenList;
+import edu.kit.scc.webreg.service.twofa.token.PaperTanListToken;
+import edu.kit.scc.webreg.service.twofa.token.TokenStatusResponse;
+import edu.kit.scc.webreg.service.twofa.token.TotpCreateResponse;
+import edu.kit.scc.webreg.service.twofa.token.TotpToken;
+import edu.kit.scc.webreg.service.twofa.token.TwoFaTokenList;
+import edu.kit.scc.webreg.service.twofa.token.YubicoToken;
+import java.util.Arrays;
+import java.util.HashSet;
+
+public class EduMFATokenManager extends AbstractTwoFaManager {
+
+	private static Logger logger = LoggerFactory.getLogger(EduMFATokenManager.class);
+
+	private static final Set<String> capabilities = Set.of(new String[] {
+			"TOTP", "YUBIKEY", "PAPER_TAN"
+	});
+	
+	@Override
+	public Set<String> getCapabilities() {
+		if (getConfigMap().containsKey("capabilities")) {
+			Set<String> capab = new HashSet<String>(Arrays.asList(getConfigMap().get("capabilities")
+					.toUpperCase().split("\\s*;\\s*")));
+			if (capab.retainAll(capabilities)) {
+				// capab was changed -> unsupported input detected!
+				logger.warn("Some provided capabilities are not supported and will be ignored!");
+			}
+			return capab;
+		}
+		return capabilities;
+	}
+	
+	@Override
+	public TwoFaTokenList findByIdentity(IdentityEntity identity) throws TwoFaException {
+		TwoFaTokenList resultList = new TwoFaTokenList();
+		if (getConfigMap().containsKey("reallyReadOnly") && getConfigMap().get("reallyReadOnly").equalsIgnoreCase("true")) {
+			resultList.setReallyReadOnly(true);
+			resultList.setReadOnly(true);
+			if (getConfigMap().containsKey("managementUrl")) {
+				resultList.setManagementUrl(getConfigMap().get("managementUrl"));
+			}
+		}
+		else {
+			resultList.setReallyReadOnly(false);
+			
+			EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+			connection.requestAdminSession();
+
+			EduMFAShowUserResponse response = connection.getTokenList();
+			if (response.getResult() != null && response.getResult().getValue() != null &&
+					response.getResult().getValue().getTokens() !=null) {
+				
+				for (EduMFAToken token : response.getResult().getValue().getTokens()) {
+					GenericTwoFaToken genericToken = convertToken(token);
+
+					if (genericToken != null) {
+						resultList.add(genericToken);
+					}
+				}
+			}
+			
+			if (getConfigMap().containsKey("readOnly") && getConfigMap().get("readOnly").equalsIgnoreCase("true")) {
+				resultList.setReadOnly(true);
+			}
+			else {
+				resultList.setReadOnly(false);
+			}
+	
+			if (getConfigMap().containsKey("managementUrl")) {
+				resultList.setManagementUrl(getConfigMap().get("managementUrl"));
+			}
+	
+			if (getConfigMap().containsKey("adminRole")) {
+				resultList.setAdminRole(getConfigMap().get("adminRole"));
+			}
+	
+		}
+		return resultList;
+	}
+	
+	@Override
+	public Boolean hasActiveToken(IdentityEntity identity) throws TwoFaException {
+		TwoFaTokenList tokenList = findByIdentity(identity);
+
+		if (tokenList.getReallyReadOnly() != null && tokenList.getReallyReadOnly()) {
+			return true;
+		}
+		
+		for (GenericTwoFaToken token : tokenList) {
+			if (token.getIsactive()) {
+				/*
+				 * filter token, that are not initialized
+				 */
+				if (token.getDescription() != null && token.getDescription().contains("INIT")) {
+					return false;
+				}
+				return true;
+			}
+		}
+		
+		return false;
+	}
+	
+	@Override
+	public Boolean checkToken(IdentityEntity identity, String token) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		EduMFASimpleResponse response = connection.checkToken(token);
+		
+		if (!(response.getResult() != null && response.getResult().isStatus() && 
+				response.getResult().isValue())) {
+			return false;
+		}
+		else {
+			return true;
+		}
+	}
+	
+	@Override
+	public Boolean checkSpecificToken(IdentityEntity identity, String serial, String token) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		EduMFASimpleResponse response = connection.checkSpecificToken(serial, token);
+		
+		if (!(response.getResult() != null && response.getResult().isStatus() && 
+				response.getResult().isValue())) {
+			return false;
+		}
+		else {
+			return true;
+		}	
+	}
+	
+	@Override
+	public Map<String,Object> initToken(IdentityEntity identity, String serial, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		EduMFASetFieldResult response = connection.initToken(serial);
+		return response.getValue();
+	}
+	
+	@Override
+	public TotpCreateResponse createAuthenticatorToken(IdentityEntity identity, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		
+		EduMFAInitAuthenticatorTokenResponse specificResponse = connection.createAuthenticatorToken();
+		TotpCreateResponse response = new TotpCreateResponse();
+		
+		if (specificResponse.getResult().isStatus() && specificResponse.getResult().isValue()) {
+			response.setSuccess(true);
+			response.setSerial(specificResponse.getDetail().getSerial());
+			response.setDescription(specificResponse.getDetail().getGoogleurl().getDescription());
+			response.setImage("<img src=\"" + specificResponse.getDetail().getGoogleurl().getImg() + "\" width=\"128\" height=\"128\" />");
+			response.setOrder(specificResponse.getDetail().getGoogleurl().getOrder());
+			response.setValue(specificResponse.getDetail().getGoogleurl().getValue());
+			response.setSeed(specificResponse.getDetail().getOtpkey().getValue());
+		}
+		else {
+			response.setSuccess(false);
+		}
+		
+		return response;
+	}
+
+	@Override
+	public TokenStatusResponse disableToken(IdentityEntity identity, String serial, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		EduMFASimpleResponse specificResponse = connection.disableToken(serial);
+		TokenStatusResponse response = new TokenStatusResponse();
+		if ((specificResponse.getResult() != null) && specificResponse.getResult().isStatus() &&
+				specificResponse.getResult().isValue()) {
+			response.setSuccess(true);
+		}
+		else {
+			response.setSuccess(false);
+		}
+		response.setSerial(serial);
+		
+		return response;
+	}
+	
+	@Override
+	public TokenStatusResponse enableToken(IdentityEntity identity, String serial, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		EduMFASimpleResponse specificResponse = connection.enableToken(serial);
+		TokenStatusResponse response = new TokenStatusResponse();
+		if ((specificResponse.getResult() != null) && specificResponse.getResult().isStatus() &&
+				specificResponse.getResult().isValue()) {
+			response.setSuccess(true);
+		}
+		else {
+			response.setSuccess(false);
+		}
+		response.setSerial(serial);
+		
+		return response;
+	}
+	
+	@Override
+	public TotpCreateResponse createYubicoToken(IdentityEntity identity, String yubi, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		
+		EduMFAInitAuthenticatorTokenResponse specificResponse = connection.createYubicoToken(yubi);
+		TotpCreateResponse response = new TotpCreateResponse();
+		
+		if (specificResponse == null || specificResponse.getDetail() == null) {
+			response.setSuccess(false);
+		}
+		else {
+			response.setSuccess(true);
+			response.setSerial(specificResponse.getDetail().getSerial());
+		}
+		
+		return response;
+	}
+
+	@Override
+	public TotpCreateResponse createHotpBackupTanList(IdentityEntity identity, TokenAuditor auditor) throws TwoFaException {
+		throw new IllegalAccessError();
+	}
+
+	@Override
+	public TotpCreateResponse createPaperTanList(IdentityEntity identity, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		
+		EduMFAInitPaperTanTokenResponse specificResponse = connection.createPaperTanList();
+		TotpCreateResponse response = new TotpCreateResponse();
+		
+		if (specificResponse == null || specificResponse.getDetail() == null) {
+			response.setSuccess(false);
+		}
+		else {
+			response.setSuccess(true);
+			response.setSerial(specificResponse.getDetail().getSerial());
+			if (getConfigMap().containsKey("papertan_count")) {
+				LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
+				AtomicInteger i = new AtomicInteger(0);
+				int max = Integer.parseInt(getConfigMap().get("papertan_count"));
+				
+				specificResponse.getDetail().getOtps().forEach( (x, y) -> {
+					if (i.incrementAndGet() <= max) { 
+						map.put(x, y);
+					}
+				});
+				response.setOtps(map);
+			}
+			else {
+				response.setOtps(specificResponse.getDetail().getOtps());
+			}
+		}
+		
+		return response;
+	}
+	
+	@Override
+	public TokenStatusResponse resetFailcounter(IdentityEntity identity, String serial, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		EduMFASimpleResponse specificResponse = connection.resetFailcounter(serial);
+		TokenStatusResponse response = new TokenStatusResponse();
+
+		if ((specificResponse.getResult() != null) && specificResponse.getResult().isStatus() &&
+				specificResponse.getResult().isValue()) {
+			response.setSuccess(true);
+		}
+		else {
+			response.setSuccess(false);
+		}
+		response.setSerial(serial);
+		
+		return response;
+	}
+	
+	@Override
+	public TokenStatusResponse deleteToken(IdentityEntity identity, String serial, TokenAuditor auditor) throws TwoFaException {
+		EduMFAConnection connection = new EduMFAConnection(getConfigMap());
+		connection.requestAdminSession();
+		EduMFASimpleResponse specificResponse = connection.deleteToken(serial);
+		TokenStatusResponse response = new TokenStatusResponse();
+
+		if ((specificResponse.getResult() != null) && specificResponse.getResult().isStatus() &&
+				specificResponse.getResult().isValue()) {
+			response.setSuccess(true);
+		}
+		else {
+			response.setSuccess(false);
+		}
+		response.setSerial(serial);
+		
+		return response;
+	}
+	
+	@Override
+	public HmacTokenList getBackupTanList(IdentityEntity identity, String serial) throws TwoFaException {
+		throw new IllegalAccessError();
+	}
+	
+	private GenericTwoFaToken convertToken(EduMFAToken piToken) {
+		GenericTwoFaToken token;
+		if (piToken.getTokentype().equals("totp")) {
+			TotpToken totpToken = new TotpToken();
+			totpToken.setOtpLen(piToken.getOtplen());
+			totpToken.setCountWindow(piToken.getCountWindow());
+			token = totpToken;
+			token.setTokenType("TOTP");
+		}
+		else if (piToken.getTokentype().equals("yubico")) {
+			token = new YubicoToken();
+			token.setTokenType("yubico");
+		}
+		else if (piToken.getTokentype().equals("hotp")) {
+			token = new HmacToken();
+			token.setTokenType("HMAC");
+		}
+		else if (piToken.getTokentype().equals("paper")) {
+			PaperTanListToken paperToken = new PaperTanListToken();
+			paperToken.setTokenType("PAPER_TAN");
+			token = paperToken;
+		}
+		else {
+			logger.warn("Unknown Tokentype {}. Ingoring.", piToken.getTokentype());
+			return null;
+		}
+		
+		// Token in PI only have serials
+		//token.setId(piToken.getId());
+		token.setSerial(piToken.getSerial());
+		//token.setTokenInfo(piToken.getTokenInfo());
+		token.setDescription(piToken.getDescription());
+		token.setMaxFail(piToken.getMaxfail());
+		token.setCount(piToken.getCount());
+		token.setUsername(piToken.getUsername());
+		//token.setSyncWindow(piToken.getSyncWindow());
+		token.setFailCount(piToken.getFailcount());
+		token.setIsactive(piToken.getActive());
+		
+		return token;
+	}	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFATokenResultList.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFATokenResultList.java
new file mode 100644
index 0000000000000000000000000000000000000000..07a4452076cb944315860acaf34df1e873334cf5
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFATokenResultList.java
@@ -0,0 +1,70 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+public class EduMFATokenResultList extends ArrayList<EduMFAToken> implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private boolean status;
+	private String statusMessage;
+	
+	private boolean readOnly;
+	private boolean reallyReadOnly;
+	
+	private String managementUrl;
+	
+	private String adminRole;
+	
+	public EduMFATokenResultList() {
+		super();
+	}	
+
+	public boolean getReadOnly() {
+		return readOnly;
+	}
+
+	public void setReadOnly(boolean readOnly) {
+		this.readOnly = readOnly;
+	}
+
+	public String getManagementUrl() {
+		return managementUrl;
+	}
+
+	public void setManagementUrl(String managementUrl) {
+		this.managementUrl = managementUrl;
+	}
+	public boolean getStatus() {
+		return status;
+	}
+
+	public void setStatus(boolean status) {
+		this.status = status;
+	}
+
+	public String getStatusMessage() {
+		return statusMessage;
+	}
+
+	public void setStatusMessage(String statusMessage) {
+		this.statusMessage = statusMessage;
+	}
+
+	public String getAdminRole() {
+		return adminRole;
+	}
+
+	public void setAdminRole(String adminRole) {
+		this.adminRole = adminRole;
+	}
+
+	public boolean getReallyReadOnly() {
+		return reallyReadOnly;
+	}
+
+	public void setReallyReadOnly(boolean reallyReadOnly) {
+		this.reallyReadOnly = reallyReadOnly;
+	}
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAValue.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..80c4c78e7678f8e3e279a904cba8d5fa79fa76b7
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAValue.java
@@ -0,0 +1,38 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class EduMFAValue implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private Integer count;
+	private Integer current;
+	
+	private List<EduMFAToken> tokens;
+
+	public Integer getCount() {
+		return count;
+	}
+
+	public void setCount(Integer count) {
+		this.count = count;
+	}
+
+	public Integer getCurrent() {
+		return current;
+	}
+
+	public void setCurrent(Integer current) {
+		this.current = current;
+	}
+
+	public List<EduMFAToken> getTokens() {
+		return tokens;
+	}
+
+	public void setTokens(List<EduMFAToken> tokens) {
+		this.tokens = tokens;
+	}	
+}
diff --git a/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAValueResult.java b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAValueResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9a8e10c1106901bcf8fafd3b66c49ea3a1b7977
--- /dev/null
+++ b/regapp-twofa/src/main/java/edu/kit/scc/webreg/service/twofa/edumfa/EduMFAValueResult.java
@@ -0,0 +1,30 @@
+package edu.kit.scc.webreg.service.twofa.edumfa;
+
+import java.io.Serializable;
+
+public class EduMFAValueResult implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private boolean status;
+
+	private EduMFAValue value;
+	
+	public boolean isStatus() {
+		return status;
+	}
+
+	public void setStatus(boolean status) {
+		this.status = status;
+	}
+
+	public EduMFAValue getValue() {
+		return value;
+	}
+
+	public void setValue(EduMFAValue value) {
+		this.value = value;
+	}
+	
+	
+}