Skip to content

Commit

Permalink
Merge pull request #39 from privacyidea/21-feature-send-empty-pass
Browse files Browse the repository at this point in the history
21 feature send empty pass
  • Loading branch information
lukasmatusiewicz authored Oct 24, 2023
2 parents e54edc8 + 0ac83d6 commit 0bfce13
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 109 deletions.
34 changes: 18 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Updating following parameters is required to ensure at least the very basic func
- `privacyidea.plugin_version`
- `privacyidea.server_url`
- `privacyidea.verify_ssl`
- `privacyidea.authentication_flow`

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`.
Expand All @@ -34,22 +35,23 @@ Note: Example of this configuration contains the *privacyidea.properties* file (

The different configuration parameters are explained in the following table:

| Configuration | Explanation |
|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `privacyidea.plugin_version` | The actual plugin version which will be forwarded to the privacyIDEA. |
| `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.polling_interval` | Decide after how many seconds the form should be reloaded, to check if the push token was confirmed. Default is 2. |
| `privacyidea.debug` | Set this parameter to true to see the debug messages in the `idp-process.log`. |
| Configuration | Explanation |
|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `privacyidea.plugin_version` | The actual plugin version which will be forwarded to the privacyIDEA. |
| `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.authentication_flow` | Choose one of three possible options:<br>`default` - standard authentication flow,<br>`triggerChallenge` - triggers all challenges beforehand using the provided service account. Required additional parameters: *privacyidea.service_name*, *privacyidea.service_pass* (see below),<br>`sendStaticPass` - performs the privacyIDEA server request automatically beforehand using the provided static password. Required additional parameter: *privacyidea.static_pass* (see below). |
| `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.static_pass` | The password which should be use in the `sendStaticPass` authentication flow. <br/>Note: You can also leave it empty to perform the privacyIDEA server request with empty pass (useful in some scenarios). |
| `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.polling_interval` | Decide after how many seconds the form should be reloaded, to check if the push token was confirmed. Default is 2. |
| `privacyidea.debug` | Set this parameter to true to see the debug messages in the `idp-process.log`. |

### Log check:
- **Main log: `$idp_install_path/logs/idp-process.log`.**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.privacyidea.action;

import java.util.Map;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.servlet.http.HttpServletRequest;
import org.opensaml.profile.action.ActionSupport;
import org.opensaml.profile.context.ProfileRequestContext;
import org.privacyidea.PIResponse;
import org.privacyidea.context.PIContext;
import org.privacyidea.context.PIServerConfigContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AlternativeAuthenticationFlows extends AbstractChallengeResponseAction
{
private static final Logger LOGGER = LoggerFactory.getLogger(AlternativeAuthenticationFlows.class);

public AlternativeAuthenticationFlows() {}

@Override
protected final void doExecute(@Nonnull ProfileRequestContext profileRequestContext, @Nonnull PIContext piContext, @Nonnull PIServerConfigContext piServerConfigContext)
{
if (piServerConfigContext.getConfigParams().getAuthenticationFlow().equals("triggerChallenge"))
{
if (debug)
{
LOGGER.info("{} Authentication flow - triggerChallenge.", this.getLogPrefix());
}

HttpServletRequest request = Objects.requireNonNull(this.getHttpServletRequestSupplier()).get();
Map<String, String> headers = this.getHeadersToForward(request);
PIResponse piResponse = privacyIDEA.triggerChallenges(piContext.getUsername(), headers);

if (piResponse != null)
{
if (piResponse.error != null)
{
LOGGER.error("{} privacyIDEA server error: {}!", this.getLogPrefix(), piResponse.error.message);
ActionSupport.buildEvent(profileRequestContext, "AuthenticationException");
return;
}

if (!piResponse.multichallenge.isEmpty())
{
if (debug)
{
LOGGER.info("{} Extracting the form data from triggered challenges...", this.getLogPrefix());
}
extractChallengeData(piResponse);
}
}
else
{
LOGGER.error("{} triggerChallenge failed. Response was null. Fallback to standard procedure.", this.getLogPrefix());
}
}
else if (piServerConfigContext.getConfigParams().getAuthenticationFlow().equals("sendStaticPass"))
{
if (debug)
{
LOGGER.info("{} Authentication flow - sendStaticPass.", this.getLogPrefix());
}

if (piServerConfigContext.getConfigParams().getStaticPass() == null)
{
LOGGER.error("{} Static pass isn't set. Fallback to default authentication flow...", this.getLogPrefix());
}
else
{
// Call /validate/check with a static pass from the configuration
// This could already end the authentication if the "passOnNoToken" policy is set.
// Otherwise, it might trigger the challenges.
HttpServletRequest request = Objects.requireNonNull(this.getHttpServletRequestSupplier()).get();
Map<String, String> headers = this.getHeadersToForward(request);
PIResponse piResponse = privacyIDEA.validateCheck(piContext.getUsername(), piServerConfigContext.getConfigParams().getStaticPass(), headers);

if (piResponse != null)
{
if (piResponse.error != null)
{
LOGGER.error("{} privacyIDEA server error: {}!", this.getLogPrefix(), piResponse.error.message);
ActionSupport.buildEvent(profileRequestContext, "AuthenticationException");
return;
}

if (piResponse.value)
{
if (debug)
{
LOGGER.info("{} Authentication succeeded!", this.getLogPrefix());
}
ActionSupport.buildEvent(profileRequestContext, "success");
}

if (!piResponse.multichallenge.isEmpty())
{
extractChallengeData(piResponse);
}
}
}
}
else
{
if (debug)
{
LOGGER.info("{} Authentication flow: default.", this.getLogPrefix());
}
}
}
}
Loading

0 comments on commit 0bfce13

Please sign in to comment.