Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change user e-mail on login - LDAP #158

Open
aaloise opened this issue Aug 6, 2024 · 13 comments
Open

Change user e-mail on login - LDAP #158

aaloise opened this issue Aug 6, 2024 · 13 comments
Labels

Comments

@aaloise
Copy link

aaloise commented Aug 6, 2024

It's probably not a good practice to open an issue to ask a question. I was unable to post on the support forum (https://wordpress.org/support/plugin/authorizer/).

The question is actually quite simple, but I haven't found a direction yet. Users in the LDAP domain we have are @abc.com emails and I need this email to be "transformed" to @xyz.com after a successfull authentication.

The closest I found was using functions.php but without success.

If possible, I would like some guidance, and I apologize in advance for using github to ask a simple question.

@pkarjala
Copy link
Collaborator

pkarjala commented Aug 7, 2024

Hi @aaloise it's fine that you've opened an issue here! In order to keep discussion in one place, I've closed your recently opened WordPress support thread and will keep my responses here.

You may want to consider that if a user is created in WordPress with an abc.com email address and that user expects to receive emails at that domain name, they will not receive them if the email is changed from abc.com to xyz.com, or the emails could be sent to someone completely different who has the same xyz.com email address. This is important because password reset emails and other notifications that are sent via WordPress go to the email address on the user's account. Just something to be aware of!

The main hook in Authorizer that you can use to manipulate user data on account creation would be authorizer_user_register which can be found at https://github.com/uhm-coe/authorizer/blob/master/src/authorizer/class-authorization.php#L291-L310. More on how to create actions when this hook is called can be found at https://developer.wordpress.org/reference/functions/add_action/

So you would want to make your function that will check if the domain name on the email address is abc.com and update it to xyz.com, then create your action with something like:

my_function( $user, $user_data ) {
    // ...some code here to check and manipulate email addresses
}

add_action( 'authorizer_user_register', 'my_function', 10, 2 );

I hope that gets you started! Please let us know if you have additional questions.

@pkarjala pkarjala closed this as completed Aug 7, 2024
@aaloise
Copy link
Author

aaloise commented Aug 9, 2024

I was able to get it done! Thanks @pkarjala !

@aaloise
Copy link
Author

aaloise commented Aug 21, 2024

Well, it seems I'm missing something here. I was able to change the users e-mail, but when they try to authenticate again, WP creates a new user with the "old" e-mail, instead of authenticate again with the same user before.

I assume that some work must be done with the hooks, but before that I need to understand the whole process of authentication using LDAP/AD.

Any tips why a new user gets created and what workaround should I use? Thanks again!

@pkarjala
Copy link
Collaborator

Hi @aaloise without seeing your code, it is difficult to determine what might be happening in this case.

It sounds like when the user initially logs in with an abc.com email and is authenticated against LDAP, their email is altered to an xyz.com address using your code and then the user is added to WordPress with the xyz.com email address.

The next time the user attempts to log in, are they using their username or their email address? If they are using their email address, are they logging in with the abc.com or the xyz.com email?

@pkarjala pkarjala reopened this Aug 21, 2024
@aaloise
Copy link
Author

aaloise commented Aug 21, 2024

The users authenticate using a username (sAmAccountName) at all moments. The first time, when it doesn't exist in WP, the e-mail is changed to xyz.com and saved in the DB. The second time, instead of authenticate against the recently created user, WP creates a new one using abc.com e-mail in both username and e-mail fields.

The code I am using is this:

function custom_email_domain_change($user, $user_data) {
    error_log('Hook authorizer_user_register called'); 
    error_log('User Data: ' . print_r($user_data, true)); 
    
    if (isset($user_data['email']) && strpos($user_data['email'], '@abc.com') !== false) {
        
        $user_data['email'] = str_replace('@abc.com', '@xyz.com', $user_data['email']);
        
        $user->user_email = $user_data['email'];
        
        wp_update_user(array('ID' => $user->ID, 'user_email' => $user->user_email));
    }

    error_log('Updated User Email: ' . $user->user_email); 
    
    return $user;
}

