When attempting to login with an existing user on the IdP, but new to Drupal, a new user is created without issue. When attempting to login with an existing user, where the user id exists on both the IdP and the Drupal site, I receive the following error:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'username' for key 'name': UPDATE {users} SET name=:db_update_placeholder_0 WHERE (uid = :db_condition_placeholder_0) ; Array ( [:db_update_placeholder_0] => username [:db_condition_placeholder_0] => 16555 ) in simplesamlphp_auth_user_insert() (line 326 of [path to]\sites\all\modules\simplesamlphp_auth\simplesamlphp_auth.module).

This is on a Windows box with MySQL db. Drupal 7.7, SimpleSAMLphp_auth 7.x-1.0

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

geekwisdom’s picture

The PDOException says that simplesamlphp_auth_user_insert() is trying to update the users.name column for uid 16555 with the value "username". Do you have multiple users with the name "username"?

Let me make sure I understand your scenarios.

Scenario #1: If Joe Blogs (eduPersonPrincipalName: joe_blogs@idp.example.com; mail: joe_blogs@example.com) is a valid user at the IdP but does not exist in the Drupal site he is able to authenticate against the IdP and the simplesamlphp_auth module will properly create a corresponding Drupal user for him. Is this correct?

Are you saying that if Joe Blogs were to log out and then attempt to log in a second time he would receive this error?

Scenario #2: Or are you saying that scenario works fine (creating new accounts and letting those users come and go fine) but if a user already exists in Drupal and had previously been using a local Drupal account to log in, but now tries to access Drupal using SAML that the process will fail with this error?

Additional information that could shed some light on this issue:
Which attribute from SimpleSAMLphp are you using for the Drupal Username attribute?
Which attribute from SimpleSAMLphp are you using for the unique identifier?

Note to self:
If the issue is scenario #2 it could be that user_external_load fails to locate the user because they do not have a record in authmap. (Which would make sense if they were created before the simplesamlphp_auth module was installed.) If this is the case, then some armor plating that attempts to find a matching user with user_load_by_name() needs to be added to .module between lines 181 and 184, in simplesamlphp_auth_init().

kpastore’s picture

I was able to fix this issue, but I thought clarifying what the actual parameters were would help.

We started with a preexisting set of users on a legacy CMS (not Drupal). Those users had many profile features that needed to be ported from the old site to the new Drupal site. We used Migrate to do this. This created users in the Drupal database that associated with their profile information.

These users ALSO existed on the IdP, but not with as many fields (email, GUID and username). They were being authenticated by their GUID field on the old system.

When attempting to login with this existing user, authentication failed, while new users created on the IdP worked just fine.

To fix this issue, I had to manually add the users, with their GUID to the 'authmap' table in the Drupal db, as this step was not automatic. Once this was completed, the users authenticated correctly.

geekwisdom’s picture

The issue is caused when a Drupal user that was created using the Drupal interface decides to try logging in using SAML. The module fails to find them because the user does not have a record in the authmap table. (The authmap table is used to map Drupal user accounts to external accounts.) Adding a record to the authmap table, which joins user's Drupal uid and their external identifier (authmap.authname) from the SAML IdP will solve the problem.

The question is, how can we reliably make this connection at runtime?

In Drupal no two users can have the same user.name; this is controlled both by core code and by a database constraint that requires this column to be unique.

Drupal core also forbids two users with the same user.mail, however this is not enforced at the database level and there are modules (e.g., Shared Email) that circumvent this requirement. So, comparing against e-mail seems like a bad idea.

It would seem that if the identifier received from the SAML IdP (simplesamlphp_auth_unique_id) matched the user's name (users.name) then the connection could be made by inserting a record into authmap.

If they do not match then it should be assumed that this user is a new user.

The problem with trying to match authname (from SAML assertion) with user.name in Drupal is that they will almost NEVER match in most scenarios. This is especially true if authname is configured to use eduPersonPrincipalName or eduPersonTargetedID.

