Problem
ADFS 4.0 on Windows Server 2016 tells users to log in with their full email address “someone@example.com.” This generates many support requests, and complaints about too much typing.
Additionally, some extranet users may have email addresses not on the domain, and it’s unclear which email address they should supply.
This affects both the ADFS log in page, and the ADFS password change page.
Solution Methodology
ADFS Server 4.0 has PowerShell cmdlets to manage the content delivered to users during authentication requests: https://technet.microsoft.com/windows-server-docs/identity/ad-fs/operations/ad-fs-user-sign-in-customization
We’ll focus on the following
Get-AdfsWebTheme
and
Set-AdfsWebTheme
Of particular interest here is that we’re able to modify the JavaScript that runs on these pages.
Steps
Use PowerShell to manage custom ADFS Themes
- Export the Default ADFS Theme using this snippet:
Export-ADFSWebTheme -Name "Default" -DirectoryPath c:\test
- Use your favorite editor to open c:\test\script\onload.js
- Add the snippets from below (as desired) into onload.js
- Create a New ADFS Theme
New-AdfsWebTheme -Name BetterDefault -SourceName c:\test
- Set your new theme as the default (best for testing)
Set-ADFSWebConfig -ActiveThemeName BetterDefault
- Set your new theme as the default (best for testing)
- Alternatively, you may update an existing theme with your code changes
Set-AdfsWebTheme -TargetName "Default" -AdditionalFileResource @{Uri=“/adfs/portal/script/onload.js”;Path=“C:\theme\script\onload.js"}
Placeholder Text Solution
To update the “someone@example.com” placeholder on both the login and the password change ADFS pages, paste this code into your onload.js, and update your ADFS theme.
function UpdatePlaceholders() { var userName; if (typeof Login != 'undefined'){ userName = document.getElementById(Login.userNameInput) } if (typeof UpdatePassword != 'undefined'){ userName = document.getElementById(UpdatePassword.userNameInput); } if (typeof userName != 'undefined'){ userName.setAttribute("placeholder","Username"); } } document.addEventListener("DOMContentLoaded", function(){ // Handler when the DOM is fully loaded UpdatePlaceholders() });
Formatting of the Username field
For single-domain organizations, it may be less than desirable to force users to enter the domain name as part of their username. To “fix” this requirement of entering usernames in a format of “domain\username” or “username@domain.com”, paste the following code into your onload.js. Make sure to update your domain where appropriate.
Logon Username Format Solution
if (typeof Login != 'undefined'){ Login.submitLoginRequest = function () { var u = new InputUtil(); var e = new LoginErrors(); var userName = document.getElementById(Login.userNameInput); var password = document.getElementById(Login.passwordInput); if (userName.value && !userName.value.match('[@\\\\]')) { var userNameValue = 'example.org\\' + userName.value; document.forms['loginForm'].UserName.value = userNameValue; } if (!userName.value) { u.setError(userName, e.userNameFormatError); return false; } if (!password.value) { u.setError(password, e.passwordEmpty); return false; } document.forms['loginForm'].submit(); return false; }; }
Password Change Username Formatting Solution
if (typeof UpdatePassword != 'undefined'){ UpdatePassword.submitPasswordChange = function () { var u = new InputUtil(); var e = new UpdErrors(); var userName = document.getElementById(UpdatePassword.userNameInput); var oldPassword = document.getElementById(UpdatePassword.oldPasswordInput); var newPassword = document.getElementById(UpdatePassword.newPasswordInput); var confirmNewPassword = document.getElementById(UpdatePassword.confirmNewPasswordInput); if (userName.value && !userName.value.match('[@\\\\]')) { var userNameValue = 'example.org\\' + userName.value; document.forms['updatePasswordForm'].UserName.value = userNameValue; } if (!userName.value) { u.setError(userName, e.userNameFormatError); return false; } if (!oldPassword.value) { u.setError(oldPassword, e.oldPasswordEmpty); return false; } if (oldPassword.value.length > maxPasswordLength) { u.setError(oldPassword, e.oldPasswordTooLong); return false; } if (!newPassword.value) { u.setError(newPassword, e.newPasswordEmpty); return false; } if (!confirmNewPassword.value) { u.setError(confirmNewPassword, e.confirmNewPasswordEmpty); return false; } if (newPassword.value.length > maxPasswordLength) { u.setError(newPassword, e.newPasswordTooLong); return false; } if (newPassword.value !== confirmNewPassword.value) { u.setError(confirmNewPassword, e.mismatchError); return false; } return true; }; }
Thanks for reading! If you have any questions, feel free to send me a tweet @crossan007.
Great post. I ‘m confronting a couple of these difficulties.
This looks great – we have multiple domains but all use the same email suffix
Do you know of a way to append @example.com on the password change page?
I have managed to get it working on the login screen via this below:
//remove email address requirement
function runScript(e) {
if (e.keyCode == 13) {
AppendUPN();
return Login.submitLoginRequest();
}
}
var AppendUPN = function () {
var userName = document.getElementById(Login.userNameInput);
var lowerUserName = userName.value.toLowerCase();
//Check to see if they already included the UPN
var li = lowerUserName.lastIndexOf(‘@example.com’);
if (li == -1)
{
userName.value = userName.value + ‘@example.com’;
}
return true;
}
document.getElementById(‘submitButton’).onclick = new Function(‘AppendUPN();return Login.submitLoginRequest();’);
document.getElementById(‘passwordInput’).onkeypress = runScript;
document.getElementById(“userNameInput”).placeholder=”Username”;
Yes – this blog post should have affected both pages.
I don’t understand the placeholder update. What does it change it TO? There’s no place to put the text that you would like. Some people would want ‘username@yourdomain.com’, others might like ’emailaddress@yourdomain.com’.
The other fix I see elsewhere is to update the usernameinput.placeholder value, but that seems to have vanished from the onload.js once you add 2016 servers to a 2012R2 farm.
Thanks much!
Hello,
On the password reset page it doesn’t seem to work, it required to enter the full username.
Any ideas please?
Thanks
Hi,
will this work for ADFS Server 2019 ?
Hello,
We have customized our ADFS login page to add the suffix of @example.com to our users SAMAccountName but during an exception condition the username field is pre populated with username@example.com. Is it possible to blank the username field during an exception condition or set it to just username without the suffix. Any help in this regard will be greatly appreciated.
Regards,
Syed