浏览代码

Override username with AuthenticationProvider

Pass back the Username directive returned by an AuthenticationProvider
to the calling code, so we may override the user-provided Username
value if the authentication provider passes this back. Useful for
instance in an LDAP scenario where what the user types may not
necessarily be the "username" that is mapped in the system, e.g.
the user providing 'mail' while 'uid' is the "username" value.
Could also then be extensible to other authentication providers
as well, should they wish to do a similar thing.
Joshua Boniface 6 年之前
父节点
当前提交
1af9c047fb
共有 1 个文件被更改,包括 33 次插入11 次删除
  1. 33 11
      Emby.Server.Implementations/Library/UserManager.cs

+ 33 - 11
Emby.Server.Implementations/Library/UserManager.cs

@@ -277,24 +277,35 @@ namespace Emby.Server.Implementations.Library
                 .FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
                 .FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
 
 
             var success = false;
             var success = false;
+            string updatedUsername = null;
             IAuthenticationProvider authenticationProvider = null;
             IAuthenticationProvider authenticationProvider = null;
 
 
             if (user != null)
             if (user != null)
             {
             {
                 var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false);
                 var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false);
                 authenticationProvider = authResult.Item1;
                 authenticationProvider = authResult.Item1;
-                success = authResult.Item2;
+                updatedUsername = authResult.Item2;
+                success = authResult.Item3;
             }
             }
             else
             else
             {
             {
                 // user is null
                 // user is null
                 var authResult = await AuthenticateLocalUser(username, password, hashedPassword, null, remoteEndPoint).ConfigureAwait(false);
                 var authResult = await AuthenticateLocalUser(username, password, hashedPassword, null, remoteEndPoint).ConfigureAwait(false);
                 authenticationProvider = authResult.Item1;
                 authenticationProvider = authResult.Item1;
-                success = authResult.Item2;
+                updatedUsername = authResult.Item2;
+                success = authResult.Item3;
 
 
                 if (success && authenticationProvider != null && !(authenticationProvider is DefaultAuthenticationProvider))
                 if (success && authenticationProvider != null && !(authenticationProvider is DefaultAuthenticationProvider))
                 {
                 {
-                    user = await CreateUser(username).ConfigureAwait(false);
+                    // We should trust the user that the authprovider says, not what was typed
+                    if (updatedUsername != username)
+                    {
+                        username = updatedUsername;
+                    }
+
+                    // Search the database for the user again; the authprovider might have created it
+                    user = Users
+                        .FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
 
 
                     var hasNewUserPolicy = authenticationProvider as IHasNewUserPolicy;
                     var hasNewUserPolicy = authenticationProvider as IHasNewUserPolicy;
                     if (hasNewUserPolicy != null)
                     if (hasNewUserPolicy != null)
@@ -414,32 +425,40 @@ namespace Emby.Server.Implementations.Library
             return providers;
             return providers;
         }
         }
 
 
-        private async Task<bool> AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser)
+        private async Task<Tuple<string, bool>> AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser)
         {
         {
             try
             try
             {
             {
                 var requiresResolvedUser = provider as IRequiresResolvedUser;
                 var requiresResolvedUser = provider as IRequiresResolvedUser;
+                ProviderAuthenticationResult authenticationResult = null;
                 if (requiresResolvedUser != null)
                 if (requiresResolvedUser != null)
                 {
                 {
-                    await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false);
+                    authenticationResult = await requiresResolvedUser.Authenticate(username, password, resolvedUser).ConfigureAwait(false);
                 }
                 }
                 else
                 else
                 {
                 {
-                    await provider.Authenticate(username, password).ConfigureAwait(false);
+                    authenticationResult = await provider.Authenticate(username, password).ConfigureAwait(false);
+                }
+
+                if(authenticationResult.Username != username)
+                {
+                    _logger.LogDebug("Authentication provider provided updated username {1}", authenticationResult.Username);
+                    username = authenticationResult.Username;
                 }
                 }
 
 
-                return true;
+                return new Tuple<string, bool>(username, true);
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
                 _logger.LogError(ex, "Error authenticating with provider {provider}", provider.Name);
                 _logger.LogError(ex, "Error authenticating with provider {provider}", provider.Name);
 
 
-                return false;
+                return new Tuple<string, bool>(username, false);
             }
             }
         }
         }
 
 
-        private async Task<Tuple<IAuthenticationProvider, bool>> AuthenticateLocalUser(string username, string password, string hashedPassword, User user, string remoteEndPoint)
+        private async Task<Tuple<IAuthenticationProvider, string, bool>> AuthenticateLocalUser(string username, string password, string hashedPassword, User user, string remoteEndPoint)
         {
         {
+            string updatedUsername = null;
             bool success = false;
             bool success = false;
             IAuthenticationProvider authenticationProvider = null;
             IAuthenticationProvider authenticationProvider = null;
 
 
@@ -458,11 +477,14 @@ namespace Emby.Server.Implementations.Library
             {
             {
                 foreach (var provider in GetAuthenticationProviders(user))
                 foreach (var provider in GetAuthenticationProviders(user))
                 {
                 {
-                    success = await AuthenticateWithProvider(provider, username, password, user).ConfigureAwait(false);
+                    var providerAuthResult = await AuthenticateWithProvider(provider, username, password, user).ConfigureAwait(false);
+                    updatedUsername = providerAuthResult.Item1;
+                    success = providerAuthResult.Item2;
 
 
                     if (success)
                     if (success)
                     {
                     {
                         authenticationProvider = provider;
                         authenticationProvider = provider;
+                        username = updatedUsername;
                         break;
                         break;
                     }
                     }
                 }
                 }
@@ -484,7 +506,7 @@ namespace Emby.Server.Implementations.Library
                 }
                 }
             }
             }
 
 
-            return new Tuple<IAuthenticationProvider, bool>(authenticationProvider, success);
+            return new Tuple<IAuthenticationProvider, string, bool>(authenticationProvider, username, success);
         }
         }
 
 
         private void UpdateInvalidLoginAttemptCount(User user, int newValue)
         private void UpdateInvalidLoginAttemptCount(User user, int newValue)