So, while certain configurations could theoretically be configured in a way that could make the match, it's not likely that matches would ever be made at runtime seems. A modification that did this kind of matching is likely to be problematic, or at least limited in its usefulness.

This problem seems to call for another module, or a major new administrative feature in this one, that makes it easy for a Drupal administrator to populate the authmap table with the appropriate authnames for existing Drupal users. Perhaps such a module or feature could allow an administrator to load a CSV file containing records that link either user.name with authname or e-mail with authname. Then the code could resolve user.name or e-mail to a drupal uid and use it to create the appropriate authmap record for each user.

doublejosh’s picture

Priority: Critical » Normal
Status: Active » Postponed

Imagine I'm about to have this same issue.
We've used Drupal to manage profiles and users for a few years, but are now moving to OpenAM and simpleSAML as an SSO solution. Drupal will just be consuming the identity for authentication. However, almost all users will have existing Drupal accounts (the scenario described as the problem).

Solution seems to be attempting to create the authmap table entry at the time of authentication if it doesn't exist rather than only at the time of provisioning.

I haven't dug in yet, so looking to clarify the problem with those who've dealt with it.
(Should mention: we'll still be on D6 for a bit longer.)

geekwisdom’s picture

I've clarified this issue a little more in my analysis comment above. Further comments welcome.

geekwisdom’s picture

kpastore, thanks for posting your resolution.

doublejosh’s picture

Thanks all for sharing your situations.

Curious why this module doesn't create authmap entries for all existing users during the install? Perhaps somewhat irresponsible :)
Maybe need a batch process from the admin interface called "Regenerate Authmap For All Users" ?

Lauren Kelly’s picture

We worked around this with the Rules module, using a rule triggered upon creating a user.
For us, only users with a certain role are able to use SSO, so there is a condition in place, but you certainly don't need that if all users will be using SSO.
The action is custom PHP code, which adds a record to authmap with the UID, username, and module name.

This is the export of the rule :

array (
  'rules' => 
  array (
    'rules_saml_update_authmap' => 
    array (
      '#type' => 'rule',
      '#set' => 'event_user_insert',
      '#label' => 'Update authmap',
      '#active' => 1,
      '#weight' => '0',
      '#categories' => 
      array (
      ),
      '#status' => 'custom',
      '#conditions' => 
      array (
        0 => 
        array (
          '#info' => 
          array (
            'label' => 'User has role(s)',
            'arguments' => 
            array (
              'user' => 
              array (
                'type' => 'user',
                'label' => 'User',
              ),
            ),
            'module' => 'User',
          ),
          '#name' => 'rules_condition_user_hasrole',
          '#settings' => 
          array (
            'roles' => 
            array (
              0 => 7,
            ),
            'operation' => 'OR',
            '#argument map' => 
            array (
              'user' => 'account',
            ),
          ),
          '#type' => 'condition',
          '#weight' => 0,
        ),
      ),
      '#actions' => 
      array (
        1 => 
        array (
          '#info' => 
          array (
            'label' => 'Execute custom PHP code',
            'module' => 'PHP',
            'eval input' => 
            array (
              0 => 'code',
            ),
          ),
          '#name' => 'rules_action_custom_php',
          '#settings' => 
          array (
            'code' => 'user_set_authmaps($account, array(\'authname_simplesamlphp_auth\' => $account->name));',
            'vars' => 
            array (
              0 => 'account',
            ),
            '#eval input' => 
            array (
              'token_rules_input_evaluator' => 
              array (
                'code' => 
                array (
                  0 => ':global',
                ),
              ),
            ),
          ),
          '#type' => 'action',
          '#weight' => 0,
        ),
      ),
      '#version' => 6003,
    ),
  ),
)
doublejosh’s picture

Here's a query that will insert authmaps for all users (excluding a specific role, 8 in my case) and update any existing entries (in case you previously used LDAP, etc.) Hope this is helpful to someone else out there as it was a slight pain. Placed it in the simplesamlphp_auth.install for an update. Would be better as a batch process triggered via the settings page.

function simplesamlphp_auth_update_6001() {
  $query = "INSERT INTO authmap (authname, uid, module)
    SELECT users.name, users.uid, 'simplesamlphp_auth' FROM users
    LEFT JOIN users_roles ON users.uid = users_roles.uid
      WHERE (users_roles.rid <> 8 OR users_roles.rid IS NULL)
      AND users.uid <> 0
    GROUP BY users.uid
    ON DUPLICATE KEY UPDATE module = 'simplesamlphp_auth';";
  $result = db_result( db_query($query) );
  if ($result) {
    drupal_set_message('Sucess updating simplesamlphp authmaps', 'status');
  } else {
    drupal_set_message('Updating simplesamlphp authmaps failed!', 'error');
  }
}
geekwisdom’s picture

Category: bug » feature
Status: Postponed » Needs review

I'm changing this to a feature request because it's not really a bug and correcting it with any code that automatically makes assumptions about what an existing user's authmap entry should be could actually create a bug.

I can envision two aspects to the feature request:

1) An administrative feature that allows an administrator to do one or more of the following:

  • choose from one of the Drupal user attributes (name or mail) and use this to create authmap entries (for all users without authmap entries; for all users with a specific role; etc.)
  • load up a CSV file containing the following fields: Drupal name (or Drupal user id), identifier to be used in authmap entry. A batch process would then run and create (or update existing?) all the authmap entries for the users in the CSV file.

