Migration of Existing LDAP users to SAML Failed following the guide

that means:

  • We created an Enterprise application in Azure.
  • We configured SAML in sonarqube.
  • It is possible to login with users that do not already exist.
  • It is not possible to login with users that already exist.

I will now give an example how we tried to migrate an existing LDAP user user1

  • To patch the existing user user1 we made the following API call:
curl -X POST -v  -u $SONAR_TOKEN: "https://sonar.example.com/api/users/update_identity_provider?login=user1&newExternalIdentity=user1@organisation.com&newExternalProvider=saml"

where user1@organisation.com is the email we use to login in our organisation in azure.

When we now examine the user we get the following:

{
  "paging": {
    "pageIndex": 1,
    "pageSize": 50,
    "total": 1
  },
  "users": [
    {
      "login": "user1",
      "name": "Doe, John",
      "active": true,
      "email": "user1@onpremise-email-domain.com",
      "groups": [
        "_somegroup",
        "sonar-users"
      ],
      "tokensCount": 1,
      "local": false,
      "externalIdentity": "user1@organisation.com",
      "externalProvider": "saml",
      "avatar": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "lastConnectionDate": "2022-03-17T09:41:30+0000"
    }
  ]
}

When we now try to login we get the following error message on screen:

You're not authorized to access this page. Please contact the administrator.

Reason: This account is already associated with another authentication method. Sign in using the current authentication method, or contact your administrator to transfer your account to a different authentication method.

In the Trace Log of Sonar we extracted the following cause:

2022.03.17 08:04:01 DEBUG web[xxxxxxxxxxxxxxx][auth.event] login failure [cause|Email 'user1@onpremise-email-domain.com' is already used][method|OAUTH2][provider|EXTERNAL|SAML][IP|xxxxxxxxxx|xxxxxxxxxx][login|user1@organisation.com]

The relevant claims recevied by sonar for the user are:

{
http://schemas.microsoft.com/identity/claims/tenantid=[xxxxxxxxxxxxxxxxxxxxxxxxxxx], 
http://schemas.microsoft.com/identity/claims/identityprovider=[https://sts.windows.net/xxxxxxxxxxxxxxxxxxxxxxx/],
http://schemas.microsoft.com/identity/claims/objectidentifier=[xxxxxxxxxxxxxxxxxxxxxxxxxxxxx], 
http://schemas.microsoft.com/claims/authnmethodsreferences=[http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password], 
name=[Doe, John], 
groups=[_somegroup], 
last_name=[Doe],
first_name=[John],
email=[user1@onpremise-email-domain.com], 
userprinciplename=[user1@organisation.com], 
username=[user1]
}

Else here is some information that could be relevant:

"Server ID":"xxxxxxxxxxxx",
"Version":"8.9.7.52159",
"Docker":true,
"External User Authentication":"LDAP",
"Accepted external identity providers":"SAML",
"External identity providers whose users are allowed to sign themselves up":"SAML",
"High Availability":false,
"Official Distribution":true,
"Force authentication":true 
sonar.auth.saml.user.login=userprinciplename
sonar.auth.saml.user.name=name
sonar.auth.saml.user.email=email
sonar.auth.saml.group.name=groups

So overall it seems Sonar is Rejecting the login because the email adresses match.
I don’t understand entirely, why that is the case.
If I change the email claim, for example, to user1@organisation.com an entirely new user is created.

The code comments of the authenticate function also specifies that:

     * If the email of the user is already used by an existing user of the platform,
     * then the user is not authenticated and he's redirected to a dedicated page.

So it is unclear to me how we shall migrate a user, if authentication using SAML seems to trigger the registration of a new user and throws an execption because the email already exists, instead of looking for the user that matches the external identity.

In fact, I can attach the same external identity to multiple users on registration, which does not seem to be intended.

This means in theory I should be able to create an arbitrary amount of users, by simply changing my email claims sent to sonar.

Thanks in advance!

Hey there.

  • Is it possible that any other users on your instance (local or otherwise) share the same e-mail address as this user?
  • Have you made sure the case of the original login and new login are the same?

Hey,

Sorry I was on vacation :wink:

Yes, as I want to migrate existing users from LDAP to SAML, they have the same email-address.
As you can see in the claims and the result of the API call.
But there is no other user that shares the same email-address.

Following your migration guide does not work, that’s why i’m asking:

Before the migration my user looks like this:

$ curl -X GET -u $SONAR_TOKEN: "https://sonar.example.com/api/users/search?q=user1" 
{
  "paging": {
    "pageIndex": 1,
    "pageSize": 50,
    "total": 1
  },
  "users": [
    {
      "login": "user1",
      "name": "Doe, John",
      "active": true,
      "email": "user1@onpremise-email-domain.com",
      "groups": [
        "_somegroup",
        "sonar-users"
      ],
      "tokensCount": 1,
      "local": false,
      "externalIdentity": "user1",
      "externalProvider": "sonarqube",
      "avatar": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "lastConnectionDate": "2022-03-17T09:41:30+0000"
    }
  ]
}

Then we migrate it: curl -X POST -v -u $SONAR_TOKEN: "https://sonar.example.com/api/users/update_identity_provider?login=user1&newExternalIdentity=user1@organisation.com&newExternalProvider=saml"

Then it looks like this:

{
  "paging": {
    "pageIndex": 1,
    "pageSize": 50,
    "total": 1
  },
  "users": [
    {
      "login": "user1",
      "name": "Doe, John",
      "active": true,
      "email": "user1@onpremise-email-domain.com",
      "groups": [
        "_somegroup",
        "sonar-users"
      ],
      "tokensCount": 1,
      "local": false,
      "externalIdentity": "user1@organisation.com",
      "externalProvider": "saml",
      "avatar": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "lastConnectionDate": "2022-03-17T09:41:30+0000"
    }
  ]

Have you made sure the case of the original login and new login are the same?

You mean that the logins are case sensitive? I’m confused :wink:

When i login with SAML i’ll do so with my external identity - my loginname should never matter here.
In fact an external identity should be allowed exactly one time and unique, so it can be mapped to the correct user.

I would appreciate if you ask the Devs about this. I believe this behaviour is a bug and not how it is intended.

Hi,

Yes, logins are case-sensitive.

 
Ann

Yeah but I hope that does not matter in this case.
When we login via SAML we have no control over the actual login of the user, only the external identity.

And for LDAP there is the setting sonar.authenticator.downcase which we can set to true when connecting to a LDAP server using a case-insensitive setup.

Hi,

Yes, but you’re migrating away from LDAP. That setting doesn’t exist for SAML. Can you update your user in SonarQube so that all the casing matches?

 
Ann

So, when and how does Sonar determine the login name of a user?
Which claim sets the actual login property? - I would say that this not possible to control when looking at the code.

I uncovered your secrets :stuck_out_tongue:
In fact there was one user that we “deleted” previously because our saml claims where not defined correctly.

But, what I did not know until this second:

Sonarqube actually does not delete users, but can only deactivate them.
So they are still present in the database.

I had to go into the pod of the database and actually DELETE the user.

This is also highly concerning with regard to storing userdata :wink:
People should have the option to DELETE their user entirely.