Allows external logins to be listed on login page, updates BackOfficeController with actions for invoking them.
This commit is contained in:
@@ -323,12 +323,12 @@ namespace Umbraco.Core.Security
|
||||
|
||||
private static FormsAuthenticationTicket GetAuthTicket(this HttpContextBase http, string cookieName)
|
||||
{
|
||||
var allKeys = new List<string>();
|
||||
var asDictionary = new Dictionary<string, string>();
|
||||
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
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<Reference Include="Microsoft.Owin">
|
||||
<HintPath>..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
<Reference Include="Microsoft.Owin.Security, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security.Cookies">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll</HintPath>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.Cookies" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<form method="POST" name="loginForm" ng-submit="loginSubmit(login, password)" ng-controller="Umbraco.Dialogs.LoginController">
|
||||
<div ng-controller="Umbraco.Dialogs.LoginController">
|
||||
<div id="login" class="umb-modalcolumn" ng-class="{'show-validation': loginForm.$invalid}">
|
||||
|
||||
<div class="form">
|
||||
@@ -8,19 +8,37 @@
|
||||
<localize key="login_instruction">Log in below</localize>
|
||||
</p>
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.username.$invalid}">
|
||||
<input type="text" autofocus ng-model="login" name="username" class="input-xlarge" localize="placeholder" placeholder="@placeholders_username" />
|
||||
</div>
|
||||
<form method="POST" name="loginForm" ng-submit="loginSubmit(login, password)">
|
||||
<div class="control-group" ng-class="{error: loginForm.username.$invalid}">
|
||||
<input type="text" autofocus ng-model="login" name="username" class="input-xlarge" localize="placeholder" placeholder="@placeholders_username" />
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
|
||||
<input type="password" ng-model="password" name="password" class="input-xlarge" localize="placeholder" placeholder="@placeholders_password" />
|
||||
</div>
|
||||
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
|
||||
<input type="password" ng-model="password" name="password" class="input-xlarge" localize="placeholder" placeholder="@placeholders_password" />
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn" val-trigger-change="#login .form input"><localize key="general_login">Login</localize></button>
|
||||
<button type="submit" class="btn" val-trigger-change="#login .form input"><localize key="general_login">Login</localize></button>
|
||||
|
||||
<div class="control-group" ng-show="loginForm.$invalid">
|
||||
<div class="alert alert-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<br/><br/>
|
||||
|
||||
<form method="POST" name="externalLoginForm" action="{{externalLoginFormAction}}">
|
||||
|
||||
<div class="alert alert-success" ng-repeat="login in externalLogins">
|
||||
|
||||
<button type="submit" class="btn btn-default" id="{{login.authType}}" name="provider" value="{{login.authType}}"
|
||||
title="Log in using your {{login.caption}} account">
|
||||
{{login.authType}}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<div class="control-group" ng-show="loginForm.$invalid">
|
||||
<div class="alert alert-error">{{errorMsg}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -162,15 +162,20 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Host.SystemWeb">
|
||||
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.3.0.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security.Cookies">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security.Google">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.Google.3.0.0\lib\net45\Microsoft.Owin.Security.Google.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security.OAuth">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.OAuth.2.1.0\lib\net45\Microsoft.Owin.Security.OAuth.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -202,6 +207,7 @@
|
||||
</Reference>
|
||||
<Reference Include="Owin">
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.Cookies" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.Google" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
|
||||
@@ -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 @@
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
|
||||
<title ng-bind="$root.locationTitle">Umbraco</title>
|
||||
|
||||
|
||||
@{ 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)))
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body ng-class="{touch:touchDevice,emptySection:emptySection}" ng-controller="Umbraco.MainController" id="umbracoMainPageBody">
|
||||
<div ng-hide="!authenticated" ng-cloak id="mainwrapper" id="mainwrapper" class="clearfix" ng-click="closeDialogs($event)">
|
||||
<div ng-hide="!authenticated" ng-cloak id="mainwrapper" id="mainwrapper" class="clearfix" ng-click="closeDialogs($event)">
|
||||
|
||||
<umb-navigation></umb-navigation>
|
||||
|
||||
@@ -47,18 +50,28 @@
|
||||
<umb-notifications></umb-notifications>
|
||||
|
||||
|
||||
@{
|
||||
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.
|
||||
*@
|
||||
*@
|
||||
<script type="text/javascript">
|
||||
var Umbraco = {};
|
||||
Umbraco.Sys = {};
|
||||
Umbraco.Sys.ServerVariables = {
|
||||
"umbracoUrls": {
|
||||
"umbracoUrls": {
|
||||
"authenticationApiBaseUrl": "@(Url.GetUmbracoApiServiceBaseUrl<AuthenticationController>(controller => controller.PostLogin(null)))",
|
||||
"serverVarsJs": '@Url.GetUrlWithCacheBust("ServerVariables", "BackOffice")'
|
||||
"serverVarsJs": "@Url.GetUrlWithCacheBust("ServerVariables", "BackOffice")",
|
||||
"externalLoginsUrl": "@(Url.Action("ExternalLogin", "BackOffice", new { area = ViewBag.UmbracoPath }))"
|
||||
},
|
||||
"externalLogins": @Html.Raw(JsonConvert.SerializeObject(loginProviders)),
|
||||
"application": {
|
||||
"applicationPath" : "@Context.Request.ApplicationPath"
|
||||
}
|
||||
@@ -68,7 +81,7 @@
|
||||
@*And finally we can load in our angular app*@
|
||||
<script type="text/javascript" src="lib/rgrove-lazyload/lazyload.js"></script>
|
||||
<script type="text/javascript" src="@Url.GetUrlWithCacheBust("Application", "BackOffice")"></script>
|
||||
|
||||
|
||||
@{
|
||||
var isDebug = false;
|
||||
if (Request.RawUrl.IndexOf('?') >= 0)
|
||||
@@ -78,9 +91,9 @@
|
||||
if (attempt && attempt.Result)
|
||||
{
|
||||
isDebug = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@if (isDebug)
|
||||
{
|
||||
|
||||
@@ -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(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Render the default view
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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<ActionResult> 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");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the server variables regarding the application state
|
||||
/// </summary>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,8 +142,12 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.Owin.3.0.0\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
<Reference Include="Microsoft.Owin.Host.SystemWeb">
|
||||
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.3.0.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.3.0.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security.Cookies">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll</HintPath>
|
||||
@@ -167,7 +171,8 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin">
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System">
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
|
||||
<package id="Microsoft.Net.Http" version="2.2.28" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security" version="3.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.Cookies" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="2.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
|
||||
|
||||
Reference in New Issue
Block a user