Browse Source

Use authorization code from api-migration to fix startup wizard

David 5 years ago
parent
commit
1c78482b48

+ 16 - 0
Emby.Server.Implementations/HttpServer/Security/AuthService.cs

@@ -51,6 +51,22 @@ namespace Emby.Server.Implementations.HttpServer.Security
             return user;
         }
 
+        public AuthorizationInfo Authenticate(HttpRequest request)
+        {
+            var auth = _authorizationContext.GetAuthorizationInfo(request);
+            if (auth?.User == null)
+            {
+                return null;
+            }
+
+            if (auth.User.HasPermission(PermissionKind.IsDisabled))
+            {
+                throw new SecurityException("User account has been disabled.");
+            }
+
+            return auth;
+        }
+
         private User ValidateUser(IRequest request, IAuthenticationAttributes authAttribtues)
         {
             // This code is executed before the service

+ 70 - 31
Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs

@@ -8,6 +8,7 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Security;
 using MediaBrowser.Model.Services;
+using Microsoft.AspNetCore.Http;
 using Microsoft.Net.Http.Headers;
 
 namespace Emby.Server.Implementations.HttpServer.Security
@@ -38,6 +39,14 @@ namespace Emby.Server.Implementations.HttpServer.Security
             return GetAuthorization(requestContext);
         }
 
+        public AuthorizationInfo GetAuthorizationInfo(HttpRequest requestContext)
+        {
+            var auth = GetAuthorizationDictionary(requestContext);
+            var (authInfo, _) =
+                GetAuthorizationInfoFromDictionary(auth, requestContext.Headers, requestContext.Query);
+            return authInfo;
+        }
+
         /// <summary>
         /// Gets the authorization.
         /// </summary>
@@ -46,7 +55,23 @@ namespace Emby.Server.Implementations.HttpServer.Security
         private AuthorizationInfo GetAuthorization(IRequest httpReq)
         {
             var auth = GetAuthorizationDictionary(httpReq);
+            var (authInfo, originalAuthInfo) =
+                GetAuthorizationInfoFromDictionary(auth, httpReq.Headers, httpReq.QueryString);
+
+            if (originalAuthInfo != null)
+            {
+                httpReq.Items["OriginalAuthenticationInfo"] = originalAuthInfo;
+            }
+
+            httpReq.Items["AuthorizationInfo"] = authInfo;
+            return authInfo;
+        }
 
