Skip to content

Commit

Permalink
Merge pull request #29 from privacyidea/27-feature-auto-submit-after-…
Browse files Browse the repository at this point in the history
…x-digits-entered

27 feature: automatic form submitter
  • Loading branch information
lukasmatusiewicz authored Sep 28, 2023
2 parents be372c5 + 22ab4a9 commit 8180fea
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 14 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@ Otherwise, re-run the command from step 5.
- `privacyidea.forward_headers=header1,header2,header3`
- `privacyidea.debug=false`

The different configuration parameters that are available on the configuration page of the execution are explained in the following table:

| Configuration | Explanation |
|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `privacyidea.server_url` | The URL of your privacyIDEA server. This must to be reachable from the Shibboleth IdP server. |
| `privacyidea.realm` | This realm will be appended to all requests to the privacyIDEA. <br/>Note: Drop it to use the default realm. |
| `privacyidea.verify_ssl` | Choose if the Shibboleth should verify the SSL certificate of the privacyIDEA. <br/>Note: Always verify the SSL certificate in a productive environment! |
| `privacyidea.default_message` | Use this parameter to edit the default user message. |
| `privacyidea.otp_field_hint` | Use this parameter to edit the default placeholder for the OTP input field. |
| `privacyidea.triggerchallenge` | Set this to true, if all challenges should be triggered beforehand using the provided service account. <br/>Note: This config option require to update the `privacyidea.service_name` and `privacyidea.service_pass` parameters. |
| `privacyidea.service_name` | The username of the service account required by the `triggerchallenge` config option. <br/>Note: Please make sure, that the service account has the correct rights. |
| `privacyidea.service_pass` | The password of your service account required by the `triggerchallenge` config option. |
| `privacyidea.service_realm` | Specify a separate service account's realm if needed. <br/>Note: If the service account is located in the same realm as the users, it is sufficient to specify the realm in the `privacyidea.realm` parameter. |
| `privacyidea.forward_headers` | Set the headers that should be forwarded to the privacyIDEA. <br/>Note: If some header doesn't exist or has no value, will be ignored. <br/>Note: The header names should be separated by a comma (","). |
| `privacyidea.otp_length` | If you want to turn on the form-auto-submit function after x number of characters are entered into the OTP input field, set the expected OTP length here. <br/>Note: Only digits as the parameter's value allowed here. |
| `privacyidea.debug` | Set this parameter to true to see the debug messages in the `idp-process.log`. |


2. **Add the privacyIDEA subflow to the MFA flow.**<br>
- Path to the MFA flow configuration file: `$idp_install_path/conf/authn/mfa-authn-config.xml`.
- Example of the *util:map* is located in the resources at the end of the *privacyidea.properties* file (`/privacyIDEA-impl/src/resources/org/privacyidea/conf/authn/privacyidea.properties`).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,4 @@ public void error(Throwable throwable)
LOGGER.error("PrivacyIDEA Client: " + throwable);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class InitializePIContext extends AbstractAuthenticationAction
private String forwardHeaders;
@Nullable
private String otpFieldHint;
@Nullable
private String otpLength;
private boolean debug;

public InitializePIContext()
Expand All @@ -58,12 +60,29 @@ protected void doExecute(@NotNull ProfileRequestContext profileRequestContext, @
}
else
{
Config configParams = new Config(serverURL, realm, verifySSL, triggerChallenge, serviceName, servicePass, serviceRealm, forwardHeaders, debug);
Config configParams = new Config(serverURL, realm, verifySSL, triggerChallenge, serviceName, servicePass, serviceRealm, forwardHeaders, otpLength, debug);
PIServerConfigContext piServerConfigContext = new PIServerConfigContext(configParams);
log.info("{} Create PIServerConfigContext {}", this.getLogPrefix(), piServerConfigContext);
authenticationContext.addSubcontext(piServerConfigContext);
PIContext piContext;

PIContext piContext = new PIContext(user, defaultMessage, otpFieldHint);
if (otpLength != null)
{
try
{
int otpLengthToInt = Integer.parseInt(otpLength);
piContext = new PIContext(user, defaultMessage, otpFieldHint, otpLengthToInt);
}
catch (NumberFormatException e)
{
log.info("{} Config option \"otp_length\": Wrong format. Only digits allowed.", getLogPrefix());
piContext = new PIContext(user, defaultMessage, otpFieldHint, null);
}
}
else
{
piContext = new PIContext(user, defaultMessage, otpFieldHint, null);
}
log.info("{} Create PIContext {}", this.getLogPrefix(), piContext);
authenticationContext.addSubcontext(piContext);
}
Expand All @@ -85,14 +104,26 @@ private User getUser(@Nonnull ProfileRequestContext profileRequestContext)

// Spring bean property setters
public void setServerURL(@Nonnull String serverURL) {this.serverURL = serverURL;}
public void setRealm(@Nonnull String realm) {this.realm = realm;}

public void setRealm(@Nullable String realm) {this.realm = realm;}

public void setVerifySSL(boolean verifySSL) {this.verifySSL = verifySSL;}
public void setDefaultMessage(@Nonnull String defaultMessage) {this.defaultMessage = defaultMessage;}
public void setOtpFieldHint(@Nonnull String otpFieldHint) {this.otpFieldHint = otpFieldHint;}

public void setDefaultMessage(@Nullable String defaultMessage) {this.defaultMessage = defaultMessage;}

public void setOtpFieldHint(@Nullable String otpFieldHint) {this.otpFieldHint = otpFieldHint;}

public void setTriggerChallenge(boolean triggerChallenge) {this.triggerChallenge = triggerChallenge;}
public void setServiceName(@Nonnull String serviceName) {this.serviceName = serviceName;}
public void setServicePass(@Nonnull String servicePass) {this.servicePass = servicePass;}
public void setServiceRealm(@Nonnull String serviceRealm) {this.serviceRealm = serviceRealm;}
public void setForwardHeaders(@Nonnull String forwardHeaders) {this.forwardHeaders = forwardHeaders;}

public void setServiceName(@Nullable String serviceName) {this.serviceName = serviceName;}

public void setServicePass(@Nullable String servicePass) {this.servicePass = servicePass;}

public void setServiceRealm(@Nullable String serviceRealm) {this.serviceRealm = serviceRealm;}

public void setForwardHeaders(@Nullable String forwardHeaders) {this.forwardHeaders = forwardHeaders;}

public void setOtpLength(@Nullable String otpLength) {this.otpLength = otpLength;}

public void setDebug(boolean debug) {this.debug = debug;}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ public class Config
private final String serviceRealm;
@Nullable
private final String forwardHeaders;
@Nullable
private final String otpLength;

public Config(@Nonnull String serverURL, @Nullable String realm, boolean verifySSL, boolean triggerChallenge, @Nullable String serviceName, @Nullable String servicePass, @Nullable String serviceRealm, @Nullable String forwardHeaders, boolean debug)
public Config(@Nonnull String serverURL, @Nullable String realm, boolean verifySSL, boolean triggerChallenge, @Nullable String serviceName, @Nullable String servicePass, @Nullable String serviceRealm, @Nullable String forwardHeaders, @Nullable String otpLength, boolean debug)
{
this.serverURL = serverURL;
this.realm = realm;
Expand All @@ -31,6 +33,7 @@ public Config(@Nonnull String serverURL, @Nullable String realm, boolean verifyS
this.servicePass = servicePass;
this.serviceRealm = serviceRealm;
this.forwardHeaders = forwardHeaders;
this.otpLength = otpLength;
this.debug = debug;
}

Expand Down Expand Up @@ -81,6 +84,12 @@ public String getForwardHeaders()
return forwardHeaders;
}

@Nullable
public String getOtpLength()
{
return otpLength;
}

public boolean getDebug()
{
return debug;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,34 @@ public class PIContext extends BaseContext
private String transactionID = null;
@Nonnull
private final String otpFieldHint;
@Nullable
private final Integer otpLength;

public PIContext(@Nonnull User user, @Nullable String defaultMessage, @Nullable String otpFieldHint)
public PIContext(@Nonnull User user, @Nullable String defaultMessage, @Nullable String otpFieldHint, @Nullable Integer otpLength)
{
this.user = Constraint.isNotNull(user, "User cannot be null.");
this.defaultMessage = Objects.requireNonNullElse(defaultMessage, "Please enter the OTP!");
this.otpFieldHint = Objects.requireNonNullElse(otpFieldHint, "OTP");
this.otpLength = otpLength;
}

// Getters and Setters
@Nonnull
public String getUsername() {return user.getUsername();}

public void setMessage(String message) {this.message = message;}

@Nonnull
public String getMessage() {return (!message.isEmpty()) ? message : defaultMessage;}

public void setTransactionID(@Nonnull String transactionID) {this.transactionID = transactionID;}

@Nullable
public String getTransactionID() {return transactionID;}

@Nonnull
public String getOtpFieldHint() {return otpFieldHint;}

@Nullable
public Integer getOtpLength() {return otpLength;}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
p:servicePass="%{privacyidea.service_pass:#{null}}"
p:serviceRealm="%{privacyidea.service_realm:#{null}}"
p:forwardHeaders="%{privacyidea.forward_headers:#{null}}"
p:otpLength="%{privacyidea.otp_length:#{null}}"
p:debug="%{privacyidea.debug:false}"/>

<bean id="piAuthenticator" class="org.privacyidea.action.PrivacyIDEAAuthenticator" scope="prototype"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#privacyidea.service_pass=null
#privacyidea.service_realm=null
#privacyidea.forward_headers=null
#privacyidea.otp_length=null
#privacyidea.debug=false

##################################
Expand Down
14 changes: 12 additions & 2 deletions privacyIDEA-impl/src/main/resources/org/privacyidea/views/main.vm
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,20 @@
<br>
</div>

<script>
function autoSubmit(inputObject, otpLength)
{
if (otpLength != null && inputObject.value.length === otpLength)
{
document.getElementById("pi-form-submit-button").click();
}
}
</script>

<div class="form-element-wrapper">
<input id="pi_otp_input" class="form-element form-field" name="pi_otp_input" type="password" autofocus placeholder=$piContext.getOtpFieldHint() value="">
<input id="pi_otp_input" class="form-element form-field" name="pi_otp_input" type="password" onKeyUp="autoSubmit(this, $piContext.getOtpLength())" autofocus placeholder=$piContext.getOtpFieldHint() value="">
<br>
<button class="form-element form-button" type="submit" name="_eventId_proceed">Submit</button>
<button class="form-element form-button" id="pi-form-submit-button" type="submit" name="_eventId_proceed">Submit</button>
<br><br>
</div>
</form>
Expand Down

0 comments on commit 8180fea

Please sign in to comment.