[java-idp-plugin-totp] branch master updated: Bug fixing and error handling changes, initial views and messages.
Scott Cantor
cantor.2 at osu.edu
Thu Aug 6 17:30:12 UTC 2020
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-idp-plugin-totp.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-plugin-totp.git;a=commit;h=65e6ceb0af37ddb2cc96aed42a7d0cfcf07881c4
The following commit(s) were added to refs/heads/master by this push:
new 65e6ceb Bug fixing and error handling changes, initial views and messages.
65e6ceb is described below
commit 65e6ceb0af37ddb2cc96aed42a7d0cfcf07881c4
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Aug 6 13:31:29 2020 -0400
Bug fixing and error handling changes, initial views and messages.
---
.../totp/impl/AbstractTOTPCredentialValidator.java | 16 ++--
.../totp/impl/AbstractTOTPExtractionAction.java | 24 ++++-
.../totp/impl/AttributeResolverSeedSource.java | 3 +
.../totp/impl/ExtractTOTPFromFormRequest.java | 15 +--
.../plugin/totp/impl/ExtractTOTPFromHeader.java | 15 +--
.../{totp/totp-beans.xml => TOTP/TOTP-beans.xml} | 22 +++--
.../{totp/totp-flow.xml => TOTP/TOTP-flow.xml} | 36 ++++---
.../shibboleth/idp/plugin/totp/messages.properties | 13 +++
totp-impl/src/main/resources/views/totp-error.vm | 31 +++++++
totp-impl/src/main/resources/views/totp.vm | 103 +++++++++++++++++++++
.../totp/impl/ExtractTOTPFromFormRequestTest.java | 5 +-
.../totp/impl/ExtractTOTPFromHeaderTest.java | 5 +-
...GoogleAuthenticatorCredentialValidatorTest.java | 4 +-
13 files changed, 229 insertions(+), 63 deletions(-)
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPCredentialValidator.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPCredentialValidator.java
index b331029..d97edd9 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPCredentialValidator.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPCredentialValidator.java
@@ -128,24 +128,24 @@ public abstract class AbstractTOTPCredentialValidator extends AbstractCredential
if (totpContext == null) {
log.info("{} No TOTPContext available", getLogPrefix());
if (errorHandler != null) {
- errorHandler.handleError(profileRequestContext, authenticationContext, (String) null,
+ errorHandler.handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
AuthnEventIds.NO_CREDENTIALS);
}
throw new LoginException(AuthnEventIds.NO_CREDENTIALS);
} else if (totpContext.getUsername() == null) {
log.info("{} No username available within TOTPContext", getLogPrefix());
if (errorHandler != null) {
- errorHandler.handleError(profileRequestContext, authenticationContext, (String) null,
- AuthnEventIds.NO_CREDENTIALS);
+ errorHandler.handleError(profileRequestContext, authenticationContext, AuthnEventIds.UNKNOWN_USERNAME,
+ AuthnEventIds.UNKNOWN_USERNAME);
}
throw new LoginException(AuthnEventIds.NO_CREDENTIALS);
} else if (totpContext.getTokenCode() == null) {
log.info("{} No tokencode available within TOTPContext", getLogPrefix());
if (errorHandler != null) {
- errorHandler.handleError(profileRequestContext, authenticationContext, (String) null,
- AuthnEventIds.INVALID_CREDENTIALS);
+ errorHandler.handleError(profileRequestContext, authenticationContext, AuthnEventIds.NO_CREDENTIALS,
+ AuthnEventIds.NO_CREDENTIALS);
}
- throw new LoginException(AuthnEventIds.INVALID_CREDENTIALS);
+ throw new LoginException(AuthnEventIds.NO_CREDENTIALS);
}
if (totpContext.getTokenSeeds().isEmpty()) {
@@ -155,8 +155,8 @@ public abstract class AbstractTOTPCredentialValidator extends AbstractCredential
if (totpContext.getTokenSeeds().isEmpty()) {
log.info("{} No seeds were obtained for user '{}'", getLogPrefix(), totpContext.getUsername());
if (errorHandler != null) {
- errorHandler.handleError(profileRequestContext, authenticationContext, (String) null,
- AuthnEventIds.INVALID_CREDENTIALS);
+ errorHandler.handleError(profileRequestContext, authenticationContext,
+ AuthnEventIds.INVALID_CREDENTIALS, AuthnEventIds.INVALID_CREDENTIALS);
}
throw new LoginException(AuthnEventIds.INVALID_CREDENTIALS);
}
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPExtractionAction.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPExtractionAction.java
index 9c9ec1d..e6a6121 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPExtractionAction.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AbstractTOTPExtractionAction.java
@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest;
import net.shibboleth.idp.authn.AbstractAuthenticationAction;
import net.shibboleth.idp.authn.AuthnEventIds;
import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.AuthenticationErrorContext;
import net.shibboleth.idp.plugin.totp.context.TOTPContext;
import net.shibboleth.idp.session.context.navigate.CanonicalUsernameLookupStrategy;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
@@ -44,7 +45,10 @@ import org.slf4j.LoggerFactory;
*
* @event {@link org.opensaml.profile.action.EventIds#PROCEED_EVENT_ID}
* @event {@link AuthnEventIds#NO_CREDENTIALS}
- * @pre <pre>ProfileRequestContext.getSubcontext(AuthenticationContext.class, false) != null</pre>
+ * @event {@link AuthnEventIds#UNKNOWN_USERNAME}
+ * @event {@link AuthnEventIds#INVALID_CREDENTIALS}
+ * @pre <pre>ProfileRequestContext.getSubcontext(AuthenticationContext.class) != null</pre>
+ * @post <pre>AuthenticationContext.getSubcontext(TOTPContext.class) != null</pre>
*/
public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticationAction {
@@ -93,6 +97,9 @@ public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticatio
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
@Nonnull final AuthenticationContext authenticationContext) {
+ // Clear error state.
+ authenticationContext.removeSubcontext(AuthenticationErrorContext.class);
+
totpContext = totpContextCreationStrategy.apply(authenticationContext);
totpContext.setTokenCode(null);
@@ -101,7 +108,7 @@ public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticatio
final String username = usernameLookupStrategy.apply(profileRequestContext);
if (username == null) {
log.warn("{} No principal name available", getLogPrefix());
- ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
+ ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.UNKNOWN_USERNAME);
return;
}
totpContext.setUsername(username);
@@ -114,13 +121,20 @@ public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticatio
return;
}
- final Integer code = extractCode(request);
+ final String code = extractCode(request);
if (code == null) {
ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_CREDENTIALS);
return;
}
- totpContext.setTokenCode(code);
+ try {
+ totpContext.setTokenCode(Integer.valueOf(code));
+ } catch (final NumberFormatException e) {
+ log.warn("{} Exception converting code string to an integer", getLogPrefix(), e);
+ authenticationContext.getSubcontext(AuthenticationErrorContext.class,
+ true).getClassifiedErrors().add(AuthnEventIds.INVALID_CREDENTIALS);
+ ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.INVALID_CREDENTIALS);
+ }
}
/**
@@ -130,6 +144,6 @@ public abstract class AbstractTOTPExtractionAction extends AbstractAuthenticatio
*
* @return the token code, or null
*/
- @Nullable protected abstract Integer extractCode(@Nonnull final HttpServletRequest httpRequest);
+ @Nullable protected abstract String extractCode(@Nonnull final HttpServletRequest httpRequest);
}
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AttributeResolverSeedSource.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AttributeResolverSeedSource.java
index c0f4c2e..011ee0a 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AttributeResolverSeedSource.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/AttributeResolverSeedSource.java
@@ -47,6 +47,9 @@ import net.shibboleth.utilities.java.support.service.ReloadableService;
@ThreadSafeAfterInit
public class AttributeResolverSeedSource extends AbstractSeedSource {
+ /** Default attribute ID source. */
+ @Nonnull @NotEmpty public static final String DEFAULT_ATTRIBUTE_ID = "tokenSeeds";
+
/** Class logger. */
@Nonnull private final Logger log = LoggerFactory.getLogger(AttributeResolverSeedSource.class);
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequest.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequest.java
index 622f0a2..068db9a 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequest.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequest.java
@@ -62,19 +62,8 @@ public class ExtractTOTPFromFormRequest extends AbstractTOTPExtractionAction {
/** {@inheritDoc} */
@Override
- @Nullable protected Integer extractCode(@Nonnull final HttpServletRequest httpRequest) {
- final String code = httpRequest.getParameter(fieldName);
- if (code != null) {
- try {
- return Integer.valueOf(code);
- } catch (final NumberFormatException e) {
- log.warn("{} Exception converting parameter value to integer code", getLogPrefix(), e);
- }
- } else {
- log.trace("{} Token code field {} not found", getLogPrefix(), fieldName);
- }
-
- return null;
+ @Nullable protected String extractCode(@Nonnull final HttpServletRequest httpRequest) {
+ return httpRequest.getParameter(fieldName);
}
}
\ No newline at end of file
diff --git a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeader.java b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeader.java
index d07fc0f..e99235e 100644
--- a/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeader.java
+++ b/totp-impl/src/main/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeader.java
@@ -62,19 +62,8 @@ public class ExtractTOTPFromHeader extends AbstractTOTPExtractionAction {
/** {@inheritDoc} */
@Override
- @Nullable protected Integer extractCode(@Nonnull final HttpServletRequest httpRequest) {
- final String code = httpRequest.getHeader(headerName);
- if (code != null) {
- try {
- return Integer.valueOf(code);
- } catch (final NumberFormatException e) {
- log.warn("{} Exception converting header value to integer code", getLogPrefix(), e);
- }
- } else {
- log.trace("{} Token code header {} not found", getLogPrefix(), headerName);
- }
-
- return null;
+ @Nullable protected String extractCode(@Nonnull final HttpServletRequest httpRequest) {
+ return httpRequest.getHeader(headerName);
}
}
\ No newline at end of file
diff --git a/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/totp/totp-beans.xml b/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/TOTP/TOTP-beans.xml
similarity index 81%
rename from totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/totp/totp-beans.xml
rename to totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/TOTP/TOTP-beans.xml
index 900b39c..4a9cdfd 100644
--- a/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/totp/totp-beans.xml
+++ b/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/TOTP/TOTP-beans.xml
@@ -18,6 +18,11 @@
<bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
<bean class="net.shibboleth.idp.profile.impl.ProfileActionBeanPostProcessor" />
+ <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
+ p:cacheSeconds="%{idp.message.cacheSeconds:300}"
+ p:basenames="classpath:/net/shibboleth/idp/plugin/totp/messages"
+ p:defaultEncoding="UTF-8" />
+
<import resource="conditional:%{idp.home}/conf/authn/totp-authn-config.xml" />
<bean id="ExtractTOTPFromHeader"
@@ -33,18 +38,23 @@
<bean id="ValidateTOTPCredentials"
class="net.shibboleth.idp.authn.impl.ValidateCredentials" scope="prototype"
p:validators="#{getObject('shibboleth.authn.TOTP.Validator') ?: getObject('DefaultTOTPValidator')}"
- p:addDefaultPrincipals="#{getObject('shibboleth.authn.TOTP.addDefaultPrincipals') ?:
- (getObject('shibboleth.authn.TOTP.PrincipalOverride') == null
- or getObject('shibboleth.authn.TOTP.PrincipalOverride').isEmpty())}"
- p:supportedPrincipals="#{getObject('shibboleth.authn.TOTP.PrincipalOverride')}"
- p:classifiedMessages-ref="shibboleth.authn.TOTP.ClassifiedMessageMap"
p:resultCachingPredicate="#{getObject('shibboleth.authn.TOTP.resultCachingPredicate')}"
+ p:classifiedMessages-ref="TOTPClassifiedMessageMap"
p:lockoutManager="#{getObject('shibboleth.authn.TOTP.AccountLockoutManager')}" />
+ <util:map id="TOTPClassifiedMessageMap">
+ <entry key="InvalidCredentials">
+ <list>
+ <value>InvalidCredentials</value>
+ </list>
+ </entry>
+ </util:map>
+
<!-- These are singletons acting as default "back-ends". -->
<bean id="DefaultTOTPValidator" class="net.shibboleth.idp.plugin.totp.impl.GoogleAuthenticatorCredentialValidator" lazy-init="true"
- p:matchExpression="#{getObject('shibboleth.authn.TOTP.matchExpression')}" />
+ p:matchExpression="#{getObject('shibboleth.authn.TOTP.matchExpression')}"
+ p:seedSource="#{getObject('shibboleth.authn.TOTP.SeedSource') ?: getObject('DefaultSeedSource')}" />
<bean id="DefaultSeedSource" class="net.shibboleth.idp.plugin.totp.impl.AttributeResolverSeedSource" lazy-init="true"
p:attributeResolver-ref="shibboleth.AttributeResolverService"
diff --git a/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/totp/totp-flow.xml b/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/TOTP/TOTP-flow.xml
similarity index 60%
rename from totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/totp/totp-flow.xml
rename to totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/TOTP/TOTP-flow.xml
index 153b84e..76428a6 100644
--- a/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/totp/totp-flow.xml
+++ b/totp-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/authn/TOTP/TOTP-flow.xml
@@ -10,15 +10,12 @@
<evaluate expression="'proceed'" />
<transition on="proceed" to="ValidateTOTPCredentials" />
- <transition on="NoCredentials" to="ExtractTOTPFromFormRequest" />
- </action-state>
- <!-- Then check for propagation via password (or other) form. -->
- <action-state id="ExtractTOTPFromFormRequest">
- <evaluate expression="ExtractTOTPFromFormRequest" />
- <evaluate expression="'proceed'" />
+ <!-- Fall through to a different flow if header extract fails on a passive or non-browser request. -->
+ <transition on="#{ opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext)).isPassive() || !opensamlProfileRequestContext.isBrowserProfile() }" to="ReselectFlow" />
- <transition on="proceed" to="ValidateTOTPCredentials" />
+ <transition on="UnknownUsername" to="ReselectFlow" />
+ <transition on="InvalidCredentials" to="DisplayTOTPView" />
<transition on="NoCredentials" to="DisplayTOTPView" />
</action-state>
@@ -26,8 +23,10 @@
<on-render>
<evaluate expression="environment" result="viewScope.environment" />
<evaluate expression="opensamlProfileRequestContext" result="viewScope.profileRequestContext" />
- <evaluate expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext))"
- result="viewScope.authenticationContext" />
+ <evaluate expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext))" result="viewScope.authenticationContext" />
+ <evaluate expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.ui.context.RelyingPartyUIContext))" result="viewScope.rpUIContext" />
+ <evaluate expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationErrorContext))" result="viewScope.authenticationErrorContext" />
+ <evaluate expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationWarningContext))" result="viewScope.authenticationWarningContext" />
<evaluate expression="T(net.shibboleth.utilities.java.support.codec.HTMLEncoder)" result="viewScope.encoder" />
<evaluate expression="flowRequestContext.getExternalContext().getNativeRequest()" result="viewScope.request" />
<evaluate expression="flowRequestContext.getExternalContext().getNativeResponse()" result="viewScope.response" />
@@ -38,15 +37,28 @@
<transition on="proceed" to="ExtractTOTPFromFormRequest" />
</view-state>
+ <!-- Then check for propagation via password (or other) form. -->
+ <action-state id="ExtractTOTPFromFormRequest">
+ <evaluate expression="ExtractTOTPFromFormRequest" />
+ <evaluate expression="'proceed'" />
+
+ <transition on="proceed" to="ValidateTOTPCredentials" />
+ <transition on="UnknownUsername" to="ReselectFlow" />
+ <transition on="InvalidCredentials" to="DisplayTOTPView" />
+ <transition on="NoCredentials" to="DisplayTOTPView" />
+ </action-state>
+
+
<action-state id="ValidateTOTPCredentials">
<evaluate expression="ValidateTOTPCredentials" />
<evaluate expression="'proceed'" />
<transition on="proceed" to="proceed" />
- <transition on="InvalidCredentials" to="DisplayTOTPView" />
- <transition on="NoCredentials" to="DisplayTOTPView" />
+ <transition on="UnknownUsername" to="ReselectFlow" />
+ <transition on="NoCredentials" to="DisplayTOTPView" />
+ <transition on="InvalidCredentials" to="DisplayTOTPView" />
</action-state>
- <bean-import resource="totp-beans.xml" />
+ <bean-import resource="TOTP-beans.xml" />
</flow>
diff --git a/totp-impl/src/main/resources/net/shibboleth/idp/plugin/totp/messages.properties b/totp-impl/src/main/resources/net/shibboleth/idp/plugin/totp/messages.properties
new file mode 100644
index 0000000..4f3f24e
--- /dev/null
+++ b/totp-impl/src/main/resources/net/shibboleth/idp/plugin/totp/messages.properties
@@ -0,0 +1,13 @@
+# In addition to the Apache 2.0 license, this content is also licensed
+# under the Creative Commons Attribution-ShareAlike 3.0 Unported license
+# (see http://creativecommons.org/licenses/by-sa/3.0/).
+
+# This is the as-delivered set of messages used in various views
+# so that internationalized translations can be made available and
+# so administrators can locally override or supplement the values
+# in their own message files.
+
+
+idp.totp.field = Token Code
+
+bad-tokencode.message = The supplied token code was invalid.
diff --git a/totp-impl/src/main/resources/views/totp-error.vm b/totp-impl/src/main/resources/views/totp-error.vm
new file mode 100644
index 0000000..388db80
--- /dev/null
+++ b/totp-impl/src/main/resources/views/totp-error.vm
@@ -0,0 +1,31 @@
+## Velocity Template for TOTP error message production, included by totp.vm
+##
+## authenticationErrorContext - context containing error data, if available
+##
+#if ($authenticationErrorContext && $authenticationErrorContext.getClassifiedErrors().size() > 0)
+ ## This handles errors that are classified by the message maps in the authentication config.
+ #set ($eventId = $authenticationErrorContext.getClassifiedErrors().iterator().next())
+ #if ($eventId != "ReselectFlow")
+ #set ($eventKey = $springMacroRequestContext.getMessage("$eventId", "login"))
+ #set ($message = $springMacroRequestContext.getMessage("${eventKey}.message", "Login Failure: $eventId"))
+ #end
+#elseif ($authenticationErrorContext && $authenticationErrorContext.getExceptions().size() > 0)
+ ## This handles login exceptions that are left unclassified.
+ #set ($loginException = $authenticationErrorContext.getExceptions().get(0))
+ #if ($loginException.getMessage())
+ #set ($message = "Login Failure: $loginException.getMessage()")
+ #else
+ #set ($message = $loginException.toString())
+ #end
+#elseif ($flowRequestContext)
+ #set ($eventId = $flowRequestContext.getCurrentEvent().getId())
+ #if ($eventId == "InvalidCredentials")
+ #set ($message = $springMacroRequestContext.getMessage("idp.totp.invalid", "The supplied token code was invalid."))
+ #end
+#end
+
+#if ($message)
+ <section>
+ <p class="form-element form-error">$encoder.encodeForHTML($message)</p>
+ </section>
+#end
diff --git a/totp-impl/src/main/resources/views/totp.vm b/totp-impl/src/main/resources/views/totp.vm
new file mode 100644
index 0000000..b3bde33
--- /dev/null
+++ b/totp-impl/src/main/resources/views/totp.vm
@@ -0,0 +1,103 @@
+##
+## Velocity Template for DisplayTOTPView view-state
+##
+## Velocity context will contain the following properties
+## flowExecutionUrl - the form action location
+## flowRequestContext - the Spring Web Flow RequestContext
+## flowExecutionKey - the SWF execution key (this is built into the flowExecutionUrl)
+## profileRequestContext - root of context tree
+## authenticationContext - context with authentication request information
+## authenticationErrorContext - context with login error state
+## authenticationWarningContext - context with login warning state
+## rpUIContext - the context with SP UI information from the metadata
+## encoder - HTMLEncoder class
+## request - HttpServletRequest
+## response - HttpServletResponse
+## environment - Spring Environment object for property resolution
+## custom - arbitrary object injected by deployer
+##
+#set ($rpContext = $profileRequestContext.getSubcontext('net.shibboleth.idp.profile.context.RelyingPartyContext'))
+##
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
+ <title>#springMessageText("idp.title", "Web Login Service")</title>
+ <link rel="stylesheet" type="text/css" href="$request.getContextPath()/css/main.css">
+ </head>
+ <body>
+ <div class="wrapper">
+ <div class="container">
+ <header>
+ <img src="$request.getContextPath()#springMessage("idp.logo")" alt="#springMessageText("idp.logo.alt-text", "logo")">
+ </header>
+
+ <div class="content">
+ <div class="column one">
+ #parse("totp-error.vm")
+
+ <form action="$flowExecutionUrl" method="post">
+ #parse("csrf/csrf.vm")
+ #set ($serviceName = $rpUIContext.serviceName)
+ #if ($serviceName && !$rpContext.getRelyingPartyId().contains($serviceName))
+ <legend>
+ #springMessageText("idp.login.loginTo", "Login to") $encoder.encodeForHTML($serviceName)
+ </legend>
+ #end
+
+ <div class="form-element-wrapper">
+ <label for="tokencode">#springMessageText("idp.totp.field", "Foo")</label>
+ <input class="form-element form-field" id="tokencode" name="tokencode" type="text" value="" />
+ </div>
+
+
+ <div class="form-element-wrapper">
+ <button class="form-element form-button" type="submit" name="_eventId_proceed"
+ onClick="this.childNodes[0].nodeValue='#springMessageText("idp.login.pleasewait", "Logging in, please wait...")'"
+ >#springMessageText("idp.login.login", "Login")</button>
+ </div>
+ </form>
+
+ #*
+ //
+ // SP Description & Logo (optional)
+ // These idpui lines will display added information (if available
+ // in the metadata) about the Service Provider (SP) that requested
+ // authentication. These idpui lines are "active" in this example
+ // (not commented out) - this extra SP info will be displayed.
+ // Remove or comment out these lines to stop the display of the
+ // added SP information.
+ //
+ *#
+ #set ($logo = $rpUIContext.getLogo())
+ #if ($logo)
+ <img src= "$encoder.encodeForHTMLAttribute($logo)"
+ alt="$encoder.encodeForHTMLAttribute($serviceName)">
+ #end
+ #set ($desc = $rpUIContext.getServiceDescription())
+ #if ($desc)
+ $encoder.encodeForHTML($desc)
+ #end
+
+ </div>
+ <div class="column two">
+ <ul class="list list-help">
+ #if ($passwordEnabled)
+ <li class="list-help-item"><a href="#springMessageText("idp.url.password.reset", '#')"><span class="item-marker">›</span> #springMessageText("idp.login.forgotPassword", "Forgot your password?")</a></li>
+ #end
+ <li class="list-help-item"><a href="#springMessageText("idp.url.helpdesk", '#')"><span class="item-marker">›</span> #springMessageText("idp.login.needHelp", "Need Help?")</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+
+ <footer>
+ <div class="container container-footer">
+ <p class="footer-text">#springMessageText("idp.footer", "Insert your footer text here.")</p>
+ </div>
+ </footer>
+ </div>
+
+ </body>
+</html>
\ No newline at end of file
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequestTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequestTest.java
index 2b0d2e0..ad78bbe 100644
--- a/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequestTest.java
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromFormRequestTest.java
@@ -48,6 +48,7 @@ public class ExtractTOTPFromFormRequestTest extends BaseAuthenticationContextTes
@Test public void testNoServlet() throws Exception {
action = new ExtractTOTPFromFormRequest();
+ action.setUsernameLookupStrategy(FunctionSupport.constant("jdoe"));
action.initialize();
final Event event = action.execute(src);
@@ -60,7 +61,7 @@ public class ExtractTOTPFromFormRequestTest extends BaseAuthenticationContextTes
action.initialize();
final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.UNKNOWN_USERNAME);
}
@Test public void testMissingField() throws Exception {
@@ -79,7 +80,7 @@ public class ExtractTOTPFromFormRequestTest extends BaseAuthenticationContextTes
((MockHttpServletRequest) action.getHttpServletRequest()).addParameter("Foo", "A123456");
final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_CREDENTIALS);
}
@Test public void testValid() throws Exception {
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeaderTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeaderTest.java
index b8b3ad9..3ef4184 100644
--- a/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeaderTest.java
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/ExtractTOTPFromHeaderTest.java
@@ -48,6 +48,7 @@ public class ExtractTOTPFromHeaderTest extends BaseAuthenticationContextTest {
@Test public void testNoServlet() throws Exception {
action = new ExtractTOTPFromHeader();
+ action.setUsernameLookupStrategy(FunctionSupport.constant("jdoe"));
action.initialize();
final Event event = action.execute(src);
@@ -60,7 +61,7 @@ public class ExtractTOTPFromHeaderTest extends BaseAuthenticationContextTest {
action.initialize();
final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.UNKNOWN_USERNAME);
}
@Test public void testMissingHeader() throws Exception {
@@ -79,7 +80,7 @@ public class ExtractTOTPFromHeaderTest extends BaseAuthenticationContextTest {
((MockHttpServletRequest) action.getHttpServletRequest()).addHeader("X-Foo", "A123456");
final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_CREDENTIALS);
}
@Test public void testValid() throws Exception {
diff --git a/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/GoogleAuthenticatorCredentialValidatorTest.java b/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/GoogleAuthenticatorCredentialValidatorTest.java
index 7dd69de..16c8d41 100644
--- a/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/GoogleAuthenticatorCredentialValidatorTest.java
+++ b/totp-impl/src/test/java/net/shibboleth/idp/plugin/totp/impl/GoogleAuthenticatorCredentialValidatorTest.java
@@ -88,7 +88,7 @@ public class GoogleAuthenticatorCredentialValidatorTest extends BaseAuthenticati
action.initialize();
final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.UNKNOWN_USERNAME);
}
@@ -101,7 +101,7 @@ public class GoogleAuthenticatorCredentialValidatorTest extends BaseAuthenticati
action.initialize();
final Event event = action.execute(src);
- ActionTestingSupport.assertEvent(event, AuthnEventIds.INVALID_CREDENTIALS);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.NO_CREDENTIALS);
}
@Test public void testMissingSeeds() throws Exception {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list