Skip to content

Commit

Permalink
Merge pull request #1261 from PiranhaCMS/features/simplify-authentica…
Browse files Browse the repository at this point in the history
…tion

Added core support for authentication. Fixes #1259
  • Loading branch information
tidyui authored Jun 30, 2020
2 parents 6211fbf + 05f4141 commit bf859f3
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 11 deletions.
2 changes: 1 addition & 1 deletion core/Piranha.AspNetCore/ArchiveMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public override async Task Invoke(HttpContext context, IApi api, IApplicationSer

if (!response.IsPublished)
{
if (!context.User.HasClaim(Security.Permission.PagePreview, Security.Permission.PagePreview))
if (!context.User.HasClaim(Piranha.Security.Permission.PagePreview, Piranha.Security.Permission.PagePreview))
{
_logger?.LogInformation($"User not authorized to preview unpublished archive page");
authorized = false;
Expand Down
50 changes: 50 additions & 0 deletions core/Piranha.AspNetCore/AspNetCoreSecurityExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) .NET Foundation and Contributors
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* https://github.com/piranhacms/piranha.core
*
*/

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Piranha;
using Piranha.AspNetCore.Security;

/// <summary>
/// Security extensions for simplifying authorization in
/// the client application.
/// </summary>
public static class AspNetCoreSecurityExtensions
{
/// <summary>
/// Adds authorization with the given application policies to the aplication.
/// </summary>
/// <param name="builder">The service builder</param>
/// <param name="options">The security options</param>
/// <returns>The service builder</returns>
public static PiranhaServiceBuilder UseSecurity(this PiranhaServiceBuilder builder, Action<SecurityBuilder> options)
{
// Add authentication
builder.Services.AddAuthorization(o =>
{
// Invoke the security options
var securityBuilder = new SecurityBuilder(o, builder);
options?.Invoke(securityBuilder);
});
return builder;
}

/// <summary>
/// Adds the security middleware to the pipeline.
/// </summary>
/// <param name="builder">The current application builder</param>
/// <returns>The update builder</returns>
public static IApplicationBuilder UseSecurityMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Piranha.AspNetCore.Security.SecurityMiddleware>();
}
}
4 changes: 3 additions & 1 deletion core/Piranha.AspNetCore/AspNetCoreStartupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public static IServiceCollection AddPiranha(this IServiceCollection services, Ac

var config = new PiranhaRouteConfig
{
LoginUrl = serviceBuilder.LoginUrl,
UseAliasRouting = serviceBuilder.UseAliasRouting,
UseArchiveRouting = serviceBuilder.UseArchiveRouting,
UsePageRouting = serviceBuilder.UsePageRouting,
Expand Down Expand Up @@ -64,6 +65,7 @@ public static IApplicationBuilder UsePiranha(this IApplicationBuilder builder, A
var piranhaOptions = new PiranhaApplicationBuilder(builder);

piranhaOptions.Builder
.UseSecurityMiddleware()
.UseStaticFiles()
.UseIntegratedPiranha()
.UsePiranhaSitemap()
Expand All @@ -75,4 +77,4 @@ public static IApplicationBuilder UsePiranha(this IApplicationBuilder builder, A

return piranhaOptions.Builder;
}
}
}
64 changes: 64 additions & 0 deletions core/Piranha.AspNetCore/Security/SecurityBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) .NET Foundation and Contributors
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* https://github.com/piranhacms/piranha.core
*
*/

using Microsoft.AspNetCore.Authorization;

namespace Piranha.AspNetCore.Security
{
/// <summary>
/// The security builder is used for creating application
/// policies that can be selected from the manager
/// interface.
/// </summary>
public class SecurityBuilder
{
/// <summary>
/// The policy builder.
/// </summary>
private readonly AuthorizationOptions _options;
private readonly PiranhaServiceBuilder _builder;

/// <summary>
/// Default constructor.
/// </summary>
/// <param name="options">The authorization options</param>
/// <param name="builder">The service builder</param>
public SecurityBuilder(AuthorizationOptions options, PiranhaServiceBuilder builder)
{
_options = options;
_builder = builder;
}

/// <summary>
/// Uses the specified permission in the application.
/// </summary>
/// <param name="name">The name</param>
/// <param name="title">The optional title. If omitted the name will be used as title</param>
/// <returns>The builder</returns>
public SecurityBuilder UsePermission(string name, string title = null)
{
// Add a policy with the specified name
_options.AddPolicy(name, policy =>
{
// Require a claim with the same name as the policy
policy.RequireClaim(name, name);

// Add the specified policy to the manager
App.Permissions["App"].Add(new Piranha.Security.PermissionItem
{
Title = title != null ? title : name,
Name = name
});
});

return this;
}
}
}
38 changes: 38 additions & 0 deletions core/Piranha.AspNetCore/Security/SecurityMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) .NET Foundation and Contributors
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* https://github.com/piranhacms/piranha.core
*
*/

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Piranha.AspNetCore.Services;

namespace Piranha.AspNetCore.Security
{
public class SecurityMiddleware
{
private readonly RequestDelegate _next;
private readonly PiranhaRouteConfig _config;

public SecurityMiddleware(RequestDelegate next, PiranhaRouteConfig config)
{
_next = next;
_config = config;
}

public async Task InvokeAsync(HttpContext ctx, IApplicationService service)
{
await _next(ctx);

if (ctx.Response.StatusCode == 401)
{
ctx.Response.Redirect($"{ _config.LoginUrl }?returnUrl={ service.Request.Url }");
}
}
}
}
4 changes: 2 additions & 2 deletions core/Piranha.AspNetCore/Services/ModelLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public async Task<T> GetPageAsync<T>(Guid id, ClaimsPrincipal user, bool draft =
if (draft)
{
// Check that the current user is authorized to preview pages
if ((await _auth.AuthorizeAsync(user, Security.Permission.PagePreview)).Succeeded)
if ((await _auth.AuthorizeAsync(user, Piranha.Security.Permission.PagePreview)).Succeeded)
{
// Get the draft, if available
model = await _api.Pages.GetDraftByIdAsync<T>(id);
Expand Down Expand Up @@ -153,7 +153,7 @@ public async Task<T> GetPostAsync<T>(Guid id, ClaimsPrincipal user, bool draft =
if (draft)
{
// Check that the current user is authorized to preview pages
if ((await _auth.AuthorizeAsync(user, Security.Permission.PostPreview)).Succeeded)
if ((await _auth.AuthorizeAsync(user, Piranha.Security.Permission.PostPreview)).Succeeded)
{
// Get the draft, if available
model = await _api.Posts.GetDraftByIdAsync<T>(id);
Expand Down
2 changes: 1 addition & 1 deletion core/Piranha.AspNetCore/StartPageMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public override async Task Invoke(HttpContext context, IApi api, IApplicationSer

if (!response.IsPublished)
{
if (!context.User.HasClaim(Security.Permission.PagePreview, Security.Permission.PagePreview))
if (!context.User.HasClaim(Piranha.Security.Permission.PagePreview, Piranha.Security.Permission.PagePreview))
{
_logger?.LogInformation($"User not authorized to preview unpublished page");
authorized = false;
Expand Down
5 changes: 5 additions & 0 deletions core/Piranha/PiranhaRouteConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ namespace Piranha
/// </summary>
public class PiranhaRouteConfig
{
/// <summary>
/// Gets/sets the login url.
/// </summary>
public string LoginUrl { get; set; } = "/login";

/// <summary>
/// Gets/sets if alias routing should be used.
/// </summary>
Expand Down
1 change: 0 additions & 1 deletion examples/RazorWeb/RazorWeb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
<ProjectReference Include="..\..\core\Piranha.Local.FileStorage\Piranha.Local.FileStorage.csproj" />
<ProjectReference Include="..\..\core\Piranha.Manager\Piranha.Manager.csproj" />
<ProjectReference Include="..\..\core\Piranha.Manager.TinyMCE\Piranha.Manager.TinyMCE.csproj" />
<ProjectReference Include="..\..\core\Piranha.WebApi\Piranha.WebApi.csproj" />
<ProjectReference Include="..\..\data\Piranha.Data.EF.SQLite\Piranha.Data.EF.SQLite.csproj" />
<ProjectReference Include="..\..\data\Piranha.Data.EF.MySql\Piranha.Data.EF.MySql.csproj" />
<ProjectReference Include="..\..\data\Piranha.Data.EF.PostgreSql\Piranha.Data.EF.PostgreSql.csproj" />
Expand Down
12 changes: 7 additions & 5 deletions examples/RazorWeb/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ public void ConfigureServices(IServiceCollection services)
options.UseManager();
options.UseTinyMCE();
options.UseMemoryCache();
options.UseApi(config =>
{
config.AllowAnonymousAccess = true;
});

options.UseEF<SQLiteDb>(db =>
db.UseSqlite("Filename=./piranha.razorweb.db"));
options.UseIdentityWithSeed<IdentitySQLiteDb>(db =>
db.UseSqlite("Filename=./piranha.razorweb.db"));

options.UseSecurity(o =>
{
o.UsePermission("Subscriber");
});
});

services.AddSwaggerGen(options =>
Expand Down Expand Up @@ -100,7 +101,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApi api
//
// Simplified setup with dependencies
//
app.UsePiranha(options => {
app.UsePiranha(options =>
{
options.UseManager();
options.UseTinyMCE();
options.UseIdentity();
Expand Down

0 comments on commit bf859f3

Please sign in to comment.