[SIDP-291] - Update libs for 2.1.3 release
[SIDP-306] - Remove ClientCertAuth rule from SAML 2 SSO SecurityPolicy in relying-party.xml
[SIDP-310] - Change default relying-party.xml settings for SAML 2 profiles' encryptNameIds parameter from "conditional" to "never"
+[SIDP-315] - Credential provided by UsernamePasswordLogin handler as attribute
[SIDP-318] - IdP erroneously logs many normal events as errors
[SIDP-322] - Exception thrown when SP requests a particular authentication method that is not configured
/** Manager responsible for handling authentication requests. */
public class AuthenticationEngine extends HttpServlet {
+ /**
+ * Name of the Servlet config init parameter that indicates whether the public credentials of a {@link Subject} are
+ * retained after authentication.
+ */
+ public static final String RETAIN_PUBLIC_CREDENTIALS = "retainSubjectsPublicCredentials";
+
+ /**
+ * Name of the Servlet config init parameter that indicates whether the private credentials of a {@link Subject} are
+ * retained after authentication.
+ */
+ public static final String RETAIN_PRIVATE_CREDENTIALS = "retainSubjectsPrivateCredentials";
+
/** Name of the Servlet config init parameter that holds the partition name for login contexts. */
public static final String LOGIN_CONTEXT_PARTITION_NAME_INIT_PARAM_NAME = "loginContextPartitionName";
/** ID generator. */
private static IdentifierGenerator idGen;
+ /** Whether the public credentials of a {@link Subject} are retained after authentication. */
+ private boolean retainSubjectsPublicCredentials;
+
+ /** Whether the private credentials of a {@link Subject} are retained after authentication. */
+ private boolean retainSubjectsPrivateCredentials;
+
/** Profile handler manager. */
private IdPProfileHandlerManager handlerManager;
public void init(ServletConfig config) throws ServletException {
super.init(config);
+ String retain = DatatypeHelper.safeTrimOrNullString(config.getInitParameter(RETAIN_PRIVATE_CREDENTIALS));
+ if (retain != null) {
+ retainSubjectsPrivateCredentials = Boolean.parseBoolean(retain);
+ } else {
+ retainSubjectsPrivateCredentials = false;
+ }
+
+ retain = DatatypeHelper.safeTrimOrNullString(config.getInitParameter(RETAIN_PUBLIC_CREDENTIALS));
+ if (retain != null) {
+ retainSubjectsPublicCredentials = Boolean.parseBoolean(retain);
+ } else {
+ retainSubjectsPublicCredentials = false;
+ }
+
String handlerManagerId = config.getInitParameter("handlerManagerId");
if (DatatypeHelper.isEmpty(handlerManagerId)) {
handlerManagerId = "shibboleth.HandlerManager";
} else {
possibleLoginHandlers.remove(AuthnContext.PREVIOUS_SESSION_AUTHN_CTX);
if (possibleLoginHandlers.isEmpty()) {
- LOG.info("No authentication mechanism available for use with relying party '{}'", loginContext.getRelyingPartyId());
+ LOG.info("No authentication mechanism available for use with relying party '{}'", loginContext
+ .getRelyingPartyId());
throw new AuthenticationException();
}
Entry<String, LoginHandler> chosenLoginHandler = possibleLoginHandlers.entrySet().iterator().next();
protected void validateSuccessfulAuthentication(LoginContext loginContext, HttpServletRequest httpRequest,
String authenticationMethod) throws AuthenticationException {
LOG.debug("Validating authentication was performed successfully");
-
+
String errorMessage = DatatypeHelper.safeTrimOrNullString((String) httpRequest
.getAttribute(LoginHandler.AUTHENTICATION_ERROR_KEY));
if (errorMessage != null) {
}
/**
- * Merges the principals and public and private credentials from two subjects into a new subject.
+ * Merges the two {@link Subject}s in to a new {@link Subject}. The new subjects contains all the {@link Principal}s
+ * from both subjects. If {@link #retainSubjectsPrivateCredentials} is true then the new subject will contain all
+ * the private credentials from both subjects, if not the new subject will not contain private credentials. If
+ * {@link #retainSubjectsPublicCredentials} is true then the new subject will contain all the public credentials
+ * from both subjects, if not the new subject will not contain public credentials.
*
* @param subject1 first subject to merge, may be null
* @param subject2 second subject to merge, may be null
if (subject1 == null && subject2 == null) {
return new Subject();
}
-
+
if (subject1 == null) {
return subject2;
}
principals.addAll(subject2.getPrincipals());
Set<Object> publicCredentials = new HashSet<Object>(3);
- publicCredentials.addAll(subject1.getPublicCredentials());
- publicCredentials.addAll(subject2.getPublicCredentials());
+ if (retainSubjectsPublicCredentials) {
+ LOG.debug("Merging in subjects public credentials");
+ publicCredentials.addAll(subject1.getPublicCredentials());
+ publicCredentials.addAll(subject2.getPublicCredentials());
+ }
Set<Object> privateCredentials = new HashSet<Object>(3);
- privateCredentials.addAll(subject1.getPrivateCredentials());
- privateCredentials.addAll(subject2.getPrivateCredentials());
+ if (retainSubjectsPrivateCredentials) {
+ LOG.debug("Merging in subjects private credentials");
+ privateCredentials.addAll(subject1.getPrivateCredentials());
+ privateCredentials.addAll(subject2.getPrivateCredentials());
+ }
return new Subject(false, principals, publicCredentials, privateCredentials);
}
/*
- * Copyright 2006 [University Corporation for Advanced Internet Development, Inc.
+ * Copyright 2006 University Corporation for Advanced Internet Development, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import edu.internet2.middleware.shibboleth.idp.authn.UsernamePrincipal;
/**
- * This Servlet should be protected by a filter which populates REMOTE_USER. The Servlet will then set the remote user
- * field in a LoginContext.
+ * This Servlet authenticates a user via JAAS. The user's credential is always added to the returned {@link Subject} as
+ * a {@link UsernamePasswordCredential} within the subject's private credentials.
*/
public class UsernamePasswordLoginServlet extends HttpServlet {
/** Class logger. */
private final Logger log = LoggerFactory.getLogger(UsernamePasswordLoginServlet.class);
- /** Whether to store a user's credentials within the {@link Subject}. */
- private boolean storeCredentialsInSubject;
-
/** Name of JAAS configuration used to authenticate users. */
private String jaasConfigName = "ShibUserPassAuth";
/** Parameter name to indicate login failure. */
private final String failureParam = "loginFailed";
-
- /** Parameter name to indicate the login credentials should be stored in the Subject private credential set. */
- private final String storeCredentials = "storeCredentialsInSubject";
/** HTTP request parameter containing the user name. */
private final String usernameAttribute = "j_username";
/** {@inheritDoc} */
public void init(ServletConfig config) throws ServletException {
super.init(config);
-
+
if (getInitParameter(jaasInitParam) != null) {
jaasConfigName = getInitParameter(jaasInitParam);
}
-
+
if (getInitParameter(loginPageInitParam) != null) {
loginPage = getInitParameter(loginPageInitParam);
}
- if(!loginPage.startsWith("/")){
+ if (!loginPage.startsWith("/")) {
loginPage = "/" + loginPage;
}
-
- if(getInitParameter(storeCredentials) != null){
- storeCredentialsInSubject = Boolean.parseBoolean(getInitParameter(storeCredentials));
- }
}
/** {@inheritDoc} */
*/
protected void redirectToLoginPage(HttpServletRequest request, HttpServletResponse response,
List<Pair<String, String>> queryParams) {
-
+
String requestContext = DatatypeHelper.safeTrimOrNullString(request.getContextPath());
- if(requestContext == null){
+ if (requestContext == null) {
requestContext = "/";
}
request.setAttribute("actionUrl", requestContext + request.getServletPath());
- if(queryParams != null){
- for(Pair<String, String> param : queryParams){
+ if (queryParams != null) {
+ for (Pair<String, String> param : queryParams) {
request.setAttribute(param.getFirst(), param.getSecond());
}
}
-
+
try {
request.getRequestDispatcher(loginPage).forward(request, response);
log.debug("Redirecting to login page {}", loginPage);
} catch (IOException ex) {
log.error("Unable to redirect to login page.", ex);
- }catch (ServletException ex){
- log.error("Unable to redirect to login page.", ex);
+ } catch (ServletException ex) {
+ log.error("Unable to redirect to login page.", ex);
}
}
Set<Object> publicCredentials = loginSubject.getPublicCredentials();
Set<Object> privateCredentials = loginSubject.getPrivateCredentials();
- if (storeCredentialsInSubject) {
- privateCredentials.add(new UsernamePasswordCredential(username, password));
- }
+ privateCredentials.add(new UsernamePasswordCredential(username, password));
Subject userSubject = new Subject(false, principals, publicCredentials, privateCredentials);
request.setAttribute(LoginHandler.SUBJECT_KEY, userSubject);
<servlet-mapping>
<servlet-name>ProfileRequestDispatcher</servlet-name>
<url-pattern>/profile/*</url-pattern>
- </servlet-mapping>
-
- <servlet>
- <servlet-name>Status</servlet-name>
- <servlet-class>edu.internet2.middleware.shibboleth.idp.StatusServlet</servlet-class>
- <load-on-startup>2</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>Status</servlet-name>
- <url-pattern>/status</url-pattern>
- </servlet-mapping>
-
- <!-- Send request to the EntityID to the SAML metadata handler. -->
- <servlet>
- <servlet-name>shibboleth_jsp</servlet-name>
- <jsp-file>/shibboleth.jsp</jsp-file>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>shibboleth_jsp</servlet-name>
- <url-pattern>/shibboleth</url-pattern>
</servlet-mapping>
<!-- Authentication Engine Entry Point -->
<servlet>
<servlet-name>AuthenticationEngine</servlet-name>
<servlet-class>edu.internet2.middleware.shibboleth.idp.authn.AuthenticationEngine</servlet-class>
+
+ <!-- Whether public credentials returned by a login handler are retained in the subject. -->
+ <!--
+ <init-param>
+ <param-name>retainSubjectsPublicCredentials</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ -->
+
+ <!-- Whether private credentials returned by a login handler are retained in the subject. -->
+ <!--
+ <init-param>
+ <param-name>retainSubjectsPrivateCredentials</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ -->
+
<load-on-startup>2</load-on-startup>
+
</servlet>
<servlet-mapping>
<url-pattern>/Authn/UserPassword</url-pattern>
</servlet-mapping>
+ <!-- Servlet for displaying IdP status. -->
+ <servlet>
+ <servlet-name>Status</servlet-name>
+ <servlet-class>edu.internet2.middleware.shibboleth.idp.StatusServlet</servlet-class>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Status</servlet-name>
+ <url-pattern>/status</url-pattern>
+ </servlet-mapping>
+
+
+ <!-- Send request to the EntityID to the SAML metadata handler. -->
+ <servlet>
+ <servlet-name>shibboleth_jsp</servlet-name>
+ <jsp-file>/shibboleth.jsp</jsp-file>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>shibboleth_jsp</servlet-name>
+ <url-pattern>/shibboleth</url-pattern>
+ </servlet-mapping>
+
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>