2015-08-06 00:39:47 +00:00
|
|
|
package org.keycloak.models;
|
|
|
|
|
2015-09-18 17:02:36 +00:00
|
|
|
import org.jboss.logging.Logger;
|
2015-08-06 00:39:47 +00:00
|
|
|
import org.keycloak.models.utils.Base32;
|
|
|
|
import org.keycloak.models.utils.HmacOTP;
|
|
|
|
|
2015-12-03 07:23:46 +00:00
|
|
|
import java.io.Serializable;
|
2015-09-18 17:02:36 +00:00
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
import java.net.URLEncoder;
|
2015-08-06 00:39:47 +00:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
|
|
* @version $Revision: 1 $
|
|
|
|
*/
|
2015-12-03 07:23:46 +00:00
|
|
|
public class OTPPolicy implements Serializable {
|
2015-08-06 00:39:47 +00:00
|
|
|
|
2015-09-18 17:02:36 +00:00
|
|
|
protected static final Logger logger = Logger.getLogger(OTPPolicy.class);
|
2015-08-06 00:39:47 +00:00
|
|
|
|
|
|
|
protected String type;
|
|
|
|
protected String algorithm;
|
|
|
|
protected int initialCounter;
|
|
|
|
protected int digits;
|
|
|
|
protected int lookAheadWindow;
|
2015-08-06 20:54:59 +00:00
|
|
|
protected int period;
|
2015-08-06 00:39:47 +00:00
|
|
|
|
|
|
|
private static final Map<String, String> algToKeyUriAlg = new HashMap<>();
|
|
|
|
|
|
|
|
static {
|
|
|
|
algToKeyUriAlg.put(HmacOTP.HMAC_SHA1, "SHA1");
|
|
|
|
algToKeyUriAlg.put(HmacOTP.HMAC_SHA256, "SHA256");
|
|
|
|
algToKeyUriAlg.put(HmacOTP.HMAC_SHA512, "SHA512");
|
|
|
|
}
|
|
|
|
|
|
|
|
public OTPPolicy() {
|
|
|
|
}
|
|
|
|
|
2015-08-06 20:54:59 +00:00
|
|
|
public OTPPolicy(String type, String algorithm, int initialCounter, int digits, int lookAheadWindow, int period) {
|
2015-08-06 00:39:47 +00:00
|
|
|
this.type = type;
|
|
|
|
this.algorithm = algorithm;
|
|
|
|
this.initialCounter = initialCounter;
|
|
|
|
this.digits = digits;
|
|
|
|
this.lookAheadWindow = lookAheadWindow;
|
2015-08-06 20:54:59 +00:00
|
|
|
this.period = period;
|
2015-08-06 00:39:47 +00:00
|
|
|
}
|
|
|
|
|
2015-08-06 20:54:59 +00:00
|
|
|
public static OTPPolicy DEFAULT_POLICY = new OTPPolicy(UserCredentialModel.TOTP, HmacOTP.HMAC_SHA1, 0, 6, 1, 30);
|
2015-08-06 00:39:47 +00:00
|
|
|
|
|
|
|
public String getType() {
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setType(String type) {
|
|
|
|
this.type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getAlgorithm() {
|
|
|
|
return algorithm;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setAlgorithm(String algorithm) {
|
|
|
|
this.algorithm = algorithm;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getInitialCounter() {
|
|
|
|
return initialCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setInitialCounter(int initialCounter) {
|
|
|
|
this.initialCounter = initialCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getDigits() {
|
|
|
|
return digits;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDigits(int digits) {
|
|
|
|
this.digits = digits;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getLookAheadWindow() {
|
|
|
|
return lookAheadWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setLookAheadWindow(int lookAheadWindow) {
|
|
|
|
this.lookAheadWindow = lookAheadWindow;
|
|
|
|
}
|
|
|
|
|
2015-08-06 20:54:59 +00:00
|
|
|
public int getPeriod() {
|
|
|
|
return period;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setPeriod(int period) {
|
|
|
|
this.period = period;
|
|
|
|
}
|
|
|
|
|
2015-09-18 17:02:36 +00:00
|
|
|
public String getKeyURI(RealmModel realm, UserModel user, String secret) {
|
2016-01-29 10:00:28 +00:00
|
|
|
try {
|
|
|
|
String displayName = realm.getDisplayName() != null && !realm.getDisplayName().isEmpty() ? realm.getDisplayName() : realm.getName();
|
|
|
|
String uri;
|
2015-08-06 00:39:47 +00:00
|
|
|
|
2016-01-29 10:00:28 +00:00
|
|
|
uri = "otpauth://" + type + "/" + URLEncoder.encode(user.getUsername(), "UTF-8") + "?secret=" +
|
|
|
|
Base32.encode(secret.getBytes()) + "&digits=" + digits + "&algorithm=" + algToKeyUriAlg.get(algorithm);
|
|
|
|
|
|
|
|
uri += "&issuer=" + URLEncoder.encode(displayName, "UTF-8");
|
2015-08-06 00:39:47 +00:00
|
|
|
|
2016-01-29 10:00:28 +00:00
|
|
|
if (type.equals(UserCredentialModel.HOTP)) {
|
|
|
|
uri += "&counter=" + initialCounter;
|
|
|
|
}
|
|
|
|
if (type.equals(UserCredentialModel.TOTP)) {
|
|
|
|
uri += "&period=" + period;
|
|
|
|
}
|
|
|
|
|
|
|
|
return uri;
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
2015-08-06 00:39:47 +00:00
|
|
|
}
|
|
|
|
}
|