/** {@inheritDoc} */ @Override public int hashCode() { return getId().hashCode(); }
/** {@inheritDoc} */ @Override public String toString() { return MoreObjects.toStringHelper(this).add("flowId", getId()).add("supportsPassive", supportsPassive) .add("supportsForcedAuthentication", supportsForced) .add("lifetime", lifetime).add("inactivityTimeout", inactivityTimeout).toString(); }
/** * Selects an inactive flow and completes processing. * * @param profileRequestContext the current IdP profile request context * @param authenticationContext the current authentication context * @param descriptor the flow to select */ private void selectInactiveFlow(@Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final AuthenticationContext authenticationContext, @Nonnull final AuthenticationFlowDescriptor descriptor) { log.debug("{} Selecting inactive authentication flow {}", getLogPrefix(), descriptor.getId()); authenticationContext.setAttemptedFlow(descriptor); ActionSupport.buildEvent(profileRequestContext, descriptor.getId()); }
/** * Set the {@link AuthenticationFlowDescriptor} collection active in the system. * * @param flows the flows available for possible use */ public void setAuthenticationFlowDescriptors( @Nonnull @NonnullElements final Iterable<AuthenticationFlowDescriptor> flows) { ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this); Constraint.isNotNull(flows, "Flow collection cannot be null"); flowDescriptorMap.clear(); for (final AuthenticationFlowDescriptor desc : Iterables.filter(flows, Predicates.notNull())) { flowDescriptorMap.put(desc.getId(), desc); } }
/** {@inheritDoc} */ @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final AuthenticationContext authenticationContext) { final Map<String, AuthenticationFlowDescriptor> potentialFlows = authenticationContext.getPotentialFlows(); final Iterator<Entry<String, AuthenticationFlowDescriptor>> descriptorItr = potentialFlows.entrySet().iterator(); while (descriptorItr.hasNext()) { final AuthenticationFlowDescriptor descriptor = descriptorItr.next().getValue(); if (descriptor.isNonBrowserSupported()) { log.debug("{} Retaining flow {}, it supports non-browser authentication", getLogPrefix(), descriptor.getId()); } else { log.debug("{} Removing flow {}, it does not support non-browser authentication", getLogPrefix(), descriptor.getId()); descriptorItr.remove(); } } if (potentialFlows.size() == 0) { log.info("{} No potential authentication flows remain after filtering", getLogPrefix()); } else { log.debug("{} Potential authentication flows left after filtering: {}", getLogPrefix(), potentialFlows); } }
/** {@inheritDoc} */ @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final AuthenticationContext authenticationContext) { final Map<String, AuthenticationFlowDescriptor> potentialFlows = authenticationContext.getPotentialFlows(); final Iterator<Entry<String, AuthenticationFlowDescriptor>> descriptorItr = potentialFlows.entrySet().iterator(); while (descriptorItr.hasNext()) { final AuthenticationFlowDescriptor descriptor = descriptorItr.next().getValue(); if (descriptor.isForcedAuthenticationSupported()) { log.debug("{} Retaining flow {}, it supports forced authentication", getLogPrefix(), descriptor.getId()); } else { log.debug("{} Removing flow {}, it does not support forced authentication", getLogPrefix(), descriptor.getId()); descriptorItr.remove(); } } if (potentialFlows.size() == 0) { log.info("{} No potential authentication flows remain after filtering", getLogPrefix()); } else { log.debug("{} Potential authentication flows left after filtering: {}", getLogPrefix(), potentialFlows); } }
/** {@inheritDoc} */ @Override protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final AuthenticationContext authenticationContext) { final Map<String, AuthenticationFlowDescriptor> potentialFlows = authenticationContext.getPotentialFlows(); final Iterator<Entry<String, AuthenticationFlowDescriptor>> descriptorItr = potentialFlows.entrySet().iterator(); while (descriptorItr.hasNext()) { final AuthenticationFlowDescriptor descriptor = descriptorItr.next().getValue(); if (descriptor.isPassiveAuthenticationSupported()) { log.debug("{} Retaining flow {}, it supports passive authentication", getLogPrefix(), descriptor.getId()); } else { log.debug("{} Removing flow {}, it does not support passive authentication", getLogPrefix(), descriptor.getId()); descriptorItr.remove(); } } if (potentialFlows.size() == 0) { log.info("{} No potential authentication flows remain after filtering", getLogPrefix()); } else { log.debug("{} Potential authentication flows left after filtering: {}", getLogPrefix(), potentialFlows); } } }
authenticationContext.getAvailableFlows().put(desc.getId(), desc); final String flowId = desc.getId().substring(desc.getId().indexOf('/') + 1); if (activeFlows.contains(flowId)) { if (authenticationContext.getAvailableFlows().containsKey(desc.getId()) && desc.apply(profileRequestContext)) { authenticationContext.getPotentialFlows().put(desc.getId(), desc); } else { log.debug("{} Filtered out authentication flow {}", getLogPrefix(), desc.getId()); desc.getId()); if (authenticationContext.getAvailableFlows().containsKey(desc.getId()) && desc.apply(profileRequestContext)) { authenticationContext.getPotentialFlows().put(desc.getId(), desc); } else { log.debug("{} Filtered out authentication flow {}", getLogPrefix(), desc.getId());
/** * Compare the flow's custom principal names to the string values of the attribute. * * @param flow flow to examine * * @return a match between the flow's principal names and the attribute's string values, or null */ @Nullable private String getMatch(@Nonnull final AuthenticationFlowDescriptor flow) { log.debug("{} Looking for match for flow {} against values for attribute {}", getLogPrefix(), flow.getId(), attribute.getId()); for (final Principal p : flow.getSupportedPrincipals()) { log.debug("{} Comparing principal {} against attribute values {}", getLogPrefix(), p.getName(), attribute.getValues()); for (final IdPAttributeValue val : attribute.getValues()) { if (val instanceof StringAttributeValue && Objects.equals(val.getValue(), p.getName())) { return p.getName(); } } } return null; }
/** {@inheritDoc} */ @Nullable public AuthenticationResult apply(@Nullable final ProfileRequestContext input) { if (input != null) { final AuthenticationContext authnContext = input.getSubcontext(AuthenticationContext.class); if (authnContext != null) { final MultiFactorAuthenticationContext mfaContext = authnContext.getSubcontext(MultiFactorAuthenticationContext.class); if (mfaContext != null) { final Collection<AuthenticationResult> results = mfaContext.getActiveResults().values(); if (!results.isEmpty()) { final Subject subject = new Subject(); for (final AuthenticationResult result : results) { subject.getPrincipals().add(new AuthenticationResultPrincipal(result)); subject.getPrincipals().addAll(result.getSubject().getPrincipals()); subject.getPublicCredentials().addAll(result.getSubject().getPublicCredentials()); subject.getPrivateCredentials().addAll(result.getSubject().getPrivateCredentials()); } final AuthenticationResult merged = new AuthenticationResult( mfaContext.getAuthenticationFlowDescriptor().getId(), subject); return merged; } } } } return null; }
final String match = getMatch(descriptor); if (match != null) { log.debug("{} Retaining flow {}, matched custom Principal {}", getLogPrefix(), descriptor.getId(), match); } else { log.debug("{} Removing flow {}, Principals did not match any attribute values", getLogPrefix(), descriptor.getId()); descriptorItr.remove();
/** * Return the first inactive potential flow not found in the intermediate flows collection that applies * to the request. * * @param profileRequestContext the current profile request context * @param authenticationContext the current authentication context * @return an eligible flow, or null */ @Nullable private AuthenticationFlowDescriptor getUnattemptedInactiveFlow( @Nonnull final ProfileRequestContext profileRequestContext, @Nonnull final AuthenticationContext authenticationContext) { AuthenticationFlowDescriptor selectedFlow = null; for (final AuthenticationFlowDescriptor flow : authenticationContext.getPotentialFlows().values()) { if (!authenticationContext.getIntermediateFlows().containsKey(flow.getId())) { if (!authenticationContext.isPassive() || flow.isPassiveAuthenticationSupported()) { if (flow.apply(profileRequestContext)) { selectedFlow = flow; if (preferredPrincipalCtx == null || preferredPrincipalCtx.isAcceptable(flow)) { break; } } } } } return selectedFlow; }
log.debug("{} Result from login flow {} has expired", getLogPrefix(), descriptor.getId());
final AuthenticationContext ac = input.getSubcontext(AuthenticationContext.class); if (ac != null && ac.getAttemptedFlow() != null) { final AuthenticationResult mfaResult = ac.getActiveResults().get(ac.getAttemptedFlow().getId()); if (mfaResult != null) { if (ac.isForceAuthn()) {
/** * Check if a result generated by this flow is still active. * * @param result {@link AuthenticationResult} to check * * @return true iff the result remains valid */ public boolean isResultActive(@Nonnull final AuthenticationResult result) { Constraint.isNotNull(result, "AuthenticationResult cannot be null"); Constraint.isTrue(result.getAuthenticationFlowId().equals(getId()), "AuthenticationResult was not produced by this flow"); final long now = System.currentTimeMillis(); if (getLifetime() > 0 && result.getAuthenticationInstant() + getLifetime() <= now) { return false; } else if (getInactivityTimeout() > 0 && result.getLastActivityInstant() + getInactivityTimeout() <= now) { return false; } return true; }
if (predicate != null) { for (final AuthenticationFlowDescriptor descriptor : potentialFlows.values()) { if (!authenticationContext.getIntermediateFlows().containsKey(descriptor.getId()) && predicate.apply(descriptor) && descriptor.apply(profileRequestContext)) { if (!authenticationContext.isPassive() || descriptor.isPassiveAuthenticationSupported()) {
final AuthenticationResult result = new AuthenticationResult(authenticationContext.getAttemptedFlow().getId(), populateSubject(getSubject())); authenticationContext.setAuthenticationResult(result);
log.debug("{} Attempting to honor signaled flow {}", getLogPrefix(), flow.getId()); activeResult = authenticationContext.getActiveResults().get(flow.getId()); } else if (authenticationContext.getInitialAuthenticationResult() != null && authenticationContext.getInitialAuthenticationResult().getAuthenticationFlowId().equals( flow.getId())) { activeResult = authenticationContext.getInitialAuthenticationResult(); } else { log.error("{} Signaled flow {} does not support passive authentication", getLogPrefix(), flow.getId()); ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.NO_PASSIVE); return; log.error("{} Signaled flow {} was not applicable to request", getLogPrefix(), flow.getId()); ActionSupport.buildEvent(profileRequestContext, authenticationContext.isPassive() ? AuthnEventIds.NO_PASSIVE : AuthnEventIds.NO_POTENTIAL_FLOW);