Skip to content

Commit

Permalink
Merge pull request #26 from privacyidea/23-feature-forward-headers
Browse files Browse the repository at this point in the history
23 feature forward headers
  • Loading branch information
nilsbehlen authored Sep 26, 2023
2 parents c0e7120 + affa5c4 commit be372c5
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 12 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
2. **Open the terminal and run: `sudo -i` for admin rights.**
3. **Enable the MFA Module: `$idp_install_path/bin/module.sh -t idp.authn.MFA || $idp_install_path/bin/module.sh -e idp.authn.MFA`.**
4. **Check if the MFA Module is activated: `$idp_install_path/bin/module.sh -l`.**
5. **Install the privacyIDEA Plugin: `$idp_install_path/bin/plugin.sh -i path/to/zip/from/step/1 --noCheck`.**
6. **Check if the privacyIDEA Plugin is installed correctly: `$idp_install_path/bin/plugin.sh -l`.**<br>
5. **Install the privacyIDEA Plugin: `$idp_install_path/bin/plugin.sh -i path/to/zip/from/step/1 --noCheck`**<br>
The installer will also install and enable the privacyIDEA Module. You can check it by repeating the step 4.
6. **Check if the privacyIDEA Plugin is installed correctly: `$idp_install_path/bin/plugin.sh -l`**<br>
If you see the *org.privacyidea.privacyIDEA* on the list, the plugin is installed successfully.<br>
Otherwise, re-run the command from step 5.

### Configuration:
1. **Create the *privacyidea.properties* file in: `$idp_install_path/config/authn/`.**<br>
1. **Create the *privacyidea.properties* file in: `$idp_install_path/config/authn/`**<br>
You can find a template in the resources in this repo: `/privacyIDEA-impl/src/resources/org/privacyidea/conf/authn/`.<br>
The config file should contain the following configuration variables:
- `privacyidea.server_url=https://localhost`
Expand All @@ -29,6 +30,7 @@ Otherwise, re-run the command from step 5.
- `privacyidea.service_name=service`
- `privacyidea.service_pass=service`
- `privacyidea.service_realm=defrealm`
- `privacyidea.forward_headers=header1,header2,header3`
- `privacyidea.debug=false`

2. **Add the privacyIDEA subflow to the MFA flow.**<br>
Expand All @@ -37,8 +39,8 @@ Otherwise, re-run the command from step 5.
- Remember to activate the MFA flow.

### Log check:
- **Main log: `$idp_install_path/logs/idp-process.log`.**
- **Warn and error log: `$idp_install_path/logs/idp-warn.log`.**
- **Main log: `$idp_install_path/logs/idp-process.log`**
- **Warn and error log: `$idp_install_path/logs/idp-warn.log`**

### Plugin update:
To update the plugin, repeat the installation process with the new archive data.
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ org.privacyidea.privacyIDEA.versions = 0.1.0 0.2.0
#org.privacyidea.privacyIDEA.downloadURL.%{version} = https://lancelot.netknights.it/owncloud/s/XEuk1kV3veI9B7X?path=%2F0.0.1
org.privacyidea.privacyIDEA.baseName.%{version} = idp-plugin-privacyIDEA-dist-%{version}

org.privacyidea.privacyIDEA.idpVersionMax.0.1.0 = 5.0.0
org.privacyidea.privacyIDEA.idpVersionMin.0.1.0 = 4.3.0
org.privacyidea.privacyIDEA.idpVersionMax.%{version} = 5.0.0
org.privacyidea.privacyIDEA.idpVersionMin.%{version} = 4.3.0
# Support Level (OutOfDate or Current)
org.privacyidea.privacyIDEA.supportLevel.0.1.0 = OutOfDate
org.privacyidea.privacyIDEA.supportLevel.0.2.0 = Current
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package org.privacyidea.action;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.servlet.http.HttpServletRequest;
import net.shibboleth.idp.authn.context.AuthenticationContext;
import net.shibboleth.idp.profile.AbstractProfileAction;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
Expand All @@ -10,8 +17,8 @@
import org.privacyidea.IPILogger;
import org.privacyidea.PIResponse;
import org.privacyidea.PrivacyIDEA;
import org.privacyidea.context.PIServerConfigContext;
import org.privacyidea.context.PIContext;
import org.privacyidea.context.PIServerConfigContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -102,6 +109,46 @@ protected void extractChallengeData(@Nonnull PIResponse piResponse)
}
}

/**
* Search for the configured headers in HttpServletRequest and return all found with their values.
*
* @param request http servlet request
* @return headers to forward with their values
*/
protected Map<String, String> getHeadersToForward(HttpServletRequest request)
{
Map<String, String> headersToForward = new LinkedHashMap<>();
if (piServerConfigContext.getConfigParams().getForwardHeaders() != null && !piServerConfigContext.getConfigParams().getForwardHeaders().isEmpty())
{
String cleanHeaders = piServerConfigContext.getConfigParams().getForwardHeaders().replaceAll(" ", "");
List<String> headersList = List.of(cleanHeaders.split(","));

for (String headerName : headersList.stream().distinct().collect(Collectors.toList()))
{
List<String> headerValues = new ArrayList<>();
Enumeration<String> e = request.getHeaders(headerName);
if (e != null)
{
while (e.hasMoreElements())
{
headerValues.add(e.nextElement());
}
}

if (!headerValues.isEmpty())
{
String temp = String.join(",", headerValues);
headersToForward.put(headerName, temp);
}
else
{
LOGGER.info("{} No values for header \"" + headerName + "\" found.", this.getLogPrefix());
}
}
}
return headersToForward;
}

