I needed callback based login/logout URLs which would always be the same on every page, but provide the referrer.
Created two menu items, with configurable URLs via the admin interface.
Patch will go here.

Comments

doublejosh’s picture

These two links allow placing links within Drupal core menus that point to SSO login/logout destinations.
They also include a ?goto= query string in the URL allowing your auth provider to redirect back to where the user was when they clicked the link.

Example values would be: https://auth.mydomain.com/login and https://auth.mydomain.com/logout

doublejosh’s picture

Title: Configurable Login/Logout menu links with callbacks » Configurable SSO service Login/Logout menu links with callbacks
doublejosh’s picture

Title: Configurable SSO service Login/Logout menu links with callbacks » Configurable SSO service dynamic login/logout menu links

title change.

doublejosh’s picture

It came to my attention that all new links may not be necessary and just cruft in my system.
The saml_login URL is fine. What I really need is a way to go somewhere besides /user upon login and logout.
Also because we have multiple systems running on the same SSO, I do need an external logout link.

Re-architected so that this feature can be used completely "internally" (default) OR externally and made the query param configurable (I need it for my external logout).

Since I haven't been using the saml_login URL for my login previously (crafted an auto-login feature with an external SSO login form) I'm not 100% this is how you'd like this to work.

doublejosh’s picture

Title: Configurable SSO service dynamic login/logout menu links » Configurable dynamic destination login/logout menu links
doublejosh’s picture

Status: Active » Needs review
doublejosh’s picture

Status: Needs review » Needs work

This approach is cumbersome and flawed. Fixing now.

geekwisdom’s picture

What is the actual problem you're trying to solve?

/saml_login is always the same
/user/logout is always the same

Are you trying to make it so the unauthenticated user is sent back to the original page they were trying to access instead of to /user/$id ? I plan to put a patch in on the next release that will correct this. Here's the gist of the code:

function simplesamlphp_auth_loginpage() {

global $user;
global $as;
global $saml_attributes;

$output = null;
if ($user->uid == 0 ) {
if ($user->uid == 0) {
/* Record the current location. */

$url = $_SERVER['HTTP_REFERER'];;
setrawcookie('saml_redirect_url', $url, REQUEST_TIME + 60, '/');

/* Require the user to be authentcated. */
$as->requireAuth();
} else {
$output .= t('Looks like you\'re already logged in. ');
$output .= t('Perhaps you logged into Drupal using a local account?');
}
} else {
$ssp_redirurl = 'user/' . $user->uid;

/* see if we know were to send the user */
if(isset($_COOKIE['saml_redirect_url']) &&
$_COOKIE['saml_redirect_url']){
$ssp_redirurl = $_COOKIE['saml_redirect_url'];

/* clean out the URL */
setrawcookie('saml_redirect_url', '', 0, '/');
}

/* send the user on their way */
drupal_goto($ssp_redirurl);
}

return $output;
}

doublejosh’s picture

Yeah, that's the desire.
I have it working like this...

function simplesamlphp_auth_menu() {
  // MORE ABOVE
  $items['sso-login'] = array(
    'title' => t('Login'),
    'description' => t('Provides dynamic goto login link'),
    'page callback' => 'simplesamlphp_auth_links',
    'page arguments' => array(TRUE),
    'access callback' => TRUE,
    'type' => MENU_NORMAL_ITEM,
  );
  $items['sso-logout'] = array(
    'title' => t('Logout'),
    'description' => t('Provides dynamic goto logout link'),
    'page callback' => 'simplesamlphp_auth_links',
    'page arguments' => array(FALSE),
    'access callback' => TRUE,
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Dynamic referrer login/logout links.
 */
function simplesamlphp_auth_links($login = TRUE) {
  if ($login) {
    $path_array = parse_url($_SERVER['HTTP_REFERER']);
    drupal_goto('saml_login', array('query' => array('destination' => ltrim($path_array['path'], '/'))));
  }
  else {
    // HAVEN'T SOLVED THIS YET.
  }
}
doublejosh’s picture

Also, was going to create an admin setting for an "external logout link" that the sso-logout would goto.
I for one had trouble with the single logout service.
In fact mine still returns to /?msg=no_slo even though it actually does bubble up.

geekwisdom’s picture

The logout is partially corrected in that simplesamlphp_auth_user_logout() now uses base_path() to determine the post-logout destination for the user after logout. I ported this change from the 6.x-2.x branch in reaction to issue #1446776 reported by eiriksm against the 6.x-2.x branch.

doublejosh’s picture

Great.
Just realized today we have a problem with logout return heading to HTTPS rather than HTTP.
This is the fix for sure #1446776: Hardcoded URL in logout redirects to wrong URL when logging out

geekwisdom’s picture

I have committed changes to the 7.x-2.x branch to return the user to the page they were on when they clicked the link to /saml_login.

I also added support for the ReturnTo URL parameter for /saml_login (e.g., /saml_login?ReturnTo=URL) which allows a site administrator to construct special links to pages that require authentication. When a user follows one of these links they will be taken directly to either an IdP discovery page (if there are multiple IdPs) or the IdP login page if there is only one IdP. As soon as they authenticate they will be delivered to the URL in ReturnTo. This can be used to construct menu links or placed in e-mails, etc.

doublejosh’s picture

Here's the end of my login page function. Also includes a fix similar to the logout hard-code in #1446776: Hardcoded URL in logout redirects to wrong URL when logging out

  ...

  // Allow dynamic goto after saml_login if that link is used.
  $params = array();
  $query_array = parse_str(htmlspecialchars($_SERVER['QUERY_STRING']));
  if (isset($query_array['destination'])) {
    $params['ReturnTo'] = $query_array['destination'];
  } else {
    // Force returning to intended domain protocol.
    global $base_url;
    $params['ReturnTo'] = $base_url;
  }

  if ($user->uid == 0) {
    // Require the user to be authenticated.
    $_simplesamlphp_auth_as->requireAuth($params);
  }
  else {
    if (isset($params['ReturnTo'])) {
      drupal_goto($params['ReturnTo']);
    }
    else {
      drupal_goto('user/' . $user->uid);
    }
  }
  return $output;
}
colan’s picture

Version: 7.x-1.2 » 7.x-2.x-dev

The above in patch format would be great. :)

Marking #1820870: Returning user to current page as a duplicate of this issue.

brad.bulger’s picture

curious - why not just use/honor the standard "destination" parameter, rather than create a new "ReturnTo" parameter? and am i reading this correctly, that it requires a complete URL value, rather than allowing an internal Drupal path value?

compare to core support for "user/login?destination=my/current/page"

reinier-v’s picture

It's about 100 years later, but this should do.

BTW, this is useful in a project where you connect multiple drupal instances to the same SAML SP, but don't want all cookies (from drupal) to span the whole domain. I suspect that's why the cookie-method (simplesamlphp_auth_returnto) doesn't work in all cases.