diff --git a/src/Umbraco.Core/Security/AuthenticationExtensions.cs b/src/Umbraco.Core/Security/AuthenticationExtensions.cs index 008f24f492..dd688cfe25 100644 --- a/src/Umbraco.Core/Security/AuthenticationExtensions.cs +++ b/src/Umbraco.Core/Security/AuthenticationExtensions.cs @@ -323,12 +323,12 @@ namespace Umbraco.Core.Security private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName) { - var allKeys = new List(); + var asDictionary = new Dictionary(); for (var i = 0; i < http.Request.Cookies.Keys.Count; i++) { - allKeys.Add(http.Request.Cookies.Keys.Get(i)); + var key = http.Request.Cookies.Keys.Get(i); + asDictionary[key] = http.Request.Cookies[key].Value; } - var asDictionary = allKeys.ToDictionary(key => key, key => http.Request.Cookies[key].Value); //get the ticket try diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index c5da56af3d..f0f09c499c 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -63,8 +63,9 @@ ..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll - - ..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll + + False + ..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll ..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll diff --git a/src/Umbraco.Core/packages.config b/src/Umbraco.Core/packages.config index 559eae83c4..93c9737158 100644 --- a/src/Umbraco.Core/packages.config +++ b/src/Umbraco.Core/packages.config @@ -13,7 +13,7 @@ - + diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js index c9e7adabe2..00d3cda1ab 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js @@ -16,7 +16,11 @@ }); // weekday[d.getDay()]; $scope.errorMsg = ""; - + + $scope.externalLoginFormAction = Umbraco.Sys.ServerVariables.umbracoUrls.externalLoginsUrl; + + $scope.externalLogins = Umbraco.Sys.ServerVariables.externalLogins; + $scope.loginSubmit = function (login, password) { //if the login and password are not empty we need to automatically diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html index 865dd8303f..5b73743772 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html @@ -1,4 +1,4 @@ -
+
@@ -8,19 +8,37 @@ Log in below

-
- -
+ +
+ +
-
- -
+
+ +
- + + +
+
{{errorMsg}}
+
+ + +

+ +
+ +
+ + + +
+
+ -
-
{{errorMsg}}
-
- \ No newline at end of file +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index fb07ae1ff4..0cec068f48 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -162,15 +162,20 @@ False ..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll
- + + False ..\packages\Microsoft.Owin.Host.SystemWeb.3.0.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll - ..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll + ..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll + True ..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll + + ..\packages\Microsoft.Owin.Security.Google.3.0.0\lib\net45\Microsoft.Owin.Security.Google.dll + ..\packages\Microsoft.Owin.Security.OAuth.2.1.0\lib\net45\Microsoft.Owin.Security.OAuth.dll @@ -202,6 +207,7 @@ ..\packages\Owin.1.0\lib\net40\Owin.dll + True System diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 150759f582..5ed2c4b1d0 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -25,8 +25,9 @@ - + + diff --git a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml index 308f483af2..8369b5b677 100644 --- a/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml +++ b/src/Umbraco.Web.UI/umbraco/Views/Default.cshtml @@ -3,6 +3,9 @@ @using Umbraco.Core @using ClientDependency.Core @using ClientDependency.Core.Mvc +@using Microsoft.Owin.Security +@using Newtonsoft.Json +@using Newtonsoft.Json.Linq @using Umbraco.Core.IO @using Umbraco.Web @using Umbraco.Web.Editors @@ -23,17 +26,17 @@ Umbraco - + @{ Html.RequiresCss("assets/css/umbraco.css", "Umbraco");} @{ Html.RequiresCss("tree/treeicons.css", "UmbracoClient");} @Html.RenderCssHere( new BasicPath("Umbraco", IOHelper.ResolveUrl(SystemDirectories.Umbraco)), new BasicPath("UmbracoClient", IOHelper.ResolveUrl(SystemDirectories.UmbracoClient))) - + -
+
@@ -47,18 +50,28 @@ + @{ + var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes() + .Select(p => new {authType = p.AuthenticationType, caption = p.Caption, + //TODO: Need to see if this exposes any sensitive data! + properties = p.Properties}) + .ToArray(); + } + @* These are the bare minimal server variables that are required for the application to start without being authenticated, we will load the rest of the server vars after the user is authenticated. - *@ + *@ - + @{ var isDebug = false; if (Request.RawUrl.IndexOf('?') >= 0) @@ -78,9 +91,9 @@ if (attempt && attempt.Result) { isDebug = true; - } + } } - + } @if (isDebug) { diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 46028bff35..e844d8f5fb 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -5,9 +5,13 @@ using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; +using System.Threading.Tasks; using System.Web.Mvc; using System.Web.UI; using dotless.Core.Parser.Tree; +using Microsoft.AspNet.Identity; +using Microsoft.Owin; +using Microsoft.Owin.Security; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.Configuration; @@ -27,6 +31,9 @@ using Umbraco.Web.PropertyEditors; using Umbraco.Web.Models; using Umbraco.Web.WebServices; using Umbraco.Web.WebApi.Filters; +using System.Web; +using AutoMapper; +using Umbraco.Core.Security; namespace Umbraco.Web.Editors { @@ -37,12 +44,18 @@ namespace Umbraco.Web.Editors [DisableClientCache] public class BackOfficeController : UmbracoController { + protected IOwinContext OwinContext + { + get { return Request.GetOwinContext(); } + } + /// /// Render the default view /// /// public ActionResult Default() { + ViewBag.UmbracoPath = GlobalSettings.UmbracoMvcArea; return View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml"); } @@ -359,6 +372,62 @@ namespace Umbraco.Web.Editors return JavaScript(ServerVariablesParser.Parse(result)); } + [HttpPost] + [AllowAnonymous] + public ActionResult ExternalLogin(string provider, string returnUrl = null) + { + if (returnUrl.IsNullOrWhiteSpace()) + { + returnUrl = GlobalSettings.Path; + } + + // Request a redirect to the external login provider + return new ChallengeResult(provider, + Url.Action("ExternalLoginCallback", "BackOffice", new + { + area = GlobalSettings.UmbracoMvcArea, + ReturnUrl = returnUrl + })); + } + + [HttpGet] + [AllowAnonymous] + public async Task ExternalLoginCallback(string returnUrl) + { + var loginInfo = await OwinContext.Authentication.GetExternalLoginInfoAsync(); + if (loginInfo == null) + { + //go home, invalid callback + return RedirectToLocal(returnUrl); + } + + //// Sign in the user with this external login provider if the user already has a login + //var user = await UserManager<>.FindAsync(loginInfo.Login); + //if (user != null) + //{ + // await SignInAsync(user, isPersistent: false); + // return RedirectToLocal(returnUrl); + //} + //else + //{ + // // If the user does not have an account, then prompt the user to create an account + // ViewBag.ReturnUrl = returnUrl; + // ViewBag.LoginProvider = loginInfo.Login.LoginProvider; + + // return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email }); + //} + + //TODO: until we make a user thingy and make this correctly , we'll just see if this works + + var user = Security.GetBackOfficeUser(loginInfo.DefaultUserName); + + var ticket = UmbracoContext.Security.PerformLogin(user); + HttpContext.AuthenticateCurrentRequest(ticket, false); + + return View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml"); + } + + /// /// Returns the server variables regarding the application state /// @@ -505,5 +574,43 @@ namespace Umbraco.Web.Editors JsUrl } + private ActionResult RedirectToLocal(string returnUrl) + { + if (Url.IsLocalUrl(returnUrl)) + { + return Redirect(returnUrl); + } + return Redirect("/"); + } + + // Used for XSRF protection when adding external logins + private const string XsrfKey = "XsrfId"; + + private class ChallengeResult : HttpUnauthorizedResult + { + public ChallengeResult(string provider, string redirectUri, string userId = null) + { + LoginProvider = provider; + RedirectUri = redirectUri; + UserId = userId; + } + + private string LoginProvider { get; set; } + private string RedirectUri { get; set; } + private string UserId { get; set; } + + public override void ExecuteResult(ControllerContext context) + { + //Ensure the forms auth module doesn't do a redirect! + context.HttpContext.Response.SuppressFormsAuthenticationRedirect = true; + + var properties = new AuthenticationProperties() { RedirectUri = RedirectUri }; + if (UserId != null) + { + properties.Dictionary[XsrfKey] = UserId; + } + context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider); + } + } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 5be8656b13..8520557feb 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -142,8 +142,12 @@ False ..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll - - ..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll + + ..\packages\Microsoft.Owin.Host.SystemWeb.3.0.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll + + + False + ..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll ..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll @@ -167,7 +171,8 @@ False ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll - + + False ..\packages\Owin.1.0\lib\net40\Owin.dll diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config index 8506c1de5b..877034b4e5 100644 --- a/src/Umbraco.Web/packages.config +++ b/src/Umbraco.Web/packages.config @@ -20,7 +20,8 @@ - + +