diff --git a/src/Umbraco.Web.UI.Client/src/less/login.less b/src/Umbraco.Web.UI.Client/src/less/login.less index d46bb41317..d01dec8733 100644 --- a/src/Umbraco.Web.UI.Client/src/less/login.less +++ b/src/Umbraco.Web.UI.Client/src/less/login.less @@ -2,46 +2,72 @@ // ------------------------- .login-overlay { - width: 100%; - height: 100%; - background: @blackLight url(../img/application/logo.png) no-repeat 25px 30px fixed !important; - background-size: 30px 30px !important; - color: @white; - position: absolute; - z-index: 2000; - top: 0px; - left: 0px; - margin: 0 !Important; - padding: 0; - border-radius: 0 + width: 100%; + height: 100%; + background: @blackLight url(../img/application/logo.png) no-repeat 25px 30px fixed !important; + background-size: 30px 30px !important; + color: @white; + position: absolute; + z-index: 2000; + top: 0px; + left: 0px; + margin: 0 !Important; + padding: 0; + border-radius: 0; } -.login-overlay .umb-modalcolumn{ - background: none; - border: none; +.login-overlay .umb-modalcolumn { + background: none; + border: none; } .login-overlay .form { - display: block; - padding-top: 100px; - padding-left: 165px; - width: 370px; - text-align: right + display: block; + padding-top: 100px; + padding-left: 165px; + width: 370px; + text-align: right; } .login-overlay h1 { - display: block; - text-align: right; - color: @white; - font-size: 18px; - font-weight: normal + display: block; + text-align: right; + color: @white; + font-size: 18px; + font-weight: normal; } -.login-overlay .alert.alert-error{ +.login-overlay .alert.alert-error { display: inline-block; - width: 270px; padding-right: 6px; padding-left: 6px; margin-top: 10px; text-align: center; -} \ No newline at end of file +} + +#hrOr { + height: 30px; + text-align: center; + position: relative; + padding-top: 20px; +} + +#hrOr hr { + margin: 0px; + border: none; + background-color: @gray; + height: 1px; +} + +#hrOr div { + background-color: black; + position: relative; + top: -16px; + border: 1px solid @gray; + padding: 4px; + border-radius: 50%; + width: 20px; + height: 20px; + margin: auto; + color: @grayLight; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index 62a5d21ac7..c661fe1223 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -282,9 +282,9 @@ .umb-panel a.text-success:hover, .umb-panel a.text-success:focus { color: darken(@formSuccessText, 10%); } -.umb-user-panel .external-logins form { +.external-logins form { margin:0; } -.umb-user-panel .external-logins button { +.external-logins button { margin:5px; } 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 dd7971b678..25a8b28976 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 @@ -7,6 +7,33 @@ Log in below. Log in below

+ +
+ +
+ {{error}} +
+ +
+ +
+ + + +
+
+ +
+
Or
+
+ +
@@ -24,27 +51,6 @@
-
- -

External login providers

- -
- {{error}} -
- -
- -
- - - -
-
+ \ No newline at end of file diff --git a/src/Umbraco.Web.UI/App_Code/OwinStartup.cs b/src/Umbraco.Web.UI/App_Code/OwinStartup.cs index 930aed24b0..431cc35786 100644 --- a/src/Umbraco.Web.UI/App_Code/OwinStartup.cs +++ b/src/Umbraco.Web.UI/App_Code/OwinStartup.cs @@ -1,12 +1,4 @@ -using System; -using System.Globalization; -using System.Net.Http; -using System.Threading.Tasks; -using System.Web; -using Microsoft.IdentityModel.Clients.ActiveDirectory; -using Microsoft.Owin; -using Microsoft.Owin.Security.Google; -using Microsoft.Owin.Security.OpenIdConnect; +using Microsoft.Owin; using Owin; using Umbraco.Core; using Umbraco.Core.Security; @@ -19,193 +11,47 @@ namespace Umbraco.Web.UI { /// - /// Summary description for Startup + /// Default OWIN startup class /// public class OwinStartup { - public async Task DoStuff() - { - var client = new HttpClient(); - - using (var request = await client.PostAsJsonAsync("", "123")) - { - - } - } - public void Configuration(IAppBuilder app) { - - - - - - //Single method to configure the Identity user manager for use with Umbraco + //Single method to configure the Identity user manager for use with Umbraco Back office app.ConfigureUserManagerForUmbracoBackOffice( ApplicationContext.Current, Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider().AsUmbracoMembershipProvider()); - //// Enable the application to use a cookie to store information for the - //// signed in user and to use a cookie to temporarily store information - //// about a user logging in with a third party login provider - //// Configure the sign in cookie - //app.UseCookieAuthentication(new CookieAuthenticationOptions - //{ - // AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, - - // Provider = new CookieAuthenticationProvider - // { - // // Enables the application to validate the security stamp when the user - // // logs in. This is a security feature which is used when you - // // change a password or add an external login to your account. - // OnValidateIdentity = SecurityStampValidator - // .OnValidateIdentity, UmbracoApplicationUser, int>( - // TimeSpan.FromMinutes(30), - // (manager, user) => user.GenerateUserIdentityAsync(manager), - // identity => identity.GetUserId()) - // } - //}); - - //Ensure owin is configured for Umbraco back office authentication - this must - // be configured AFTER the standard UseCookieConfiguration above. + //Ensure owin is configured for Umbraco back office authentication. If you have any front-end OWIN + // cookie configuration, this must be declared after it. app .UseUmbracoBackOfficeCookieAuthentication() .UseUmbracoBackOfficeExternalCookieAuthentication(); - //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); - - //app.UseGoogleAuthentication( - // clientId: "1072120697051-07jlhgrd5hodsfe7dgqimdie8qc1omet.apps.googleusercontent.com", - // clientSecret: "Ue9swN0lEX9rwxzQz1Y_tFzg"); + /* + * Configure external logins: + * + * Depending on the authentication sources you would like to enable, you will need to install + * certain Nuget packages. + * + * For Google auth: Install-Package Microsoft.Owin.Security.Google + * For Facebook auth: Install-Package Microsoft.Owin.Security.Facebook + * For Microsoft auth: Install-Package Microsoft.Owin.Security.MicrosoftAccount + * + * There are many more providers such as Twitter, Yahoo, ActiveDirectory, etc... most information can + * be found here: http://www.asp.net/web-api/overview/security/external-authentication-services + * + * The source for these methods is located in ~/App_Code/IdentityAuthExtensions.cs, you will need to un-comment + * the methods that you would like to use. Each method contains documentation and links to + * documentation for reference. You can also tweak the code in those extension + * methods to suit your needs. + */ - var googleOptions = new GoogleOAuth2AuthenticationOptions - { - - }; - googleOptions.Description.Properties["SocialStyle"] = "btn-google-plus"; - googleOptions.Description.Properties["SocialIcon"] = "fa-google-plus"; - googleOptions.Caption = "Google"; - app.UseGoogleAuthentication(googleOptions); - - //AD docs are here: - // https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet - - var authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant); - var adOptions = new OpenIdConnectAuthenticationOptions - { - //NOTE: This by default is 'OpenIdConnect' but that doesn't match what identity actually stores in the - // loginProvider field in the database which is something like: https://sts.windows.net/1234.... - // which is something based on your AD setup. This value needs to match in order for accounts to detected as linked/un-linked - // in the back office. - AuthenticationType = "https://sts.windows.net/3bb0b4c5-364f-4394-ad36-0f29f95e5ddd/", - - ClientId = clientId, - Authority = authority, - PostLogoutRedirectUri = postLoginRedirectUri, - Notifications = new OpenIdConnectAuthenticationNotifications() - { - // - // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away. - // - AuthorizationCodeReceived = (context) => - { - var code = context.Code; - - var credential = new ClientCredential(clientId, appKey); - var userObjectId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; - var authContext = new AuthenticationContext(authority, new NaiveSessionCache(userObjectId)); - AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode( - code, - //NOTE: This URL needs to match EXACTLY the same path that is configured in the AD - // configuration. - new Uri( - HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) + - HttpContext.Current.Request.RawUrl.EnsureStartsWith('/').EnsureEndsWith('/')), - credential, - graphResourceId); - - return Task.FromResult(0); - } - - } - - }; - adOptions.Description.Properties["SocialStyle"] = "btn-microsoft"; - adOptions.Description.Properties["SocialIcon"] = "fa-windows"; - adOptions.Caption = "Active Directory"; - app.UseOpenIdConnectAuthentication(adOptions); - - } - - - } - - //NOTE: Not sure exactly what this is for but it is found in the AD source demo: - // https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet/blob/master/TodoListWebApp/Utils/NaiveSessionCache.cs - public class NaiveSessionCache : TokenCache - { - private static readonly object FileLock = new object(); - readonly string _userObjectId = string.Empty; - readonly string _cacheId = string.Empty; - public NaiveSessionCache(string userId) - { - _userObjectId = userId; - _cacheId = _userObjectId + "_TokenCache"; - - this.AfterAccess = AfterAccessNotification; - this.BeforeAccess = BeforeAccessNotification; - Load(); - } - - public void Load() - { - lock (FileLock) - { - this.Deserialize((byte[])HttpContext.Current.Session[_cacheId]); - } - } - - public void Persist() - { - lock (FileLock) - { - // reflect changes in the persistent store - HttpContext.Current.Session[_cacheId] = this.Serialize(); - // once the write operation took place, restore the HasStateChanged bit to false - this.HasStateChanged = false; - } - } - - // Empties the persistent store. - public override void Clear() - { - base.Clear(); - System.Web.HttpContext.Current.Session.Remove(_cacheId); - } - - public override void DeleteItem(TokenCacheItem item) - { - base.DeleteItem(item); - Persist(); - } - - // Triggered right before ADAL needs to access the cache. - // Reload the cache from the persistent store in case it changed since the last access. - void BeforeAccessNotification(TokenCacheNotificationArgs args) - { - Load(); - } - - // Triggered right after ADAL accessed the cache. - void AfterAccessNotification(TokenCacheNotificationArgs args) - { - // if the access operation resulted in a cache update - if (this.HasStateChanged) - { - Persist(); - } + //app.ConfigureGoogleAuth("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET"); + //app.ConfigureFacebookAuth("YOUR_APP_ID", "YOUR_APP_SECRET"); + //app.ConfigureMicrosoftAuth("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET"); + //app.ConfigureActiveDirectory("YOUR_TENANT", "YOUR_CLIENT_ID", "YOUR_POST_LOGIN_REDIRECT_URL", "YOUR_APP_KEY", "YOUR_AUTH_TYPE"); } } - } \ 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 4b8e33ca86..0c74a63e4b 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -191,6 +191,9 @@ False ..\packages\Microsoft.Owin.Security.Google.3.0.1\lib\net45\Microsoft.Owin.Security.Google.dll + + ..\packages\Microsoft.Owin.Security.MicrosoftAccount.3.0.1\lib\net45\Microsoft.Owin.Security.MicrosoftAccount.dll + False ..\packages\Microsoft.Owin.Security.OAuth.3.0.1\lib\net45\Microsoft.Owin.Security.OAuth.dll @@ -380,6 +383,7 @@ Properties\SolutionInfo.cs + loadStarterKits.ascx ASPXCodeBehind diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index c0e0034b61..62c48ef30a 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -31,6 +31,7 @@ + diff --git a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs index 0e8712ed07..67a3625f34 100644 --- a/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/Identity/AppBuilderExtensions.cs @@ -16,6 +16,7 @@ namespace Umbraco.Web.Security.Identity { public static class AppBuilderExtensions { + #region Backoffice /// /// Configure Identity User Manager for Umbraco /// @@ -32,8 +33,8 @@ namespace Umbraco.Web.Security.Identity //Configure Umbraco user manager to be created per request app.CreatePerOwinContext( (options, owinContext) => BackOfficeUserManager.Create( - options, - owinContext, + options, + owinContext, appContext.Services.UserService, appContext.Services.ExternalLoginService, userMembershipProvider)); @@ -58,7 +59,7 @@ namespace Umbraco.Web.Security.Identity GlobalSettings.UseSSL) { Provider = new CookieAuthenticationProvider - { + { //// Enables the application to validate the security stamp when the user //// logs in. This is a security feature which is used when you //// change a password or add an external login to your account. @@ -99,7 +100,8 @@ namespace Umbraco.Web.Security.Identity }); return app; - } + } + #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Web/Security/Identity/NaiveSessionCache.cs b/src/Umbraco.Web/Security/Identity/NaiveSessionCache.cs deleted file mode 100644 index f4df1fbb30..0000000000 --- a/src/Umbraco.Web/Security/Identity/NaiveSessionCache.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Microsoft.IdentityModel.Clients.ActiveDirectory; - -namespace Umbraco.Web.Security.Identity -{ - //NOTE: Not sure exactly what this is for but it is found in the AD source demo: - // https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet/blob/master/TodoListWebApp/Utils/NaiveSessionCache.cs - // apparently it is needed for AD auth, so we'll put it here for people to use. - // It would appear that this is better for whatever reason: https://github.com/OfficeDev/O365-WebApp-SingleTenant/blob/master/O365-WebApp-SingleTenant/Models/ADALTokenCache.cs - // and please note that that link came from finding this thread: https://twitter.com/chakkaradeep/status/544962341528285184 - - /// - /// This is required to initialize the AD Identity provider on startup - /// - public class NaiveSessionCache : TokenCache - { - private static readonly object FileLock = new object(); - readonly string _userObjectId = string.Empty; - readonly string _cacheId = string.Empty; - public NaiveSessionCache(string userId) - { - _userObjectId = userId; - _cacheId = _userObjectId + "_TokenCache"; - - this.AfterAccess = AfterAccessNotification; - this.BeforeAccess = BeforeAccessNotification; - Load(); - } - - public void Load() - { - lock (FileLock) - { - this.Deserialize((byte[])HttpContext.Current.Session[_cacheId]); - } - } - - public void Persist() - { - lock (FileLock) - { - // reflect changes in the persistent store - HttpContext.Current.Session[_cacheId] = this.Serialize(); - // once the write operation took place, restore the HasStateChanged bit to false - this.HasStateChanged = false; - } - } - - // Empties the persistent store. - public override void Clear() - { - base.Clear(); - System.Web.HttpContext.Current.Session.Remove(_cacheId); - } - - public override void DeleteItem(TokenCacheItem item) - { - base.DeleteItem(item); - Persist(); - } - - // Triggered right before ADAL needs to access the cache. - // Reload the cache from the persistent store in case it changed since the last access. - void BeforeAccessNotification(TokenCacheNotificationArgs args) - { - Load(); - } - - // Triggered right after ADAL accessed the cache. - void AfterAccessNotification(TokenCacheNotificationArgs args) - { - // if the access operation resulted in a cache update - if (this.HasStateChanged) - { - Persist(); - } - } - } -} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 79c59c85a4..0b8fea4a2f 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -138,12 +138,6 @@ ..\packages\Microsoft.AspNet.Identity.Owin.2.1.0\lib\net45\Microsoft.AspNet.Identity.Owin.dll - - ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll - - - ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll - False ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll @@ -560,7 +554,6 @@ - diff --git a/src/Umbraco.Web/packages.config b/src/Umbraco.Web/packages.config index d1898c46fd..bd20574668 100644 --- a/src/Umbraco.Web/packages.config +++ b/src/Umbraco.Web/packages.config @@ -18,7 +18,6 @@ -