aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Session/SessionManager.cs
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-07-07 21:41:03 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-07-07 21:41:03 -0400
commitc02e917f5657db4bd76fc6ca17c535fc441c641c (patch)
treeb09ae21bd9c5f15cc9594eba27f5c982919c1872 /MediaBrowser.Server.Implementations/Session/SessionManager.cs
parent379fa002288032097ff3222c7484136f10ab69d2 (diff)
completed auth database
Diffstat (limited to 'MediaBrowser.Server.Implementations/Session/SessionManager.cs')
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs159
1 files changed, 147 insertions, 12 deletions
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 784719318..c3d24c0de 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1,6 +1,4 @@
-using System.Security.Cryptography;
-using System.Text;
-using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -13,12 +11,14 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
+using MediaBrowser.Model.Users;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -27,7 +27,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Users;
namespace MediaBrowser.Server.Implementations.Session
{
@@ -62,6 +61,8 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationHost _appHost;
+ private readonly IAuthenticationRepository _authRepo;
+
/// <summary>
/// Gets or sets the configuration manager.
/// </summary>
@@ -104,7 +105,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="logger">The logger.</param>
/// <param name="userRepository">The user repository.</param>
/// <param name="libraryManager">The library manager.</param>
- public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient)
+ public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@@ -119,6 +120,7 @@ namespace MediaBrowser.Server.Implementations.Session
_jsonSerializer = jsonSerializer;
_appHost = appHost;
_httpClient = httpClient;
+ _authRepo = authRepo;
}
/// <summary>
@@ -204,7 +206,12 @@ namespace MediaBrowser.Server.Implementations.Session
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">user</exception>
/// <exception cref="System.UnauthorizedAccessException"></exception>
- public async Task<SessionInfo> LogSessionActivity(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user)
+ public async Task<SessionInfo> LogSessionActivity(string clientType,
+ string appVersion,
+ string deviceId,
+ string deviceName,
+ string remoteEndPoint,
+ User user)
{
if (string.IsNullOrEmpty(clientType))
{
@@ -1157,7 +1164,37 @@ namespace MediaBrowser.Server.Implementations.Session
public void ValidateSecurityToken(string token)
{
+ if (string.IsNullOrWhiteSpace(token))
+ {
+ throw new UnauthorizedAccessException();
+ }
+ var result = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ AccessToken = token
+ });
+
+ var info = result.Items.FirstOrDefault();
+
+ if (info == null)
+ {
+ throw new UnauthorizedAccessException();
+ }
+
+ if (!info.IsActive)
+ {
+ throw new UnauthorizedAccessException("Access token has expired.");
+ }
+
+ if (!string.IsNullOrWhiteSpace(info.UserId))
+ {
+ var user = _userManager.GetUserById(new Guid(info.UserId));
+
+ if (user == null || user.Configuration.IsDisabled)
+ {
+ throw new UnauthorizedAccessException("User account has been disabled.");
+ }
+ }
}
/// <summary>
@@ -1175,7 +1212,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <exception cref="UnauthorizedAccessException"></exception>
public async Task<AuthenticationResult> AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint)
{
- var result = await _userManager.AuthenticateUser(username, password).ConfigureAwait(false);
+ var result = IsLocalhost(remoteEndPoint) || await _userManager.AuthenticateUser(username, password).ConfigureAwait(false);
if (!result)
{
@@ -1185,6 +1222,8 @@ namespace MediaBrowser.Server.Implementations.Session
var user = _userManager.Users
.First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
+ var token = await GetAuthorizationToken(user.Id.ToString("N"), deviceId, clientType, deviceName).ConfigureAwait(false);
+
var session = await LogSessionActivity(clientType,
appVersion,
deviceId,
@@ -1197,11 +1236,108 @@ namespace MediaBrowser.Server.Implementations.Session
{
User = _dtoService.GetUserDto(user),
SessionInfo = GetSessionInfoDto(session),
- AuthenticationToken = Guid.NewGuid().ToString("N")
+ AccessToken = token
};
}
- private bool IsLocal(string remoteEndpoint)
+ private async Task<string> GetAuthorizationToken(string userId, string deviceId, string app, string deviceName)
+ {
+ var existing = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ DeviceId = deviceId,
+ IsActive = true,
+ UserId = userId,
+ Limit = 1
+ });
+
+ if (existing.Items.Length > 0)
+ {
+ _logger.Debug("Reissuing access token");
+ return existing.Items[0].AccessToken;
+ }
+
+ var newToken = new AuthenticationInfo
+ {
+ AppName = app,
+ DateCreated = DateTime.UtcNow,
+ DeviceId = deviceId,
+ DeviceName = deviceName,
+ UserId = userId,
+ IsActive = true,
+ AccessToken = Guid.NewGuid().ToString("N")
+ };
+
+ _logger.Debug("Creating new access token for user {0}", userId);
+ await _authRepo.Create(newToken, CancellationToken.None).ConfigureAwait(false);
+
+ return newToken.AccessToken;
+ }
+
+ public async Task Logout(string accessToken)
+ {
+ if (string.IsNullOrWhiteSpace(accessToken))
+ {
+ throw new ArgumentNullException("accessToken");
+ }
+
+ var existing = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ Limit = 1,
+ AccessToken = accessToken
+
+ }).Items.FirstOrDefault();
+
+ if (existing != null)
+ {
+ existing.IsActive = false;
+
+ await _authRepo.Update(existing, CancellationToken.None).ConfigureAwait(false);
+
+ var sessions = Sessions
+ .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+
+ foreach (var session in sessions)
+ {
+ try
+ {
+ ReportSessionEnded(session.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reporting session ended", ex);
+ }
+ }
+ }
+ }
+
+ public async Task RevokeUserTokens(string userId)
+ {
+ var existing = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ IsActive = true,
+ UserId = userId
+ });
+
+ foreach (var info in existing.Items)
+ {
+ await Logout(info.AccessToken).ConfigureAwait(false);
+ }
+ }
+
+ private bool IsLocalhost(string remoteEndpoint)
+ {
+ if (string.IsNullOrWhiteSpace(remoteEndpoint))
+ {
+ throw new ArgumentNullException("remoteEndpoint");
+ }
+
+ return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 ||
+ remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
+ remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase);
+ }
+
+ public bool IsLocal(string remoteEndpoint)
{
if (string.IsNullOrWhiteSpace(remoteEndpoint))
{
@@ -1211,12 +1347,11 @@ namespace MediaBrowser.Server.Implementations.Session
// Private address space:
// http://en.wikipedia.org/wiki/Private_network
- return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 ||
+ return IsLocalhost(remoteEndpoint) ||
remoteEndpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) ||
- remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
- remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase);
+ remoteEndpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase);
}
/// <summary>