Dynamically sending a RelayState in Play Pac4J

456 views
Skip to first unread message

LEON DE SILVA

unread,
Nov 10, 2017, 6:48:16 AM11/10/17
to Pac4j users mailing list
Hi,

In order to secure an endpoint in a play framework application, I annotated the controller method with the SAML2 Client.
Now I have a requirement to dynamically set a RelayState when sending an authentication request to Okta. 

How can I dynamically set a RelayState when using Play Pac4j?

Jérôme LELEU

unread,
Nov 10, 2017, 2:26:46 PM11/10/17
to LEON DE SILVA, Pac4j users mailing list
Hi,

I took a look at the code and this is a bit strange, the state parameter is taken from the session :

final String relayState = (String) webContext.getSessionStore().get(webContext, SAML_RELAY_STATE_ATTRIBUTE);

And used for the redirection to the identity provider.

Though I don't see any check for this value after a successful login and thus I don't really understand this parameter usefulness.

Misagh, can you enlighten on this?

Thanks.
Best regards,


--
You received this message because you are subscribed to the Google Groups "Pac4j users mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

LEON DE SILVA

unread,
Nov 13, 2017, 12:24:07 AM11/13/17
to Pac4j users mailing list
To get a clear understanding on this, Please find the following information explained in the Okta documentation.

"A RelayState is an HTTP parameter that can be included as part of the SAML request and SAML response. In an SP-initiated login flow, the SP can set the RelayState parameter in the SAML request with additional information about the request. A SAML IDP, upon receiving the SAML request, will take the RelayState value and simply attach it back as a HTTP parameter in the SAML response after the user has been authenticated. This way, when the round trip completes, the SP can use the RelayState information to get additional context about the initial SAML authentication request.

In the case of a deeplink, the SP will set the RelayState of the SAML request with the deep-link value. When the SAML response comes back, the SP can use the RelayState value and take the authenticated user to the right resource." 


Please let me know if there is a way I can set a RelayState parameter in play-pac4j, so that I can use it for identifying the requested resource and serve it to the user.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.

LEON DE SILVA

unread,
Nov 13, 2017, 11:28:11 PM11/13/17
to Pac4j users mailing list
Hi Jerome and Misagh,

Can you give your ideas on how to implement this using play-pac4j ?

LEON DE SILVA

unread,
Nov 15, 2017, 1:53:39 AM11/15/17
to Pac4j users mailing list
Hi all,

As the solution I took an exact copy of the Secure annotation and SecureActon class. 
Linked the new SecureAnnotation with the new SecureAction class and made the following change to the new SecureAction class.
  • In internalCall method I have added the following line after creating the playWebContext. This is to set the relay state parameter with the value of the currently called URI. So this can be used for redirecting to the correct resource at the callback controller.
    playWebContext.setSessionAttribute(SAML2Client.SAML_RELAY_STATE_ATTRIBUTE, ctx.request().uri());
Then I wrote a new CallbackController class to call callbackLogic.perform with the redirect URL. In the current implementation defaultUrl is being used. In the new implementation there is a method to get the redirect URL.
  • Callback logic performing line :
    return (Result)this.callbackLogic.perform(playWebContext, this.config, this.config.getHttpActionAdapter(), getRedirectUrl(), this.multiProfile, false);

  • The method to get the redirect URL.
    private String getRedirectUrl() {
        PlayWebContext playWebContext = new PlayWebContext(ctx(), playSessionStore);
        String relayState = playWebContext.getRequestParameter("RelayState");
               if (StringUtils.isNotEmpty(relayState)) {
                   return relayState;
              }

              return this.getDefaultUrl();
          }

Jérôme LELEU

unread,
Nov 16, 2017, 2:25:02 AM11/16/17
to LEON DE SILVA, Pac4j users mailing list
Hi,

Thanks for the follow-up and the solution. I guess it's close to what we should implement: save the relay state and pass it to the redirection URL, then after the authentication, check the relay state parameter against the one we saved in the session.

I think you should compare the relay state in the session with the one received in the URL.

I opened this issue to track this improvement: https://github.com/pac4j/pac4j/issues/1041

Thanks.
Best regards,
Jérôme



To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages