Commit 14e9b179 authored by ls1947's avatar ls1947
Browse files

add token create for totp and yubico

parent 74946b43
......@@ -18,4 +18,10 @@ public interface TwoFaService {
Boolean hasActiveToken(Long userId) throws TwoFaException;
LinotpSimpleResponse deleteToken(Long userId, String serial) throws TwoFaException;
LinotpSimpleResponse checkSpecificToken(Long userId, String serial, String token) throws TwoFaException;
LinotpInitAuthenticatorTokenResponse createYubicoToken(Long userId, String yubi) throws TwoFaException;
}
......@@ -81,7 +81,17 @@ public class TwoFaServiceImpl implements TwoFaService {
LinotpConnection linotpConnection = new LinotpConnection(configMap);
return linotpConnection.checkToken(user, token);
}
@Override
public LinotpSimpleResponse checkSpecificToken(Long userId, String serial, String token) throws TwoFaException {
UserEntity user = userDao.findById(userId);
Map<String, String> configMap = configResolver.resolveConfig(user);
LinotpConnection linotpConnection = new LinotpConnection(configMap);
return linotpConnection.checkSpecificToken(serial, token);
}
@Override
public LinotpInitAuthenticatorTokenResponse createAuthenticatorToken(Long userId) throws TwoFaException {
UserEntity user = userDao.findById(userId);
......@@ -103,7 +113,25 @@ public class TwoFaServiceImpl implements TwoFaService {
throw new TwoFaException("Token generation did not succeed!");
}
}
@Override
public LinotpInitAuthenticatorTokenResponse createYubicoToken(Long userId, String yubi) throws TwoFaException {
UserEntity user = userDao.findById(userId);
Map<String, String> configMap = configResolver.resolveConfig(user);
LinotpConnection linotpConnection = new LinotpConnection(configMap);
linotpConnection.requestAdminSession();
LinotpInitAuthenticatorTokenResponse response = linotpConnection.createYubicoToken(user, yubi);
if (response == null) {
throw new TwoFaException("Token generation did not succeed!");
}
return response;
}
@Override
public LinotpSimpleResponse disableToken(Long userId, String serial) throws TwoFaException {
UserEntity user = userDao.findById(userId);
......@@ -127,4 +155,17 @@ public class TwoFaServiceImpl implements TwoFaService {
return linotpConnection.enableToken(serial);
}
@Override
public LinotpSimpleResponse deleteToken(Long userId, String serial) throws TwoFaException {
UserEntity user = userDao.findById(userId);
Map<String, String> configMap = configResolver.resolveConfig(user);
LinotpConnection linotpConnection = new LinotpConnection(configMap);
linotpConnection.requestAdminSession();
return linotpConnection.deleteToken(serial);
}
}
......@@ -86,8 +86,8 @@ public class LinotpConnection {
context.setAuthCache(authCache);
config = RequestConfig.custom()
.setSocketTimeout(5000)
.setConnectTimeout(5000)
.setSocketTimeout(30000)
.setConnectTimeout(30000)
.build();
httpClient = HttpClients.custom().setDefaultRequestConfig(config).build();
}
......@@ -125,6 +125,36 @@ public class LinotpConnection {
}
}
public LinotpSimpleResponse checkSpecificToken(String serial, String token) throws TwoFaException {
try {
HttpPost httpPost = new HttpPost(configMap.get("url") + "/validate/check_s");
List<NameValuePair> nvps = new ArrayList <NameValuePair>();
if (configMap.containsKey("realm"))
nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
nvps.add(new BasicNameValuePair("serial", serial));
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);
logger.trace(responseString);
return resultParser.parseSimpleResponse(responseString);
} finally {
response.close();
}
} catch (ParseException | IOException e) {
throw new TwoFaException(e);
}
}
public LinotpInitAuthenticatorTokenResponse createAuthenticatorToken(UserEntity user) throws TwoFaException {
try {
HttpPost httpPost = new HttpPost(configMap.get("url") + "/admin/init");
......@@ -163,6 +193,41 @@ public class LinotpConnection {
}
}
public LinotpInitAuthenticatorTokenResponse createYubicoToken(UserEntity user, String yubi) throws TwoFaException {
try {
HttpPost httpPost = new HttpPost(configMap.get("url") + "/admin/init");
List<NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("session", adminSession));
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
nvps.add(new BasicNameValuePair("user", user.getEppn()));
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);
logger.trace(responseString);
return resultParser.parseInitAuthenticatorTokenResponse(responseString);
} finally {
response.close();
}
} catch (ParseException | IOException e) {
throw new TwoFaException(e);
}
}
public LinotpSimpleResponse disableToken(String serial) throws TwoFaException {
try {
HttpPost httpPost = new HttpPost(configMap.get("url") + "/admin/disable");
......@@ -215,6 +280,32 @@ public class LinotpConnection {
}
}
public LinotpSimpleResponse deleteToken(String serial) throws TwoFaException {
try {
HttpPost httpPost = new HttpPost(configMap.get("url") + "/admin/remove");
List<NameValuePair> nvps = new ArrayList <NameValuePair>();
if (configMap.containsKey("realm"))
nvps.add(new BasicNameValuePair("realm", configMap.get("realm")));
nvps.add(new BasicNameValuePair("session", adminSession));
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);
logger.trace(responseString);
return resultParser.parseSimpleResponse(responseString);
} finally {
response.close();
}
} catch (ParseException | IOException e) {
throw new TwoFaException(e);
}
}
public LinotpShowUserResponse getTokenList(UserEntity user) throws TwoFaException {
try {
......
......@@ -17,6 +17,7 @@ import javax.faces.bean.ViewScoped;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Inject;
import org.primefaces.PrimeFaces;
import org.slf4j.Logger;
import edu.kit.scc.webreg.entity.UserEntity;
......@@ -54,8 +55,13 @@ public class TwoFaUserBean implements Serializable {
private LinotpTokenResultList tokenList;
private LinotpInitAuthenticatorTokenResponse createTokenResponse;
private String totpCode, yubicoCode;
private String defaultButton;
public void preRenderView(ComponentSystemEvent ev) {
defaultButton = "yubicoStartButton";
if (user == null) {
try {
tokenList = twoFaService.findByUserId(sessionManager.getUserId());
......@@ -76,7 +82,55 @@ public class TwoFaUserBean implements Serializable {
logger.warn("TwoFaException", e);
}
}
public void createYubicoToken() {
try {
LinotpInitAuthenticatorTokenResponse response = twoFaService.createYubicoToken(user.getId(), yubicoCode);
if (response.getResult().isStatus() && response.getResult().isValue()) {
tokenList = twoFaService.findByUserId(sessionManager.getUserId());
}
else {
messageGenerator.addResolvedWarningMessage("warn", "twofa_token_failed", true);
}
PrimeFaces.current().executeScript("PF('addYubicoDlg').hide();");
createTokenResponse = null;
yubicoCode = "";
} catch (TwoFaException e) {
logger.warn("TwoFaException", e);
}
}
public void checkAuthenticatorToken() {
try {
if (createTokenResponse != null && createTokenResponse.getDetail() != null) {
String serial = createTokenResponse.getDetail().getSerial();
LinotpSimpleResponse response = twoFaService.enableToken(user.getId(), serial);
if (response.getResult() != null && response.getResult().isStatus() && response.getResult().isValue()) {
response = twoFaService.checkSpecificToken(user.getId(), serial, totpCode);
if (response.getResult() != null && response.getResult().isStatus() && response.getResult().isValue()) {
// success, Token stays active
tokenList = twoFaService.findByUserId(sessionManager.getUserId());
PrimeFaces.current().executeScript("PF('addTotpDlg').hide();");
createTokenResponse = null;
totpCode = "";
}
else {
// wrong code, disable token
response = twoFaService.disableToken(user.getId(), serial);
totpCode = "";
}
}
}
} catch (TwoFaException e) {
logger.warn("TwoFaException", e);
}
}
public void enableToken(String serial) {
try {
LinotpSimpleResponse response = twoFaService.enableToken(user.getId(), serial);
......@@ -111,6 +165,23 @@ public class TwoFaUserBean implements Serializable {
}
}
public void deleteToken(String serial) {
try {
LinotpSimpleResponse response = twoFaService.deleteToken(user.getId(), serial);
tokenList = twoFaService.findByUserId(sessionManager.getUserId());
if ((response.getResult() != null) && response.getResult().isStatus() &&
response.getResult().isValue()) {
messageGenerator.addInfoMessage("Info", "Token " + serial + " deleted");
}
else {
messageGenerator.addWarningMessage("Warn", "Token " + serial + " could not be deleted");
}
} catch (TwoFaException e) {
logger.warn("TwoFaException", e);
messageGenerator.addErrorMessage("Error", e.toString());
}
}
public Boolean getReadOnly() {
return tokenList.getReadOnly();
}
......@@ -131,4 +202,28 @@ public class TwoFaUserBean implements Serializable {
return createTokenResponse;
}
public String getTotpCode() {
return totpCode;
}
public void setTotpCode(String totpCode) {
this.totpCode = totpCode;
}
public String getDefaultButton() {
return defaultButton;
}
public void setDefaultButton(String defaultButton) {
this.defaultButton = defaultButton;
}
public String getYubicoCode() {
return yubicoCode;
}
public void setYubicoCode(String yubicoCode) {
this.yubicoCode = yubicoCode;
}
}
......@@ -36,7 +36,7 @@
</p:repeat>
</p:panel>
<p:dataGrid var="token" value="#{twoFaUserBean.tokenList}" columns="1" styleClass="whitefoot"
<p:dataGrid var="token" value="#{twoFaUserBean.tokenList}" columns="2" styleClass="whitefoot"
layout="grid" style="margin-bottom: 16px;" rendered="#{! twoFaUserBean.readOnly}">
<f:facet name="header">#{messages.twofa_list}</f:facet>
<p:panel styleClass="grayback" style="margin-bottom: 0px;">
......@@ -44,22 +44,100 @@
<i class="fa fa-fw fa-key"></i>
<b><h:outputText value="#{token.serial}" /></b>
</f:facet>
<div><h:outputText value="#{token.tokenType}" /></div>
<div><h:outputText value="#{token.isactive}" /></div>
<h:panelGrid columns="2">
<p:outputLabel for="@next" value="#{messages.twofa_tokentype}:" />
<h:panelGroup>
<h:outputText value="#{messages.twofa_tokentype_totp}" rendered="#{token.tokenType == 'TOTP' and token.serial.startsWith('TOTP')}"/>
<h:outputText value="#{messages.twofa_tokentype_totp_hardware}" rendered="#{token.tokenType == 'TOTP' and not token.serial.startsWith('TOTP')}"/>
<h:outputText value="#{messages.twofa_tokentype_tanlist}" rendered="#{token.tokenType == 'HOTP'}"/>
<h:outputText value="#{messages.twofa_tokentype_yubikey}" rendered="#{token.tokenType == 'yubico'}"/>
</h:panelGroup>
<p:outputLabel for="@next" value="#{messages.twofa_active}:" />
<h:outputText value="#{token.isactive ? messages.yes : messages.no}" />
</h:panelGrid>
<p:commandButton action="#{twoFaUserBean.disableToken(token.serial)}" value="Disable"
update="@form" rendered="#{token.isactive}"/>
<p:commandButton action="#{twoFaUserBean.enableToken(token.serial)}" value="Enable"
update="@form" rendered="#{! token.isactive}"/>
<p:commandButton action="#{twoFaUserBean.deleteToken(token.serial)}" value="Delete"
update="@form" rendered="#{! token.isactive}">
<p:confirm header="#{messages.confirm_header}" message="#{messages.confirm}" />
</p:commandButton>
</p:panel>
<f:facet name="footer">
<p:commandButton action="#{twoFaUserBean.createAuthenticatorToken()}" value="Create" update="@form"></p:commandButton>
</f:facet>
</p:dataGrid>
<p:panel rendered="#{! twoFaUserBean.readOnly}">
<h:outputText value="#{twoFaUserBean.createTokenResponse.detail.googleurl.img}" escape="false" />
<h:outputText value="#{twoFaUserBean.createTokenResponse.detail.serial}"/>
<p:panel>
<div>
<h:outputText value="#{messages.twofa_create_new_token}" />
</div>
<p:commandButton id="openAddTotpDialog" oncomplete="PF('addTotpDlg').show();" value="#{messages.twofa_create_new_totp}"></p:commandButton>
<p:commandButton id="openAddYubicoDialog" oncomplete="PF('addYubicoDlg').show();" value="#{messages.twofa_create_new_yubico}"></p:commandButton>
</p:panel>
<p:dialog header="#{messages.twofa_create_totp_token}"
widgetVar="addTotpDlg" id="addTotpDlgId" modal="true" closable="false" closeOnEscape="true"
showEffect="fade" hideEffect="fade">
<p:ajax event="close" update="@form" />
<div class="panel" style="width:360px;">
<h:outputText value="#{messages.twofa_create_totp_token_desc}" />
</div>
<p:panel id="totpResponsePanel">
<p:commandButton id="totpStartButton" action="#{twoFaUserBean.createAuthenticatorToken()}" value="#{messages.start}"
update="totpResponsePanel" rendered="#{empty twoFaUserBean.createTokenResponse}"/>
<h:panelGroup rendered="#{not empty twoFaUserBean.createTokenResponse}">
<div>
<h:outputText value="#{twoFaUserBean.createTokenResponse.detail.googleurl.img}" escape="false" />
</div>
<h:panelGrid columns="2">
<p:outputLabel for="@next" value="#{messages.twofa_serial}:" />
<h:outputText value="#{twoFaUserBean.createTokenResponse.detail.serial}"/>
<p:outputLabel for="@next" value="#{messages.twofa_code}:" />
<p:inputText id="totpText" value="#{twoFaUserBean.totpCode}"/>
</h:panelGrid>
<p:commandButton id="checkTotpButton" action="#{twoFaUserBean.checkAuthenticatorToken()}" value="#{messages.check}"
update="totpResponsePanel" />
</h:panelGroup>
</p:panel>
</p:dialog>
<p:dialog header="#{messages.twofa_create_yubico_token}"
widgetVar="addYubicoDlg" id="addYubicoDlgId" modal="true" closable="false" closeOnEscape="true"
showEffect="fade" hideEffect="fade">
<p:ajax event="close" update="@form" />
<div class="panel" style="width:360px;">
<h:outputText value="#{messages.twofa_create_yubico_token_desc}" />
</div>
<p:panel id="yubicoResponsePanel">
<h:panelGrid columns="2">
<p:outputLabel for="@next" value="#{messages.twofa_code}:" />
<p:inputText id="yubicoText" value="#{twoFaUserBean.yubicoCode}"/>
</h:panelGrid>
<p:commandButton id="yubicoStartButton" action="#{twoFaUserBean.createYubicoToken()}" value="#{messages.start}"
update="yubicoResponsePanel"/>
</p:panel>
</p:dialog>
<p:dialog header="#{messages.twofa_create_backuptan_token}"
widgetVar="addBackuptanDlg" id="addBackuptanDlgId" modal="true" closable="false" closeOnEscape="true"
showEffect="fade" hideEffect="fade">
</p:dialog>
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" closable="false" closeOnEscape="true">
<p:commandButton value="#{messages.yes}" type="button" styleClass="ui-confirmdialog-yes" />
<p:commandButton value="#{messages.no}" type="button" styleClass="ui-confirmdialog-no" />
</p:confirmDialog>
<p:defaultCommand target="yubicoStartButton" scope="addYubicoDlgId"/>
<p:defaultCommand target="checkTotpButton" scope="addTotpDlgId"/>
</h:form>
</ui:define>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment