aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
diff options
context:
space:
mode:
author7illusions <z@7illusions.com>2014-08-30 19:06:58 +0200
committer7illusions <z@7illusions.com>2014-08-30 19:06:58 +0200
commit66ad1699e22029b605e17735e8d9450285d8748a (patch)
treeffc92c88d24850b2f82b6b3a8bdd904a2ccc77a5 /MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
parent34bc54263e886aae777a3537dc50a6535b51330a (diff)
parent9d36f518182bc075c19d78084870f5115fa62d1e (diff)
Merge pull request #1 from MediaBrowser/master
Update to latest
Diffstat (limited to 'MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs')
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs164
1 files changed, 164 insertions, 0 deletions
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
new file mode 100644
index 000000000..19870c435
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -0,0 +1,164 @@
+using System.Collections.Generic;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Session;
+using ServiceStack;
+using ServiceStack.Auth;
+using ServiceStack.Web;
+using System;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.Security
+{
+ public class AuthService : IAuthService
+ {
+ private readonly IServerConfigurationManager _config;
+
+ public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config)
+ {
+ AuthorizationContext = authorizationContext;
+ _config = config;
+ SessionManager = sessionManager;
+ UserManager = userManager;
+ }
+
+ public IUserManager UserManager { get; private set; }
+ public ISessionManager SessionManager { get; private set; }
+ public IAuthorizationContext AuthorizationContext { get; private set; }
+
+ /// <summary>
+ /// Restrict authentication to a specific <see cref="IAuthProvider"/>.
+ /// For example, if this attribute should only permit access
+ /// if the user is authenticated with <see cref="BasicAuthProvider"/>,
+ /// you should set this property to <see cref="BasicAuthProvider.Name"/>.
+ /// </summary>
+ public string Provider { get; set; }
+
+ /// <summary>
+ /// Redirect the client to a specific URL if authentication failed.
+ /// If this property is null, simply `401 Unauthorized` is returned.
+ /// </summary>
+ public string HtmlRedirect { get; set; }
+
+ public void Authenticate(IRequest req, IResponse res, object requestDto)
+ {
+ if (HostContext.HasValidAuthSecret(req))
+ return;
+
+ //ExecuteBasic(req, res, requestDto); //first check if session is authenticated
+ //if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed)
+
+ ValidateUser(req);
+ }
+
+ // TODO: Remove this when all clients have supported the new sescurity
+ private readonly List<string> _updatedClients = new List<string>(){"Dashboard"};
+
+ private void ValidateUser(IRequest req)
+ {
+ //This code is executed before the service
+ var auth = AuthorizationContext.GetAuthorizationInfo(req);
+
+ if (!string.IsNullOrWhiteSpace(auth.Token)
+ || _config.Configuration.EnableTokenAuthentication
+ || _updatedClients.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ SessionManager.ValidateSecurityToken(auth.Token);
+ }
+
+ var user = string.IsNullOrWhiteSpace(auth.UserId)
+ ? null
+ : UserManager.GetUserById(new Guid(auth.UserId));
+
+ if (user == null & !string.IsNullOrWhiteSpace(auth.UserId))
+ {
+ // TODO: Re-enable
+ //throw new ArgumentException("User with Id " + auth.UserId + " not found");
+ }
+
+ if (user != null && user.Configuration.IsDisabled)
+ {
+ throw new AuthenticationException("User account has been disabled.");
+ }
+
+ if (!string.IsNullOrWhiteSpace(auth.DeviceId) &&
+ !string.IsNullOrWhiteSpace(auth.Client) &&
+ !string.IsNullOrWhiteSpace(auth.Device))
+ {
+ SessionManager.LogSessionActivity(auth.Client,
+ auth.Version,
+ auth.DeviceId,
+ auth.Device,
+ req.RemoteIp,
+ user);
+ }
+ }
+
+ private void ExecuteBasic(IRequest req, IResponse res, object requestDto)
+ {
+ if (AuthenticateService.AuthProviders == null)
+ throw new InvalidOperationException(
+ "The AuthService must be initialized by calling AuthService.Init to use an authenticate attribute");
+
+ var matchingOAuthConfigs = AuthenticateService.AuthProviders.Where(x =>
+ this.Provider.IsNullOrEmpty()
+ || x.Provider == this.Provider).ToList();
+
+ if (matchingOAuthConfigs.Count == 0)
+ {
+ res.WriteError(req, requestDto, "No OAuth Configs found matching {0} provider"
+ .Fmt(this.Provider ?? "any"));
+ res.EndRequest();
+ }
+
+ matchingOAuthConfigs.OfType<IAuthWithRequest>()
+ .Each(x => x.PreAuthenticate(req, res));
+
+ var session = req.GetSession();
+ if (session == null || !matchingOAuthConfigs.Any(x => session.IsAuthorized(x.Provider)))
+ {
+ if (this.DoHtmlRedirectIfConfigured(req, res, true)) return;
+
+ AuthProvider.HandleFailedAuth(matchingOAuthConfigs[0], session, req, res);
+ }
+ }
+
+ protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false)
+ {
+ var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect;
+ if (htmlRedirect != null && req.ResponseContentType.MatchesContentType(MimeTypes.Html))
+ {
+ DoHtmlRedirect(htmlRedirect, req, res, includeRedirectParam);
+ return true;
+ }
+ return false;
+ }
+
+ public static void DoHtmlRedirect(string redirectUrl, IRequest req, IResponse res, bool includeRedirectParam)
+ {
+ var url = req.ResolveAbsoluteUrl(redirectUrl);
+ if (includeRedirectParam)
+ {
+ var absoluteRequestPath = req.ResolveAbsoluteUrl("~" + req.PathInfo + ToQueryString(req.QueryString));
+ url = url.AddQueryParam(HostContext.ResolveLocalizedString(LocalizedStrings.Redirect), absoluteRequestPath);
+ }
+
+ res.RedirectToUrl(url);
+ }
+
+ private static string ToQueryString(INameValueCollection queryStringCollection)
+ {
+ return ToQueryString((NameValueCollection)queryStringCollection.Original);
+ }
+
+ private static string ToQueryString(NameValueCollection queryStringCollection)
+ {
+ if (queryStringCollection == null || queryStringCollection.Count == 0)
+ return String.Empty;
+
+ return "?" + queryStringCollection.ToFormUrlEncoded();
+ }
+ }
+}