+        private (AuthorizationInfo authInfo, AuthenticationInfo originalAuthenticationInfo) GetAuthorizationInfoFromDictionary(
+            in Dictionary<string, string> auth,
+            in IHeaderDictionary headers,
+            in IQueryCollection queryString)
+        {
             string deviceId = null;
             string device = null;
             string client = null;
@@ -64,20 +89,20 @@ namespace Emby.Server.Implementations.HttpServer.Security
 
             if (string.IsNullOrEmpty(token))
             {
-                token = httpReq.Headers["X-Emby-Token"];
+                token = headers["X-Emby-Token"];
             }
 
             if (string.IsNullOrEmpty(token))
             {
-                token = httpReq.Headers["X-MediaBrowser-Token"];
+                token = headers["X-MediaBrowser-Token"];
             }
 
             if (string.IsNullOrEmpty(token))
             {
-                token = httpReq.QueryString["api_key"];
+                token = queryString["api_key"];
             }
 
-            var info = new AuthorizationInfo
+            var authInfo = new AuthorizationInfo
             {
                 Client = client,
                 Device = device,
@@ -86,6 +111,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
                 Token = token
             };
 
+            AuthenticationInfo originalAuthenticationInfo = null;
             if (!string.IsNullOrWhiteSpace(token))
             {
                 var result = _authRepo.Get(new AuthenticationInfoQuery
@@ -93,81 +119,77 @@ namespace Emby.Server.Implementations.HttpServer.Security
                     AccessToken = token
                 });
 
-                var tokenInfo = result.Items.Count > 0 ? result.Items[0] : null;
+                originalAuthenticationInfo = result.Items.Count > 0 ? result.Items[0] : null;
 
-                if (tokenInfo != null)
+                if (originalAuthenticationInfo != null)
                 {
                     var updateToken = false;
 
                     // TODO: Remove these checks for IsNullOrWhiteSpace
-                    if (string.IsNullOrWhiteSpace(info.Client))
+                    if (string.IsNullOrWhiteSpace(authInfo.Client))
                     {
-                        info.Client = tokenInfo.AppName;
+                        authInfo.Client = originalAuthenticationInfo.AppName;
                     }
 
-                    if (string.IsNullOrWhiteSpace(info.DeviceId))
+                    if (string.IsNullOrWhiteSpace(authInfo.DeviceId))
                     {
-                        info.DeviceId = tokenInfo.DeviceId;
+                        authInfo.DeviceId = originalAuthenticationInfo.DeviceId;
                     }
 
                     // Temporary. TODO - allow clients to specify that the token has been shared with a casting device
-                    var allowTokenInfoUpdate = info.Client == null || info.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1;
+                    var allowTokenInfoUpdate = authInfo.Client == null || authInfo.Client.IndexOf("chromecast", StringComparison.OrdinalIgnoreCase) == -1;
 
-                    if (string.IsNullOrWhiteSpace(info.Device))
+                    if (string.IsNullOrWhiteSpace(authInfo.Device))
                     {
-                        info.Device = tokenInfo.DeviceName;
+                        authInfo.Device = originalAuthenticationInfo.DeviceName;
                     }
-                    else if (!string.Equals(info.Device, tokenInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
+                    else if (!string.Equals(authInfo.Device, originalAuthenticationInfo.DeviceName, StringComparison.OrdinalIgnoreCase))
                     {
                         if (allowTokenInfoUpdate)
                         {
                             updateToken = true;
-                            tokenInfo.DeviceName = info.Device;
+                            originalAuthenticationInfo.DeviceName = authInfo.Device;
                         }
                     }
 
-                    if (string.IsNullOrWhiteSpace(info.Version))
+                    if (string.IsNullOrWhiteSpace(authInfo.Version))
                     {
-                        info.Version = tokenInfo.AppVersion;
+                        authInfo.Version = originalAuthenticationInfo.AppVersion;
                     }
-                    else if (!string.Equals(info.Version, tokenInfo.AppVersion, StringComparison.OrdinalIgnoreCase))
+                    else if (!string.Equals(authInfo.Version, originalAuthenticationInfo.AppVersion, StringComparison.OrdinalIgnoreCase))
                     {
                         if (allowTokenInfoUpdate)
                         {
                             updateToken = true;
-                            tokenInfo.AppVersion = info.Version;
+                            originalAuthenticationInfo.AppVersion = authInfo.Version;
                         }
                     }
 
-                    if ((DateTime.UtcNow - tokenInfo.DateLastActivity).TotalMinutes > 3)
+                    if ((DateTime.UtcNow - originalAuthenticationInfo.DateLastActivity).TotalMinutes > 3)
                     {
-                        tokenInfo.DateLastActivity = DateTime.UtcNow;
+                        originalAuthenticationInfo.DateLastActivity = DateTime.UtcNow;
                         updateToken = true;
                     }
 
-                    if (!tokenInfo.UserId.Equals(Guid.Empty))
+                    if (!originalAuthenticationInfo.UserId.Equals(Guid.Empty))
                     {
-                        info.User = _userManager.GetUserById(tokenInfo.UserId);
+                        authInfo.User = _userManager.GetUserById(originalAuthenticationInfo.UserId);
 
-                        if (info.User != null && !string.Equals(info.User.Username, tokenInfo.UserName, StringComparison.OrdinalIgnoreCase))
+                        if (authInfo.User != null && !string.Equals(authInfo.User.Username, originalAuthenticationInfo.UserName, StringComparison.OrdinalIgnoreCase))
                         {
-                            tokenInfo.UserName = info.User.Username;
+                            originalAuthenticationInfo.UserName = authInfo.User.Username;
                             updateToken = true;
                         }
                     }
 
                     if (updateToken)
                     {
-                        _authRepo.Update(tokenInfo);
+                        _authRepo.Update(originalAuthenticationInfo);
                     }
                 }
-
-                httpReq.Items["OriginalAuthenticationInfo"] = tokenInfo;
             }
 
-            httpReq.Items["AuthorizationInfo"] = info;
-
-            return info;
+            return (authInfo, originalAuthenticationInfo);
         }
 
         /// <summary>
@@ -187,6 +209,23 @@ namespace Emby.Server.Implementations.HttpServer.Security
             return GetAuthorization(auth);
         }
 