// Logger implementation
@Override
public void log(String message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class InitializePIContext extends AbstractAuthenticationAction
@Nullable
private String serviceRealm;
@Nullable
private String forwardHeaders;
@Nullable
private String otpFieldHint;
private boolean debug;

Expand All @@ -56,7 +58,7 @@ protected void doExecute(@NotNull ProfileRequestContext profileRequestContext, @
}
else
{
Config configParams = new Config(serverURL, realm, verifySSL, triggerChallenge, serviceName, servicePass, serviceRealm, debug);
Config configParams = new Config(serverURL, realm, verifySSL, triggerChallenge, serviceName, servicePass, serviceRealm, forwardHeaders, debug);
PIServerConfigContext piServerConfigContext = new PIServerConfigContext(configParams);
log.info("{} Create PIServerConfigContext {}", this.getLogPrefix(), piServerConfigContext);
authenticationContext.addSubcontext(piServerConfigContext);
Expand Down Expand Up @@ -91,5 +93,6 @@ private User getUser(@Nonnull ProfileRequestContext profileRequestContext)
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 setDebug(boolean debug) {this.debug = debug;}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.privacyidea.action;

import java.util.Map;
import javax.annotation.Nonnull;
import javax.servlet.http.HttpServletRequest;
import org.opensaml.profile.action.ActionSupport;
Expand All @@ -20,6 +21,7 @@ public PrivacyIDEAAuthenticator() {}
protected final void doExecute(@Nonnull ProfileRequestContext profileRequestContext, @Nonnull PIContext piContext, @Nonnull PIServerConfigContext piServerConfigContext)
{
HttpServletRequest request = this.getHttpServletRequest();
Map<String, String> headers = this.getHeadersToForward(request);
if (request == null)
{
LOGGER.error("{} Profile action does not contain an HttpServletRequest.", this.getLogPrefix());
Expand All @@ -35,7 +37,7 @@ protected final void doExecute(@Nonnull ProfileRequestContext profileRequestCont

if (otp != null)
{
piResponse = privacyIDEA.validateCheck(piContext.getUsername(), otp, piContext.getTransactionID(), null);
piResponse = privacyIDEA.validateCheck(piContext.getUsername(), otp, piContext.getTransactionID(), headers);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.privacyidea.action;

import java.util.LinkedHashMap;
import java.util.Map;
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;
Expand All @@ -25,7 +28,18 @@ protected final void doExecute(@Nonnull ProfileRequestContext profileRequestCont
LOGGER.info("{} Triggering challenges...", this.getLogPrefix());
}

PIResponse triggerredResponse = privacyIDEA.triggerChallenges(piContext.getUsername());
HttpServletRequest request = this.getHttpServletRequest();
Map<String, String> headers = new LinkedHashMap<>();
if (request != null)
{
headers = this.getHeadersToForward(request);
}
else
{
LOGGER.info("{} Failed to attach headers to triggerchallenge request because HTTP Servlet Request was null", this.getLogPrefix());
}

PIResponse triggerredResponse = privacyIDEA.triggerChallenges(piContext.getUsername(), headers);

if (triggerredResponse != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ public class Config
private final String servicePass;
@Nullable
private final String serviceRealm;
@Nullable
private final String forwardHeaders;

public Config(@Nonnull String serverURL, @Nullable String realm, boolean verifySSL, boolean triggerChallenge, @Nullable String serviceName, @Nullable String servicePass, @Nullable String serviceRealm, 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, boolean debug)
{
this.serverURL = serverURL;
this.realm = realm;
Expand All @@ -28,6 +30,7 @@ public Config(@Nonnull String serverURL, @Nullable String realm, boolean verifyS
this.serviceName = serviceName;
this.servicePass = servicePass;
this.serviceRealm = serviceRealm;
this.forwardHeaders = forwardHeaders;
this.debug = debug;
}

Expand Down Expand Up @@ -72,6 +75,12 @@ public String getServiceRealm()
return serviceRealm;
}

@Nullable
public String getForwardHeaders()
{
return forwardHeaders;
}

public boolean getDebug()
{
return debug;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
p:serviceName="%{privacyidea.service_name:#{null}}"
p:servicePass="%{privacyidea.service_pass:#{null}}"
p:serviceRealm="%{privacyidea.service_realm:#{null}}"
p:forwardHeaders="%{privacyidea.forward_headers:#{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 @@ -11,6 +11,7 @@
#privacyidea.service_name=null
#privacyidea.service_pass=null
#privacyidea.service_realm=null
#privacyidea.forward_headers=null
#privacyidea.debug=false

##################################
Expand Down

0 comments on commit be372c5

Please sign in to comment.