Set the shared account's password before claiming it
Provisioning assigned AuthenticationProviderId and only then called IUserManager.ChangePassword. Jellyfin dispatches that call to the provider the user is currently assigned to, so it reached this plugin's own ChangePassword, which refuses by design. Creating a group by typing "alice+bob" at the login screen therefore died with NotSupportedException. Set the placeholder password first, while the freshly created account is still on Jellyfin's default provider, then claim it. The new end-to-end tests wire the real provisioning, group and authentication services together rather than mocking IProvisioningService, and cover a group created on demand being unlocked afterwards by either member's password. With the old ordering restored, six of them fail with the original exception. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,15 +100,20 @@ public class ProvisioningService : IProvisioningService
|
||||
|
||||
var sharedUser = await _userManager.CreateUserAsync(accountName).ConfigureAwait(false);
|
||||
|
||||
// The shared account never authenticates against its own password - our provider checks
|
||||
// member hashes instead. Setting a random one avoids leaving a passwordless account behind
|
||||
// if the provider is ever unassigned.
|
||||
//
|
||||
// This must happen before the account is claimed below. IUserManager.ChangePassword
|
||||
// dispatches to the provider the user is currently assigned to, and ours refuses the call
|
||||
// by design, so claiming first would make provisioning throw NotSupportedException. A
|
||||
// freshly created user is still on Jellyfin's default provider, which stores the hash.
|
||||
await _userManager.ChangePassword(sharedUser, GenerateUnusedPassword()).ConfigureAwait(false);
|
||||
|
||||
// Route this account's logins through our provider. Jellyfin matches providers by
|
||||
// GetType().FullName, the same key the SSO plugin uses, and the assignment only sticks
|
||||
// once the user is updated.
|
||||
sharedUser.AuthenticationProviderId = AuthProviderId;
|
||||
|
||||
// The shared account never authenticates against its own password - our provider checks
|
||||
// member hashes instead. Setting a random one avoids leaving a passwordless account behind
|
||||
// if the provider is ever unassigned.
|
||||
await _userManager.ChangePassword(sharedUser, GenerateUnusedPassword()).ConfigureAwait(false);
|
||||
await _userManager.UpdateUserAsync(sharedUser).ConfigureAwait(false);
|
||||
|
||||
await ApplyLibraryAccessAsync(sharedUser.Id, distinctIds).ConfigureAwait(false);
|
||||
|
||||
Reference in New Issue
Block a user