<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">On 6/18/2020 12:52 PM, Joseph Fischetti
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:27998C13-9EF8-4C26-A05A-3CF16FADDB08@marist.edu">
      <pre class="moz-quote-pre" wrap="">For some reason, error.vm doesn't appear to have the flowExecutionUrl available (and I'm not sure what it's supposed to be part of since I don't see where it's set during login.vm).

That said, this should more or less achieve exactly what I'm trying to do.  I'm using attribute-resolver to figure out whether to send the user to SP-B or not, and if the user goes to SP-B and does that they should do, the attribute will be set appropriately.  As long as the attribute-resolver is executed after hitting the flowExecutionUrl (assuming SSO takes over, as you said), it should work fine.
</pre>
    </blockquote>
    <p>You end up needing to reinvoke the resolver to pick up the
      changed value.  I'll throw our our expired password flow here to
      give you an idea of how we put it together.  Note the new view
      state we defined, and that we push the flowExecutionUrl into it. 
      There is probably some extra noise that could be cleaned up. 
      Enable it by adding it to an appropriate relying party definition
      with e.g. <span class="pl-e">p</span><span class="pl-e">:</span><span
        class="pl-e">postAuthenticationFlows</span>=<span class="pl-s"><span
          class="pl-pds">"</span>expiredpw<span class="pl-pds">".</span></span></p>
    <p><tt>    <decision-state id="CheckPasswordExpired"></tt><tt><br>
      </tt><tt>    <on-entry></tt><tt><br>
      </tt><tt>        <evaluate expression="ResolveAttributes" /></tt><tt><br>
      </tt><tt>        <evaluate
        expression="isPasswordExpired.apply(opensamlProfileRequestContext)"
        result="flowScope.ispwexpired" /></tt><tt><br>
      </tt><tt>        <evaluate
        expression="isPasswordChangeSP.apply(opensamlProfileRequestContext)"
        result="flowScope.ispwchangesp" /></tt><tt><br>
      </tt><tt>    </on-entry></tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>        <if test="ispwexpired &amp;&amp;
        !ispwchangesp"</tt><tt><br>
      </tt><tt>            then="PasswordExpired" else="CleanUpContexts"
        /></tt><tt><br>
      </tt><tt>    </decision-state></tt><tt><br>
      </tt><tt><br>
      </tt><tt>    <view-state id="PasswordExpired"
        view="expired-password"></tt><tt><br>
      </tt><tt>        <on-render></tt><tt><br>
      </tt><tt>            <evaluate expression="environment"
        result="viewScope.environment" /></tt><tt><br>
      </tt><tt>            <evaluate
        expression="opensamlProfileRequestContext"
        result="viewScope.profileRequestContext" /></tt><tt><br>
      </tt><tt>            <evaluate
expression="opensamlProfileRequestContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext))"
        result="viewScope.authenticationContext" /></tt><tt><br>
      </tt><tt>            <evaluate
expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationErrorContext))"
        result="viewScope.authenticationErrorContext" /></tt><tt><br>
      </tt><tt>            <evaluate
expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationWarningContext))"
        result="viewScope.authenticationWarningContext" /></tt><tt><br>
      </tt><tt>            <evaluate
expression="authenticationContext.getSubcontext(T(net.shibboleth.idp.authn.context.LDAPResponseContext))"
        result="viewScope.ldapResponseContext" /></tt><tt><br>
      </tt><tt>            <evaluate
        expression="T(net.shibboleth.utilities.java.support.codec.HTMLEncoder)"
        result="viewScope.encoder" /></tt><tt><br>
      </tt><tt>        </on-render></tt><tt><br>
      </tt><tt>        <transition on="proceed"
        to="RetryExpiredCheck" /></tt><tt><br>
      </tt><tt>    </view-state></tt><tt><br>
      </tt><tt>    <action-state id="RetryExpiredCheck"></tt><tt><br>
      </tt><tt>    <evaluate
expression="opensamlProfileRequestContext.removeSubcontext(T(net.shibboleth.idp.attribute.context.AttributeContext))"/></tt><tt><br>
      </tt><tt>    <evaluate
expression="opensamlProfileRequestContext.removeSubcontext(T(net.shibboleth.idp.attribute.resolution.context.AttributeResolutionContext))"/></tt><tt><br>
      </tt><tt>        <transition to="CheckPasswordExpired"/></tt><tt><br>
      </tt><tt>    </action-state></tt><tt><br>
      </tt><tt>    <action-state id="CleanUpContexts"></tt><tt><br>
      </tt><tt>    <evaluate
expression="opensamlProfileRequestContext.removeSubcontext(T(net.shibboleth.idp.attribute.context.AttributeContext))"/></tt><tt><br>
      </tt><tt>    <evaluate
expression="opensamlProfileRequestContext.removeSubcontext(T(net.shibboleth.idp.attribute.resolution.context.AttributeResolutionContext))"/></tt><tt><br>
      </tt><tt>    <transition to="proceed"/></tt><tt><br>
      </tt><tt>    </action-state></tt><tt><br>
      </tt></p>
    <p>And a snippet of the beans file:</p>
    <p><tt>    <bean id="isPasswordChangeSP"
        parent="shibboleth.Conditions.RelyingPartyId"></tt><tt><br>
      </tt><tt>        <constructor-arg></tt><tt><br>
      </tt><tt>            <list></tt><tt><br>
      </tt><tt>               
        <value><a class="moz-txt-link-freetext" href="https://sp-b-test">https://sp-b-test</a>...</value></tt><tt><br>
      </tt><tt>               
        <value><a class="moz-txt-link-freetext" href="https://sp-b-prod">https://sp-b-prod</a>...</value></tt><tt><br>
      </tt><tt>            </list></tt><tt><br>
      </tt><tt>        </constructor-arg></tt><tt><br>
      </tt><tt>    </bean></tt><tt><br>
      </tt><tt><br>
      </tt><tt>    <bean id="isPasswordExpired"
        class="edu.umn.oit.idm.shib.RegexAttributePredicate" <!--
        there is a built-in predicate or condition for this now --></tt><tt><br>
      </tt><tt>    p:pat="^[Xs].*" p:attributeId="umnPasswordStatus"</tt><tt><br>
      </tt><tt>   
p:attributeContextLookupStrategy-ref="shibboleth.ChildLookupOrCreate.AttributeContext"/></tt><tt><br>
      </tt><tt><br>
      </tt><tt>    <bean id="ResolveAttributes"</tt><tt><br>
      </tt><tt>           
        class="net.shibboleth.idp.profile.impl.ResolveAttributes"
        scope="prototype"   <!-- WARNING: this instances an "impl"
        bean which is not guaranteed to work across idp releases --></tt><tt><br>
      </tt><tt>           
        c:resolverService-ref="shibboleth.AttributeResolverService"</tt><tt><br>
      </tt><tt>            p:maskFailures="true"
        p:attributesToResolve="umnPasswordStatus"</tt><tt><br>
      </tt><tt>       
p:attributeContextCreationStrategy-ref="shibboleth.ChildLookupOrCreate.AttributeContext"/>
        <!-- this tells it to put these attributes in a separate
        context --></tt></p>
    <p>And the corresponding expired-password view:</p>
    <p><tt>#parse("header.vm")</tt><tt><br>
      </tt><tt><h1 class="text-center">Password has
        expired</h1></tt><tt><br>
      </tt><tt><div class="row"></tt><tt><br>
      </tt><tt>    <div class="col-md-8 col-md-offset-2
        col-xs-12"></tt><tt><br>
      </tt><tt>        <p class="idp3_confirmation-message">Your
        password has expired and must be changed before</tt><tt><br>
      </tt><tt>     you can proceed to the application.</p></tt><tt><br>
      </tt><tt>       
        <p>#springMessageText("idp.login.changePassword", "To
        create a new password now, go to")</tt><tt><br>
      </tt><tt>        <strong><a
        href=<a class="moz-txt-link-rfc2396E" href="https://example.edu/change-password">"https://example.edu/change-password"</a>
target="_blank"><a class="moz-txt-link-freetext" href="https://example.edu/change-password">https://example.edu/change-password</a></a></strong>.</p></tt><tt><br>
      </tt><tt>          <p>After you change your password, click
        <a
href="$flowExecutionUrl&_eventId_proceed=1">Continue</a>.</p></tt><tt><br>
      </tt><tt>    </div></tt><tt><br>
      </tt><tt></div></tt><tt><br>
      </tt><tt>#parse("footer.vm")</tt></p>
    <p><br>
    </p>
    <pre class="moz-signature" cols="72">-- 
%%  Christopher A. Bongaarts   %%  <a class="moz-txt-link-abbreviated" href="mailto:cab@umn.edu">cab@umn.edu</a>          %%
%%  OIT - Identity Management  %%  <a class="moz-txt-link-freetext" href="http://umn.edu/~cab">http://umn.edu/~cab</a>  %%
%%  University of Minnesota    %%  +1 (612) 625-1809    %%
</pre>
  </body>
</html>