Browse Source

Frontend Area.

pull/169/head
Sebastian Stehle 9 years ago
parent
commit
7efb337ae6
  1. 2
      src/Squidex/Areas/Frontend/Middlewares/WebpackMiddleware.cs
  2. 81
      src/Squidex/Areas/Frontend/Startup.cs
  3. 42
      src/Squidex/Areas/OrleansDashboard/Middlewares/OrleansDashboardAuthenticationMiddleware.cs
  4. 27
      src/Squidex/Areas/OrleansDashboard/Startup.cs
  5. 6
      src/Squidex/Config/Constants.cs
  6. 13
      src/Squidex/Config/Identity/AuthenticationServices.cs
  7. 36
      src/Squidex/Config/Identity/LazyClientStore.cs
  8. 27
      src/Squidex/Config/Orleans/SiloExtensions.cs
  9. 32
      src/Squidex/Config/Web/WebExtensions.cs
  10. 7
      src/Squidex/Config/Web/WebpackExtensions.cs
  11. 14
      src/Squidex/Controllers/UI/Account/AccountController.cs
  12. 2
      src/Squidex/Program.cs
  13. 49
      src/Squidex/WebStartup.cs
  14. 4
      src/Squidex/app/shared/services/auth.service.ts
  15. 12
      src/Squidex/wwwroot/client-callback-popup.html
  16. 12
      src/Squidex/wwwroot/client-callback-silent.html

2
src/Squidex/Pipeline/WebpackMiddleware.cs → src/Squidex/Areas/Frontend/Middlewares/WebpackMiddleware.cs

@ -11,7 +11,7 @@ using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace Squidex.Pipeline
namespace Squidex.Areas.Frontend.Middlewares
{
public sealed class WebpackMiddleware
{

81
src/Squidex/Areas/Frontend/Startup.cs

@ -0,0 +1,81 @@
// ==========================================================================
// Startup.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;
using Squidex.Areas.Frontend.Middlewares;
namespace Squidex.Areas.Frontend
{
public static class Startup
{
public static void ConfigureFrontend(this IApplicationBuilder app)
{
var environment = app.ApplicationServices.GetRequiredService<IHostingEnvironment>();
if (environment.IsDevelopment())
{
app.UseMiddleware<WebpackMiddleware>();
}
app.Use((context, next) =>
{
if (context.Request.Path == "/client-callback-popup")
{
context.Request.Path = new PathString("/client-callback-popup.html");
}
else if (context.Request.Path == "/client-callback-silent")
{
context.Request.Path = new PathString("/client-callback-silent.html");
}
else if (!Path.HasExtension(context.Request.Path.Value))
{
if (environment.IsDevelopment())
{
context.Request.Path = new PathString("/index.html");
}
else
{
context.Request.Path = new PathString("/build/index.html");
}
}
return next();
});
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
var response = context.Context.Response;
var responseHeaders = response.GetTypedHeaders();
if (!string.Equals(response.ContentType, "text/html", StringComparison.OrdinalIgnoreCase))
{
responseHeaders.CacheControl = new CacheControlHeaderValue
{
MaxAge = TimeSpan.FromDays(60)
};
}
else
{
responseHeaders.CacheControl = new CacheControlHeaderValue
{
NoCache = true
};
}
}
});
}
}
}

42
src/Squidex/Areas/OrleansDashboard/Middlewares/OrleansDashboardAuthenticationMiddleware.cs

@ -0,0 +1,42 @@
// ==========================================================================
// LazyClientStore.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;
using Squidex.Shared.Identity;
namespace Squidex.Areas.OrleansDashboard.Middlewares
{
public sealed class OrleansDashboardAuthenticationMiddleware
{
private readonly RequestDelegate next;
public OrleansDashboardAuthenticationMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
var authentication = await context.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
if (!authentication.Succeeded || !authentication.Principal.IsInRole(SquidexRoles.Administrator))
{
await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
{
RedirectUri = context.Request.PathBase + context.Request.Path
});
}
await next(context);
}
}
}

27
src/Squidex/Areas/OrleansDashboard/Startup.cs

@ -0,0 +1,27 @@
// ==========================================================================
// Startup.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Microsoft.AspNetCore.Builder;
using Orleans;
using Squidex.Areas.OrleansDashboard.Middlewares;
namespace Squidex.Areas.OrleansDashboard
{
public static class Startup
{
public static void ConfigureOrleansDashboard(this IApplicationBuilder app)
{
app.Map("/orleans", orleansApp =>
{
orleansApp.UseAuthentication();
orleansApp.UseMiddleware<OrleansDashboardAuthenticationMiddleware>();
orleansApp.UseOrleansDashboard();
});
}
}
}

6
src/Squidex/Config/Constants.cs

@ -6,6 +6,8 @@
// All rights reserved.
// ==========================================================================
using IdentityServer4.Models;
namespace Squidex.Config
{
public static class Constants
@ -22,6 +24,10 @@ namespace Squidex.Config
public static readonly string FrontendClient = "squidex-frontend";
public static readonly string InternalClientId = "squidex-internal";
public static readonly string InternalClientSecret = "squidex-internal".Sha256();
public static readonly string IdentityPrefix = "/identity-server";
public static readonly string OrleansPrefix = "/orleans";

13
src/Squidex/Config/Identity/AuthenticationServices.cs

@ -7,6 +7,7 @@
// ==========================================================================
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -21,6 +22,7 @@ namespace Squidex.Config.Identity
var identityOptions = config.GetSection("identity").Get<MyIdentityOptions>();
services.AddAuthentication()
.AddCookie()
.AddMyGoogleAuthentication(identityOptions)
.AddMyMicrosoftAuthentication(identityOptions)
.AddMyApiProtection(identityOptions, config);
@ -52,6 +54,17 @@ namespace Squidex.Config.Identity
options.ApiSecret = null;
options.RequireHttpsMetadata = identityOptions.RequiresHttps;
});
authBuilder.AddOpenIdConnect(options =>
{
options.ClientId = Constants.InternalClientId;
options.ClientSecret = Constants.InternalClientSecret;
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = apiAuthorityUrl;
options.RequireHttpsMetadata = identityOptions.RequiresHttps;
options.Scope.Add(Constants.RoleScope);
options.SaveTokens = true;
});
}
return authBuilder;

36
src/Squidex/Config/Identity/LazyClientStore.cs

@ -91,17 +91,17 @@ namespace Squidex.Config.Identity
private static IEnumerable<Client> CreateStaticClients(MyUrlsOptions urlsOptions)
{
var id = Constants.FrontendClient;
var frontendId = Constants.FrontendClient;
yield return new Client
{
ClientId = id,
ClientName = id,
ClientId = frontendId,
ClientName = frontendId,
RedirectUris = new List<string>
{
urlsOptions.BuildUrl("login;"),
urlsOptions.BuildUrl("identity-server/client-callback-silent/"),
urlsOptions.BuildUrl("identity-server/client-callback-popup/")
urlsOptions.BuildUrl("client-callback-silent", false),
urlsOptions.BuildUrl("client-callback-popup", false)
},
PostLogoutRedirectUris = new List<string>
{
@ -120,6 +120,32 @@ namespace Squidex.Config.Identity
},
RequireConsent = false
};
var internalClient = Constants.InternalClientId;
yield return new Client
{
ClientId = internalClient,
ClientName = internalClient,
ClientSecrets = new List<Secret> { new Secret(Constants.InternalClientSecret) },
RedirectUris = new List<string>
{
urlsOptions.BuildUrl("orleans/signin-oidc", false),
urlsOptions.BuildUrl("portal/signin-oidc", false)
},
AccessTokenLifetime = (int)TimeSpan.FromDays(30).TotalSeconds,
AllowedGrantTypes = GrantTypes.ImplicitAndClientCredentials,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
Constants.ApiScope,
Constants.ProfileScope,
Constants.RoleScope
},
RequireConsent = false
};
}
}
}

27
src/Squidex/Config/Orleans/SiloExtensions.cs

@ -7,13 +7,10 @@
// ==========================================================================
using System.Reflection;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Orleans;
using Orleans.Hosting;
using Orleans.Runtime.Configuration;
using Squidex.Shared.Identity;
namespace Squidex.Config.Orleans
{
@ -42,29 +39,5 @@ namespace Squidex.Config.Orleans
return config;
}
public static IApplicationBuilder UseMyOrleansDashboard(this IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var authentication = await context.AuthenticateAsync();
if (authentication.Succeeded && authentication.Principal.IsInRole(SquidexRoles.Administrator))
{
await next();
}
else
{
await context.ChallengeAsync(new AuthenticationProperties
{
RedirectUri = context.Request.PathBase + context.Request.Path
});
}
});
app.UseOrleansDashboard();
return app;
}
}
}

32
src/Squidex/Config/Web/WebExtensions.cs

@ -6,11 +6,8 @@
// All rights reserved.
// ==========================================================================
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Net.Http.Headers;
using Squidex.Pipeline;
namespace Squidex.Config.Web
@ -37,34 +34,5 @@ namespace Squidex.Config.Web
app.UseMiddleware<EnforceHttpsMiddleware>();
}
public static void UseMyCachedStaticFiles(this IApplicationBuilder app)
{
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
context.Context.Request.GetTypedHeaders();
var response = context.Context.Response;
var headers = response.GetTypedHeaders();
if (!string.Equals(response.ContentType, "text/html", StringComparison.OrdinalIgnoreCase))
{
headers.CacheControl = new CacheControlHeaderValue
{
MaxAge = TimeSpan.FromDays(60)
};
}
else
{
headers.CacheControl = new CacheControlHeaderValue
{
NoCache = true
};
}
}
});
}
}
}