+        /// <summary>
+        /// Gets the auth.
+        /// </summary>
+        /// <param name="httpReq">The HTTP req.</param>
+        /// <returns>Dictionary{System.StringSystem.String}.</returns>
+        private Dictionary<string, string> GetAuthorizationDictionary(HttpRequest httpReq)
+        {
+            var auth = httpReq.Headers["X-Emby-Authorization"];
+
+            if (string.IsNullOrEmpty(auth))
+            {
+                auth = httpReq.Headers[HeaderNames.Authorization];
+            }
+
+            return GetAuthorization(auth);
+        }
+
         /// <summary>
         /// Gets the authorization.
         /// </summary>

+ 4 - 7
Jellyfin.Api/Auth/CustomAuthenticationHandler.cs

@@ -39,21 +39,18 @@ namespace Jellyfin.Api.Auth
         /// <inheritdoc />
         protected override Task<AuthenticateResult> HandleAuthenticateAsync()
         {
-            var authenticatedAttribute = new AuthenticatedAttribute();
             try
             {
-                var user = _authService.Authenticate(Request, authenticatedAttribute);
-                if (user == null)
+                var authorizationInfo = _authService.Authenticate(Request);
+                if (authorizationInfo == null)
                 {
                     return Task.FromResult(AuthenticateResult.Fail("Invalid user"));
                 }
 
                 var claims = new[]
                 {
-                    new Claim(ClaimTypes.Name, user.Username),
-                    new Claim(
-                        ClaimTypes.Role,
-                        value: user.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User)
+                    new Claim(ClaimTypes.Name, authorizationInfo.User.Username),
+                    new Claim(ClaimTypes.Role, authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User)
                 };
                 var identity = new ClaimsIdentity(claims, Scheme.Name);
                 var principal = new ClaimsPrincipal(identity);

+ 7 - 0
MediaBrowser.Controller/Net/IAuthService.cs

@@ -11,5 +11,12 @@ namespace MediaBrowser.Controller.Net
         void Authenticate(IRequest request, IAuthenticationAttributes authAttribtues);
 
         User? Authenticate(HttpRequest request, IAuthenticationAttributes authAttribtues);
+
+        /// <summary>
+        /// Authenticate request.
+        /// </summary>
+        /// <param name="request">The request.</param>
+        /// <returns>Authorization information. Null if unauthenticated.</returns>
+        AuthorizationInfo Authenticate(HttpRequest request);
     }
 }

+ 11 - 0
MediaBrowser.Controller/Net/IAuthorizationContext.cs

@@ -1,7 +1,11 @@
 using MediaBrowser.Model.Services;
+using Microsoft.AspNetCore.Http;
 
 namespace MediaBrowser.Controller.Net
 {
+    /// <summary>
+    /// IAuthorization context.
+    /// </summary>
     public interface IAuthorizationContext
     {
         /// <summary>
@@ -17,5 +21,12 @@ namespace MediaBrowser.Controller.Net
         /// <param name="requestContext">The request context.</param>
         /// <returns>AuthorizationInfo.</returns>
         AuthorizationInfo GetAuthorizationInfo(IRequest requestContext);
+
+        /// <summary>
+        /// Gets the authorization information.
+        /// </summary>
+        /// <param name="requestContext">The request context.</param>
+        /// <returns>AuthorizationInfo.</returns>
+        AuthorizationInfo GetAuthorizationInfo(HttpRequest requestContext);
     }
 }