When you trap the 18488 error, You need to show your own "change password" dialog, and use connection string properties "Old Password"
/"Password"
via SQL Native Client
as your provider (i.e. Provider=SQLNCLI10
or SQLNCLI.1
).
Here is a small code I used to test this:
procedure TForm1.Button1Click(Sender: TObject);
begin
// 12345 is the "old password"
ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;Password=12345;User ID=test;Initial Catalog=test;Data Source=127.0.0.1;Persist Security Info=True;';
try
ADOConnection1.Open;
except
if Assigned(ADOConnection1.Errors) and (ADOConnection1.Errors.Count > 0) and
(ADOConnection1.Errors.Item[0].NativeError = 18488) then
begin
// show your "change password" dialog... new password is 67890
ADOConnection1.ConnectionString := 'Provider=SQLNCLI10.1;Old Password=12345;Password=67890;User ID=test;Initial Catalog=test;Data Source=127.0.0.1;Persist Security Info=True;';
ADOConnection1.Open; // this will login and change the password
// OPTIONAL (unless you use SQLNCLI10.1 anyway)
// you may close the connection and re-open with your original provider and new password
ADOConnection1.Close;
ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;Password=67890;User ID=test;Initial Catalog=test;Data Source=127.0.0.1;Persist Security Info=True;';
ADOConnection1.Open;
end
else
raise;
end;
ShowMessage('Login OK');
end;
My answer is based on these readings:
This is the official way of changing passwords from the client side when you enforce password expiration and use "User must change password at next login" option on the SQL server.
If installing the SQL Server Native Client on the users machine is an issue, I can think of few more options:
- Create a web-service (on your servers) that will be responsible for changing the user's password provided old/new passwords and returning status back to your client.
- Connect as "super user" (such as
sa
), and alter the user's/login password. meaning you will need to hold that username/password on the client machine (bad idea IMHO from security point of view but might be workable). - not tested
- do NOT create SQL logins with "User must change password at next login". which is my favorite solution.