7
src/Squidex/Config/Web/WebpackExtensions.cs

@ -13,13 +13,6 @@ namespace Squidex.Config.Web
{
public static class WebpackExtensions
{
public static IApplicationBuilder UseWebpackProxy(this IApplicationBuilder app)
{
app.UseMiddleware<WebpackMiddleware>();
return app;
}
public static IApplicationBuilder UseMyTracking(this IApplicationBuilder app)
{
app.UseMiddleware<LogPerformanceMiddleware>();

14
src/Squidex/Controllers/UI/Account/AccountController.cs

@ -61,20 +61,6 @@ namespace Squidex.Controllers.UI.Account
this.signInManager = signInManager;
}
[HttpGet]
[Route("client-callback-silent/")]
public IActionResult ClientSilent()
{
return View();
}
[HttpGet]
[Route("client-callback-popup/")]
public IActionResult ClientPopup()
{
return View();
}
[HttpGet]
[Route("account/forbidden/")]
public IActionResult Forbidden()

2
src/Squidex/Program.cs

@ -41,7 +41,7 @@ namespace Squidex
})
.ConfigureLogging(builder =>
{
builder.AddSemanticLog();
// builder.AddSemanticLog();
})
.ConfigureAppConfiguration((hostContext, builder) =>
{

49
src/Squidex/WebStartup.cs

@ -7,14 +7,14 @@
// ==========================================================================
using System;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Orleans;
using Squidex.Areas.Frontend;
using Squidex.Areas.OrleansDashboard;
using Squidex.Config;
using Squidex.Config.Domain;
using Squidex.Config.Identity;
@ -60,15 +60,13 @@ namespace Squidex
app.UseMyCors();
app.UseMyForwardingRules();
app.UseMyTracking();
app.UseMyAuthentication();
MapAndUseIdentityServer(app);
MapAndUseApi(app);
MapAndUseOrleans(app);
MapAndUseFrontend(app);
}
private void MapAndUseOrleans(IApplicationBuilder app)
{
app.ConfigureOrleansDashboard();
app.ConfigureFrontend();
}
private void MapAndUseIdentityServer(IApplicationBuilder app)
@ -84,7 +82,6 @@ namespace Squidex
identityApp.UseExceptionHandler("/error");
}
identityApp.UseMyAuthentication();
identityApp.UseMyIdentityServer();
identityApp.UseMyAdminRole();
identityApp.UseMyAdmin();
@ -94,11 +91,6 @@ namespace Squidex
{
mvcApp.UseMvc();
});
identityApp.Map(Constants.OrleansPrefix, orleansApp =>
{
orleansApp.UseMyOrleansDashboard();
});
});
}
@ -120,37 +112,6 @@ namespace Squidex
});
}
private void MapAndUseFrontend(IApplicationBuilder app)
{
if (environment.IsDevelopment())
{
app.UseWebpackProxy();
app.Use((context, next) =>
{
if (!Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = new PathString("/index.html");
}
return next();
});
}
else
{
app.Use((context, next) =>
{
if (!Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = new PathString("/build/index.html");
}
return next();
});
}
app.UseMyCachedStaticFiles();
}
private static bool IsIdentityRequest(HttpContext context)
{
return IdentityServerPaths.Any(p => context.Request.Path.StartsWithSegments(p));

4
src/Squidex/app/shared/services/auth.service.ts

@ -79,8 +79,8 @@ export class AuthService {
response_type: 'id_token token',
redirect_uri: apiUrl.buildUrl('login;'),
post_logout_redirect_uri: apiUrl.buildUrl('logout'),
silent_redirect_uri: apiUrl.buildUrl('identity-server/client-callback-silent/'),
popup_redirect_uri: apiUrl.buildUrl('identity-server/client-callback-popup/'),
silent_redirect_uri: apiUrl.buildUrl('client-callback-silent'),
popup_redirect_uri: apiUrl.buildUrl('client-callback-popup'),
authority: apiUrl.buildUrl('identity-server/'),
userStore: new WebStorageStateStore({ store: window.localStorage || window.sessionStorage }),
automaticSilentRenew: true

12
src/Squidex/wwwroot/client-callback-popup.html

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<script src="/scripts/oidc-client.min.js"></script>
<script>
Oidc.Log.logger = console;
Oidc.Log.logLevel = Oidc.Log.INFO;
new Oidc.UserManager().signinPopupCallback();
</script>
</body>
</html>

12
src/Squidex/wwwroot/client-callback-silent.html

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<body>
<script src="/scripts/oidc-client.min.js"></script>
<script>
Oidc.Log.logger = console;
Oidc.Log.logLevel = Oidc.Log.INFO;
new Oidc.UserManager().signinSilentCallback();
</script>
</body>
</html>
Loading…
Cancel
Save