2) A couple additional configuration settings that will cause authmap entries to be created for new Drupal users (registered through Drupal). One of the new settings would need to allow the administrator to decide whether the Drupal user name or mail should be used for the authmap entry.

Would these features have helped you address the issues in your respective environments?

doublejosh’s picture

This would have done it.
At the time I needed to retroactively add authmap entries for everyone (other than one role) with: username | 'simplesamlphp_auth'

As you know this module does currently create authmap entries for folks registered via SSO due to user_external_login_register().

It should create entries for new users registered via Drupal under certain conditions.
I personally would do it for all users as I only have one IdP.

doublejosh’s picture

Created an issue for the potential problem caused by missing authmaps for native Drupal registrations...
#1635578: Path into Integrity Constraint Violation

doublejosh’s picture

I was going to suggest a Rules integration point for external login, where I need insert an authmap, but It hink this is much simpler.
#1576460: Add Rules integration for register & login

doublejosh’s picture

Adding a super simple admin option...

function simplesamlphp_auth_settings() {
...
    'simplesamlphp_auth_default_authmap' => array(
      '#type' => 'checkbox',
      '#title' => t('Set simpleSAMLphp_auth Authmap for ALL user registrations'),
      '#default_value' => variable_get('simplesamlphp_auth_default_authmap', TRUE),
      '#description' => t('Add an authmap to simpleSAMLphp_auth for all user registrations in addition to users auto-registered via SSO.<br />Probably only appropriate is this is your only IdP service.'),
    ),
...
function simplesamlphp_auth_user_insert(&$edit, $account, $category = NULL) {
...
        if (variable_set('simplesamlphp_auth_default_authmap')) {
          user_set_authmaps($account, array('authname_simplesamlphp_auth' => $account->name));
        }
...

Not tested yet.
If this works out I'll create a patch.

doublejosh’s picture

Thinking I may do this via my boot submodule so I can only add authmaps to local accounts when the SSO cookie is present and they actually need it.

msankhala’s picture

subscribe

colan’s picture

Title: Authentication fails for existing users on external IdP » Create authmap entries for pre-existing Drupal users
Version: 7.x-1.0 » 7.x-2.x-dev
Status: Needs review » Active

I agree with the way forward in #10, and #14 is a reasonable place to start.

Moving to latest dev branch. Also, setting to active as there's no patch here yet.

LiceBaseAdmin’s picture

I would opt to put this in the bug category again, because this behavior is somewhat counterintuitive and violates reasonable assumptions about the module works. Neither from the documentation nor the help text in the configuration page could the user expect this to happen. For example the following configuration option:
"Reevaluate roles every time the user logs in.
NOTE: This means users could loose any roles that have been assigned manually in Drupal."

This implies, that if not checked, users will not loose any roles. In addition, the help text of "Register users" implies that module works well with already existing Drupal accounts.
At minimum there should be mention in the documentation, and a portable way to deal with it, before it could be made a feature request again.

The SQL in #9 seems to be MySQL specific and didn't work with postgres, I have just taken away the ON DUPLICATE ... part:

INSERT INTO authmap (authname, uid, module)
    SELECT users.name, users.uid, 'simplesamlphp_auth' FROM users
    LEFT JOIN users_roles ON users.uid = users_roles.uid
      WHERE (users_roles.rid IS NULL)
      AND users.uid <> 0
    GROUP BY users.uid

But this can only be run once.

LiceBaseAdmin’s picture

Hi, and thanks for putting the SQL. The code is MySQL specific, so it didn't work for me at first.
The following modification worked for me on PostgreSQL 8.4 (got the idea from #9 and here http://stackoverflow.com/q/1009584):

BEGIN TRANSACTION;
CREATE RULE "authmap_on_duplicate_ignore" AS ON INSERT TO "authmap"
  WHERE EXISTS(SELECT 1 FROM authmap 
                WHERE (authname)=(NEW.authname))
  DO INSTEAD UPDATE authmap SET  module = 'simplesamlphp_auth'
                WHERE (authname)=(NEW.authname);
INSERT INTO authmap (authname, uid, module)  
  SELECT users.name, users.uid, 'simplesamlphp_auth' FROM users
    LEFT JOIN users_roles ON users.uid = users_roles.uid
      WHERE (users_roles.rid IS NULL)
      AND users.uid <> 0
    GROUP BY users.uid, users.name;
DROP RULE "authmap_on_duplicate_ignore" ON "authmap"; 
END TRANSACTION;

This should move over all user which do not have a role set and are not super user.

If the existing entries shouls be left alone, replace

DO INSTEAD UPDATE ...
with
 DO INSTEAD NOTHING;

Also, removing (users_roles.rid IS NULL) AND should move all existing users over to simplesamlphp.

cmcintosh’s picture

So this error is still relevant in the Drupal 7 release of the module. It starts at, simplesamlphp_auth_init(), because of duplicate username issues. To reliably prevent this we need to do a quick check before running user_external_login_register(), to see if there is a user with an existing name in the system. If so then we need to create a Authmap entry to that username.

However, there may be cases where you need to do some additional checking to validate the user before you actually merge the accounts. Also, provide a solution path for those users who do not match with the local installations name for that user.

I suggest creating a new rule event, that fires when this happens as well as a module hook, that allows others to create solutions that match their needs. For now I addressed the issue this way, around line 247 is where user_external_login_register() is called, and this is where the error is triggered. To prevent this I have changed the code to the below:

 // We need to check to see if this username / id exists
                     $name_field = variable_get('simplesamlphp_auth_user_name', 'eduPersonPrincipalName');
                     $extname = $_simplesamlphp_auth_saml_attributes($name_field);
                     
                     if(db_query('SELECT COUNT(uid) FROM {users} WHERE name = :name', array( ':name' => $extname ))->fetchField() < 1 ){
                            user_external_login_register($authname, 'simplesamlphp_auth');
                     } else { 
                           _simplesaml_auth_collision($authname, $extname);                           
                     }

The below code does not do any validation to see if the collision is valid or if the user is the same user in Drupal's database. This could be a security risk if you are not sure of all the users being in your IDP will match directly to the local drupal's information. Some basic validation that could be added is email check/or other values.

function _simplesaml_auth_collision($authname, $extname){ 
 $uid = db_query('SELECT uid FROM {users} WHERE name = :name', array( ':name' => $extname ))->fetchField();
 $account = user_load($uid);
 user_set_authmaps($account, array("authname_simplesamlphp_auth" => $authname));
 user_external_login_register($authname, 'simplesamlphp_auth');
}

Currently I am on a time crunch but if anyone is interested in this then I can look at creating a patch and finishing up some additional handling.

colan’s picture

@cmcintosh: A patch would be great. Thanks!

rgristroph’s picture

I also ran into this issue, and worked around it with my own queries and code to update the authmap table. In my case it was a bit specialized because I altered the authmap table to allow for case-sensitive authnames. I will see if I can generalize my code and post a patch.

milesw’s picture

Here's a patch to help this situation.

It adds a new configuration option "Enable authentication for manually created users", which is on by default.

When that option is enabled, authmaps get created on the fly when a user account of the same name already exists. (as I typed that just now I realized it might have security implications..?)

This patch also avoids registering a user when there will be a username collision.

milesw’s picture

Status: Active » Needs review

Updating status.

milesw’s picture

Patch #23 caused an exception whenever a saml-authenticated user manually created a new user account. This was because simplesamlphp_auth_user_insert() assumed the user being added was the same one that had authenticated via saml.

New patch attached.

milesw’s picture

azathot’s picture

Updating the patch to work with 7.x-2.x-dev.

steven.wichers’s picture

I have modified the way this is implemented so that modules can implement hook_simplesamlphp_auth_addauthmaps_alter() to specify an existing user to set an authmap for. The use case I had was matching SSO users based on their email attribute to existing Drupal accounts emails while the actual Drupal account username did not match the authname.

steven.wichers’s picture

Sorry, I don't think the previous patch will actually apply cleanly. Try this one.

c.breschkow’s picture

Patch #29 worked for me!

snufkin’s picture

Version: 7.x-2.x-dev » 7.x-3.x-dev
Status: Needs review » Needs work

The structure of the code has changed substantially in 3.x, so that we could get rid of the hook_init. Could you please reroll the patch against 7.x-3.x? Thanks!

msound’s picture

Status: Needs work » Needs review
FileSize
2.1 KB

Here's a simple patch for latest 7.x-3.x.

msound’s picture

The patch #32 has a problem, and does not work sometimes. The problem is $authname could be the user's name or email. Here is a new patch that works in both scenarios.

snufkin’s picture

Status: Needs review » Needs work

Could you reroll it in a way so that it uses username as the authmap? We should use it consistently as per the summery outlines here: #2357879: Problems altering user after provisioning, also mail is empty in 'users'

msound’s picture

Status: Needs work » Needs review
FileSize
2.09 KB

Rerolling patch using username as authname.

bisonbleu’s picture

I'm just running into this issue.

Question: Can i safely update from 7.x-2.0-alpha2 to 7.x-3.x-dev and apply this patch in #35 without breaking my current SimpleSAML setup ?

Context - I'm new to SSO and simpleSAMLphp Authentication i.e. I have no experience with setting this up. I currently have some 70 Drupal users that were manually created prior to the activation of simpleSAML and that now need to be added to the authmap table to prevent the creation of a second account for each and everyone of them - which is what I'm running into right now.

Any advice and/or suggestion would be much appreciated. Thanks

snufkin’s picture

The upgrade path has not been tested at all, so although I'd be very happy for more testers for 7.x-3.x-dev, I'd advise to upgrade very carefully and not on the production site. Alternatively you could use #29, although I am not sure it applies cleanly to 2.0-alpha2, or it needs to patch 2.x-dev.

bisonbleu’s picture

Thanks for your quick reply @snufkin. I'll give it a try and report back. My plan:

- 2.0-alpha2 --> 2.x-dev + patch #29
- 2.0-alpha2 --> 3.x-dev + patch #35 (time permitting)

bisonbleu’s picture

First results.

- patch in #29 fails to apply to the current 7.x-2.x-dev
- but it (#29) applies cleanly to 7.x-2.0-alpha2 and fixes my issue: existing or manually created Drupal accounts for which there is a match are properly added to the authmap table (i.e. no new account is created).

Note - For my use case, the email is the unique identifier (not the username). So I changed the last line

+ $existing_user = user_load_by_name($context['authname']);

to

+ $existing_user = user_load_by_mail($context['authname']);

snufkin’s picture

Be careful, that although this approach works for now, it is likely to be broken when you migrate to 3.x. We are going to be using the drupal name property as the authmap in later versions of the module, which will break your approach.

I know that this sounds painful, but there is a good reason for it: the IdP determines which user attribute is the unique identifier. It may be the email address, but in some instances it is not. Actually in some of the high ed standards the email address is explicitly declared as _not_ unique.

Now on to Drupal. We have to use either the name, or the mail drupal user property as the authmap, the unique id for the user. If we were to store the IdP provided unique id (UID) as an email address, then we implicitly limit the IdP from using any string format as it wants, because Drupal enforces email validation on this property. This leaves us with the only free string field, the name. Only this approach covers both use cases:

- the email address is the UID, in which case we will have to map that to both user->name and user->mail.
- the name is the UID, in which case we have to map the name to user->name and we have to make up a string that passes Drupals internal validation.

We need to come up with an architecture that covers both cases. One would be to make the module more complex, allowing site admins to determine if they want to use the email as the authmap property, or the username. A simpler approach would be to force everyone using the user->name property as the authmap, but this means that site builders will have to introduce a new field to map the username onto.

bisonbleu’s picture

Thanks for the warning @snufkin. Let me see if I understand.

The 2.x branch uses the user->mail as the unique identifier (UID) in the authmap BUT the 3.x branch changes that and instead uses the user->name as UID ?

Will there be a upgrade path from 2.x to 3.x ?

snufkin’s picture

Actually no, the 2.x series uses the user->name. the 3.x changed that to user->mail in some locations (in save in particular). It will however change back to 2.x because of what I've described in my previous comment.

So for your use case it will be problematic either way, because none of the branches will use the mail property.

I really want an upgrade path in any case, but once we have switched back to using user->name there shouldn't be that many issues leftover.

bisonbleu’s picture

Ok, got it. So using user->name for the unique identifier (UID) is the way to go.
Thanks.

snufkin’s picture

Status: Needs review » Fixed

I've committed the patch that ensures that user->name is used as the UID from #2357879: Problems altering user after provisioning, also mail is empty in 'users', so now this issue can correctly rely on the name property being used as the authmap.

The patch is correctly using authname_simplesamlphp_auth as the key passed to user_set_authmap so the entries in the authmap table will have the simplesamlphp_auth module name as the ones created on the fly. Existing functionality should not be impacted as in the conditional which checks for this feature to be enabled the fallback branch contains the old behaviour, therefore I'm committing this.

  • snufkin committed 56869aa on 7.x-3.x authored by msound
    Issue #1280930 by msound, milesw, steven.wichers, azathot: Create...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

svendecabooter’s picture

Version: 7.x-3.x-dev » 8.x-3.x-dev
Assigned: Unassigned » svendecabooter
Status: Closed (fixed) » Needs work

This still needs to be ported to the 8.x-3.x branch.

  • svendecabooter committed af3b59e on 8.x-3.x
    Issue #1280930 - Create authmap entries for pre-existing Drupal users (...

  • svendecabooter committed 9b95604 on 8.x-3.x
    Issue #1280930 - Create authmap entries for pre-existing Drupal users (...
svendecabooter’s picture

Version: 8.x-3.x-dev » 7.x-3.x-dev
Component: Code » Documentation
Assigned: svendecabooter » Unassigned
Status: Needs work » Needs review
FileSize
1.06 KB

8.x-3.x now has feature parity with 7.x-3.x regarding this.
In the 8.x-3.x branch I have added some extra documentation / warning texts to this setting.
Attached is a patch for 7.x-3.x to included this description, since I think the consequences of enabling this feature should be better documented.

dureaghin’s picture

#8 Works for me. Thank you Lauren Kelly!

This is the export of the rule which adds a record to authmap after saving a new user account:

{ "rules_update_authmap" : {
    "LABEL" : "Update authmap",
    "PLUGIN" : "reaction rule",
    "ACTIVE" : false,
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "php" ],
    "ON" : { "user_insert" : [] },
    "IF" : [
      { "user_has_role" : { "account" : [ "account" ], "roles" : { "value" : { "4" : "4" } } } }
    ],
    "DO" : [
      { "php_eval" : { "code" : "user_set_authmaps($account, array(\u0027authname_simplesamlphp_auth\u0027 =\u003E $account-\u003Ename));" } }
    ]
  }
}

Check authmap records in MySQL database:
mysql -u root -p
mysql> use DB_NAME;

mysql> SELECT * FROM authmap;
+------+--------+----------+--------------------+
| aid  | uid    | authname | module             |
+------+--------+----------+--------------------+
|    2 | 123    | user_123 | simplesamlphp_auth |
|    3 | 345    | user_345 | simplesamlphp_auth |
dureaghin’s picture

The whole my idea to create a view page with option to manage users from views page with flag button "Add authmap" and "Delete authmap" OR use vbo to batch all records. We need to use two rules with action to execute php code, first rule with event "A user has been flagged, under "Authmap" and second rule event with "A user has been unflagged, under "Authmap".

Flag export:

$flags = array();
// Exported flag: "Authmap".
$flags['authmap'] = array(
  'content_type' => 'user',
  'title' => 'Authmap',
  'global' => 0,
  'types' => array(),
  'flag_short' => 'Add authmap',
  'flag_long' => '',
  'flag_message' => '',
  'unflag_short' => 'Delete authmap',
  'unflag_long' => '',
  'unflag_message' => '',
  'unflag_denied_text' => '',
  'link_type' => 'toggle',
  'roles' => array(
    'flag' => array(
      0 => 3,
    ),
    'unflag' => array(
      0 => 3,
    ),
  ),
  'weight' => 0,
  'show_on_entity' => 0,
  'show_on_form' => 0,
  'access_author' => '',
  'show_on_profile' => 0,
  'access_uid' => 'others',
  'api_version' => 2,
);
return $flags;

Views export:

$view = new view();
$view->name = 'authmap';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'users';
$view->human_name = 'Authmap';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['use_ajax'] = TRUE;
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'none';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['exposed_form']['options']['submit_button'] = 'Search';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['pager']['options']['items_per_page'] = '10';
$handler->display->display_options['pager']['options']['offset'] = '0';
$handler->display->display_options['pager']['options']['id'] = '0';
$handler->display->display_options['pager']['options']['quantity'] = '9';
$handler->display->display_options['style_plugin'] = 'table';
/* Relationship: Flags: authmap */
$handler->display->display_options['relationships']['flag_content_rel']['id'] = 'flag_content_rel';
$handler->display->display_options['relationships']['flag_content_rel']['table'] = 'users';
$handler->display->display_options['relationships']['flag_content_rel']['field'] = 'flag_content_rel';
$handler->display->display_options['relationships']['flag_content_rel']['required'] = 0;
$handler->display->display_options['relationships']['flag_content_rel']['flag'] = 'authmap';
/* Field: Bulk operations: User */
$handler->display->display_options['fields']['views_bulk_operations']['id'] = 'views_bulk_operations';
$handler->display->display_options['fields']['views_bulk_operations']['table'] = 'users';
$handler->display->display_options['fields']['views_bulk_operations']['field'] = 'views_bulk_operations';
$handler->display->display_options['fields']['views_bulk_operations']['label'] = '';
$handler->display->display_options['fields']['views_bulk_operations']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['display_type'] = '0';
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['enable_select_all_pages'] = 1;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['row_clickable'] = 1;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['force_single'] = 0;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['entity_load_capacity'] = '10';
$handler->display->display_options['fields']['views_bulk_operations']['vbo_operations'] = array(
  'action::flag_user_action' => array(
    'selected' => 1,
    'postpone_processing' => 0,
    'skip_confirmation' => 1,
    'override_label' => 0,
    'label' => '',
  ),
);
/* Field: User: Name */
$handler->display->display_options['fields']['name']['id'] = 'name';
$handler->display->display_options['fields']['name']['table'] = 'users';
$handler->display->display_options['fields']['name']['field'] = 'name';
$handler->display->display_options['fields']['name']['label'] = 'User Name';
$handler->display->display_options['fields']['name']['alter']['word_boundary'] = FALSE;
$handler->display->display_options['fields']['name']['alter']['ellipsis'] = FALSE;
/* Field: User: E-mail */
$handler->display->display_options['fields']['mail']['id'] = 'mail';
$handler->display->display_options['fields']['mail']['table'] = 'users';
$handler->display->display_options['fields']['mail']['field'] = 'mail';
$handler->display->display_options['fields']['mail']['link_to_user'] = '0';
/* Field: User: Roles */
$handler->display->display_options['fields']['rid']['id'] = 'rid';
$handler->display->display_options['fields']['rid']['table'] = 'users_roles';
$handler->display->display_options['fields']['rid']['field'] = 'rid';
/* Field: Flags: Flag link */
$handler->display->display_options['fields']['ops']['id'] = 'ops';
$handler->display->display_options['fields']['ops']['table'] = 'flag_content';
$handler->display->display_options['fields']['ops']['field'] = 'ops';
$handler->display->display_options['fields']['ops']['relationship'] = 'flag_content_rel';
$handler->display->display_options['fields']['ops']['label'] = '';
$handler->display->display_options['fields']['ops']['element_label_colon'] = FALSE;
$handler->display->display_options['fields']['ops']['link_type'] = 'normal';
/* Sort criterion: User: Created date */
$handler->display->display_options['sorts']['created']['id'] = 'created';
$handler->display->display_options['sorts']['created']['table'] = 'users';
$handler->display->display_options['sorts']['created']['field'] = 'created';
$handler->display->display_options['sorts']['created']['order'] = 'DESC';
/* Filter criterion: User: Active */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'users';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = '1';
$handler->display->display_options['filters']['status']['group'] = 1;
$handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
/* Filter criterion: User: Roles */
$handler->display->display_options['filters']['rid']['id'] = 'rid';
$handler->display->display_options['filters']['rid']['table'] = 'users_roles';
$handler->display->display_options['filters']['rid']['field'] = 'rid';
$handler->display->display_options['filters']['rid']['operator'] = 'not';
$handler->display->display_options['filters']['rid']['value'] = array(
  3 => '3',
);
$handler->display->display_options['filters']['rid']['group'] = 1;

/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page');
$handler->display->display_options['path'] = 'authmap';

Export of the rule to add record to authmap table:

{ "rules_add_authmap" : {
    "LABEL" : "Add authmap",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "php", "flag" ],
    "ON" : { "flag_flagged_authmap" : [] },
    "IF" : [
      { "user_has_role" : { "account" : [ "flagged-user" ], "roles" : { "value" : { "3" : "3" } } } }
    ],
    "DO" : [
      { "php_eval" : { "code" : "user_set_authmaps($flagged_user, array(\u0027authname_simplesamlphp_auth\u0027 =\u003E $flagged_user-\u003Ename));" } },
      { "drupal_message" : { "message" : "Authmap has been added for [flagged-user:name]." } }
    ]
  }
}

Export of the rule to delete record from authmap table:

{ "rules_delete_authmap" : {
    "LABEL" : "Delete authmap",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "php", "flag" ],
    "ON" : { "flag_unflagged_authmap" : [] },
    "IF" : [
      { "user_has_role" : { "account" : [ "flagged-user" ], "roles" : { "value" : { "3" : "3" } } } }
    ],
    "DO" : [
      { "php_eval" : { "code" : "  db_delete(\u0027authmap\u0027)\r\n    -\u003Econdition(\u0027uid\u0027, $flagged_user-\u003Euid)\r\n    -\u003Econdition(\u0027authname\u0027, $flagged_user-\u003Ename)\r\n    -\u003Eexecute();" } },
      { "drupal_message" : { "message" : "Authmap has been deleted for [flagged-user:name]." } }
    ]
  }
}

Works like a charm!