add_action('authorizer_user_register', 'custom_email_domain_change', 10, 2);

@pkarjala
Copy link
Collaborator

Got it, thank you for sharing your code!

Can you please let us know what is set in the Authorizer configuration under the External Service tab for the field LDAP attribute containing email address?

Additionally, are the LDAP Directory User and LDAP Directory User Password fields set?

@aaloise
Copy link
Author

aaloise commented Aug 21, 2024

The LDAP attribute containing the email address under External Service is "mail".

Yes for both LDAP user and password. They are set.

Just a quick note. The LDAP server is an Active Directory.

@pkarjala
Copy link
Collaborator

Thanks; one more question. Under the Login Access tab, what is set for Who can log into the site??

@pkarjala
Copy link
Collaborator

OK, so what we suspect is happening is the following:

  1. The user logs into WordPress using the LDAP authentication for the first time.
  2. The LDAP credentials for the user are checked and verified.
  3. The verified LDAP user is authenticated and then a WordPress account is created through Authorizer. Your hook alters their email address to xyz.com after the WordPress account is created.
  4. The same user logs out and back in.
  5. The LDAP credentials for the user are checked and verified.
  6. The verified LDAP user is authenticated, then Authorizer attempts to match the email address of the user against an existing WordPress user. Because the LDAP user's email address is abc.com and not xyz.com, there is no match. So a new user is created in WordPress using the abc.com email and your hook does not alter it.

The issue is that last one as we do not currently have a way to intercept this process. Instead, however, we suggest trying the following:

  1. Remove the code for your hook from your theme.
  2. In Authorizer under the External Service tab in the field LDAP attribute containing email address, instead of putting mail, put @xyz.com instead.

Please note that this will only work if your LDAP usernames are an exact match to the first part of the email address before the domain name. So if an LDAP user is pkarjala, the email address must be [email protected].

Please give this a try and let us know how it goes!

@aaloise
Copy link
Author

aaloise commented Aug 22, 2024

Steps 1 to 6 are exactly what's happening.

I tried your suggestion, by setting @xyz.com instead of setting "mail" attribute. Unfortunately sAmAccountName is not an exact match to the first part of the e-mail address. The username is an unique ID, so it is a lot of numbers, while e-mail has firstname and lastname.

There is the userPrincipalName attribute, which is [email protected]. Is there a way we can set it as the username in Authorizer, but remove the @domain.com part, remaining firstname.lastname only during authentication? That way we could set @xyz.com as the LDAP containing e-mail address, which would give us [email protected] at the end.

Is that doable?

@pkarjala
Copy link
Collaborator

That might be doable, but another better option may be to create a new field in your AD/LDAP setup that holds something like wordpressEmail which is a composite of the user's login name and the desired domain name. You would then set this field to be used for the LDAP attribute containing email address in Authorizer.

This way no custom code is required, but you will need to have that field populated in AD/LDAP on your end.

@aaloise
Copy link
Author

aaloise commented Aug 22, 2024

Sadly I have no management over the domain, other then to retrieve data on it. Because of that I can't create a new attribute.

For now it seems that userPrincipalName is the closest candidate here. But for that I need to use a hook, I supose.

@figureone
Copy link
Member

You should be able to use the authorizer_ldap_search_filter hook to allow users to type in the username portion of userPrincipalName, and then you append the @domain portion manually in the hook so the LDAP search finds the user.
https://github.com/uhm-coe/authorizer/blob/master/src/authorizer/class-authentication.php#L1303-L1313

Example:

// If your users log in with just a username, but your LDAP search filter 
// matches on an attribute that contains an email address, use this filter to
// append the domain portion of the email address to the username.
// Example search filter (if `userPrincipalName` is the lookup attribute): 
//   (userPrincipalName=username) => ([email protected])
add_filter( 'authorizer_ldap_search_filter', function ( $search_filter, $ldap_uid, $username ) {
	$search_filter = str_replace( $username, $username . '@domain.com', $search_filter );
	return $search_filter;
}, 10, 3 );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants