WIP audiences
This commit is contained in:
parent
9846210fd6
commit
f3bb039d2f
15 changed files with 102 additions and 82 deletions
22
contrib/bruno/blog post.yml
Normal file
22
contrib/bruno/blog post.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
info:
|
||||||
|
name: blog post
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
|
||||||
|
http:
|
||||||
|
method: POST
|
||||||
|
url: "{{Blogs}}/api/v1/blog"
|
||||||
|
body:
|
||||||
|
type: json
|
||||||
|
data: |-
|
||||||
|
{
|
||||||
|
"Title": "lkijlk",
|
||||||
|
"Article": "test"
|
||||||
|
}
|
||||||
|
auth: inherit
|
||||||
|
|
||||||
|
settings:
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
followRedirects: true
|
||||||
|
maxRedirects: 5
|
||||||
|
|
@ -25,7 +25,7 @@ request:
|
||||||
credentials:
|
credentials:
|
||||||
clientId: postit
|
clientId: postit
|
||||||
placement: basic_auth_header
|
placement: basic_auth_header
|
||||||
scope: openid blogs
|
scope: openid blogs profile
|
||||||
pkce: {}
|
pkce: {}
|
||||||
tokenConfig:
|
tokenConfig:
|
||||||
id: credentials
|
id: credentials
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ namespace Yavsc
|
||||||
|
|
||||||
public const string StreamingPath = "/api/stream/put";
|
public const string StreamingPath = "/api/stream/put";
|
||||||
|
|
||||||
|
public static string NameClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/name";
|
||||||
|
|
||||||
public static string RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
|
public static string RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Yavsc.Abstract.Identity
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static string AvatarSrc(IApplicationUser? user)
|
public static string AvatarSrc(IApplicationUser? user)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(user?.UserName))
|
if (user==null || string.IsNullOrWhiteSpace(user?.UserName))
|
||||||
return YavscConstants.DefaultAvatar;
|
return YavscConstants.DefaultAvatar;
|
||||||
return $"{YavscConstants.AvatarsPath}/{user!.UserName}.s.png";
|
return $"{YavscConstants.AvatarsPath}/{user!.UserName}.s.png";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ namespace Yavsc.Blogs.Controllers
|
||||||
return new StatusCodeResult(StatusCodes.Status204NoContent);
|
return new StatusCodeResult(StatusCodes.Status204NoContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: api/BlogApi
|
// POST: api/v1/blog
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public IActionResult PostBlog([FromBody] Models.Blog.BlogPost blog)
|
public IActionResult PostBlog([FromBody] Models.Blog.BlogPost blog)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ internal class Program
|
||||||
.AddYavscCors(builder.Configuration)
|
.AddYavscCors(builder.Configuration)
|
||||||
.AddControllers();
|
.AddControllers();
|
||||||
String authority = builder.Configuration.GetValue<string>("Site:Authority");
|
String authority = builder.Configuration.GetValue<string>("Site:Authority");
|
||||||
String audience = builder.Configuration.GetValue<string>("Site:Audience");
|
|
||||||
if (string.IsNullOrEmpty(authority))
|
if (string.IsNullOrEmpty(authority))
|
||||||
{
|
{
|
||||||
throw new Exception("Site:Authority is not configured in appsettings.json");
|
throw new Exception("Site:Authority is not configured in appsettings.json");
|
||||||
|
|
@ -100,7 +100,7 @@ internal class Program
|
||||||
.UseCors("default")
|
.UseCors("default")
|
||||||
;
|
;
|
||||||
app.Services.GetRequiredService<ILoggerFactory>().CreateLogger("Program")
|
app.Services.GetRequiredService<ILoggerFactory>().CreateLogger("Program")
|
||||||
.LogInformation($"Yavsc.Blogs started, Authority is '{authority}', Audience is '{audience}'");
|
.LogInformation($"Yavsc.Blogs started, Authority is '{authority}''");
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
app.MapIdentityApi<ApplicationUser>().RequireAuthorization("BlogScope")
|
app.MapIdentityApi<ApplicationUser>().RequireAuthorization("BlogScope")
|
||||||
.WithHttpLogging(Microsoft.AspNetCore.HttpLogging.HttpLoggingFields.All)
|
.WithHttpLogging(Microsoft.AspNetCore.HttpLogging.HttpLoggingFields.All)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
"Description": "A collection of blogs about software development, technology, and programming.",
|
"Description": "A collection of blogs about software development, technology, and programming.",
|
||||||
"Keywords": "software development, technology, programming, coding, blogs",
|
"Keywords": "software development, technology, programming, coding, blogs",
|
||||||
"Authority": "https://localhost:5001",
|
"Authority": "https://localhost:5001",
|
||||||
|
"Audience": ["blogs"],
|
||||||
"CorsAllowedOrigins": [
|
"CorsAllowedOrigins": [
|
||||||
"https://localhost:5005"
|
"https://localhost:5005"
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ using Yavsc.Server.Helpers;
|
||||||
|
|
||||||
// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
|
||||||
|
|
||||||
namespace Yavsc.Controllers
|
namespace Yavsc.Org.Controllers
|
||||||
{
|
{
|
||||||
public class BlogSpotController : Controller
|
public class BlogSpotController : Controller
|
||||||
{
|
{
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Yavsc.Controllers
|
||||||
BlogSpotService blogSpotService)
|
BlogSpotService blogSpotService)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_logger = loggerFactory.CreateLogger<AccountController>();
|
_logger = loggerFactory.CreateLogger<BlogSpotController>();
|
||||||
_authorizationService = authorizationService;
|
_authorizationService = authorizationService;
|
||||||
_localisationOptions = localisationOptions.Value;
|
_localisationOptions = localisationOptions.Value;
|
||||||
this.blogSpotService = blogSpotService;
|
this.blogSpotService = blogSpotService;
|
||||||
|
|
@ -76,7 +76,7 @@ namespace Yavsc.Controllers
|
||||||
return View(blog);
|
return View(blog);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (AuthorizationFailureException ex)
|
catch (AuthorizationFailureException)
|
||||||
{
|
{
|
||||||
return Challenge();
|
return Challenge();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,8 +157,7 @@ public static class HostingExtensions
|
||||||
|
|
||||||
|
|
||||||
services.AddAuthentication("Bearer")
|
services.AddAuthentication("Bearer")
|
||||||
.AddYavscJwtBearer(builder.Configuration,
|
.AddYavscJwtBearer(builder.Configuration);
|
||||||
configure: o => o.Audience = builder.Configuration.GetSection("Site")["ExternalUrl"]);
|
|
||||||
|
|
||||||
services.AddTransient<RoleManager<IdentityRole>>();
|
services.AddTransient<RoleManager<IdentityRole>>();
|
||||||
services.AddTransient<IRoleStore<IdentityRole>, RoleStore<IdentityRole, ApplicationDbContext>>();
|
services.AddTransient<IRoleStore<IdentityRole>, RoleStore<IdentityRole, ApplicationDbContext>>();
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,24 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.DotNet.Scaffolding.Shared;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Yavsc;
|
using Yavsc;
|
||||||
using Yavsc.Helpers;
|
|
||||||
using Yavsc.Models;
|
using Yavsc.Models;
|
||||||
using Yavsc.Models.Blog;
|
using Yavsc.Models.Blog;
|
||||||
using Yavsc.Server.Exceptions;
|
using Yavsc.Server.Exceptions;
|
||||||
using Yavsc.Server.Helpers;
|
using Yavsc.Server.Helpers;
|
||||||
using Yavsc.Services;
|
using Yavsc.Services;
|
||||||
using Yavsc.ViewModels.Auth;
|
using Yavsc.ViewModels.Auth;
|
||||||
using Yavsc.Abstract.Helpers;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
|
|
||||||
public class BlogSpotService
|
|
||||||
|
[Obsolete]
|
||||||
|
public class OldBlogSpotService
|
||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _context;
|
private readonly ApplicationDbContext _context;
|
||||||
private readonly IAuthorizationService _authorizationService;
|
private readonly IAuthorizationService _authorizationService;
|
||||||
private readonly IFileSystemAuthManager fileSystemAuthManager;
|
private readonly IFileSystemAuthManager fileSystemAuthManager;
|
||||||
|
|
||||||
public BlogSpotService(ApplicationDbContext context,
|
public OldBlogSpotService(ApplicationDbContext context,
|
||||||
IAuthorizationService authorizationService,
|
IAuthorizationService authorizationService,
|
||||||
IFileSystemAuthManager fileSystemAuthManager)
|
IFileSystemAuthManager fileSystemAuthManager)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
@using Yavsc.Abstract.Identity
|
@using Yavsc.Abstract.Identity
|
||||||
@model ApplicationUser
|
@model ApplicationUser
|
||||||
@{
|
|
||||||
// Le helper défend contre Model null et contre UserName vide
|
|
||||||
// ou whitespace. Sans cette garde, Razor lève
|
|
||||||
// NullReferenceException ici, ce qui propage un 500 et
|
|
||||||
// masque aussi la page d'erreur.
|
|
||||||
var avuri = UserDisplayHelpers.AvatarSrc(Model);
|
|
||||||
}
|
|
||||||
<div class="userinfo">
|
<div class="userinfo">
|
||||||
|
@if (Model != null && !string.IsNullOrWhiteSpace(Model.UserName))
|
||||||
|
{
|
||||||
|
string avuri = UserDisplayHelpers.AvatarSrc(Model);
|
||||||
|
|
||||||
<a title="Posts" asp-controller="Blogspot" asp-action="Index" asp-route-id="@Model.UserName" class="btn btn-primary">
|
<a title="Posts" asp-controller="Blogspot" asp-action="Index" asp-route-id="@Model.UserName" class="btn btn-primary">
|
||||||
<img src="@avuri" asp-append-version="true" class="smalltofhol" alt="@Model.UserName" title="@Model.UserName" />
|
<img src="@avuri" asp-append-version="true" class="smalltofhol" alt="@Model.UserName" title="@Model.UserName" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
} else {
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<strong>Utilisateur inconnu</strong>
|
||||||
|
<img src="@YavscConstants.DefaultAvatar" class="smalltofhol" alt="Utilisateur inconnu" title="Utilisateur inconnu" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -74,23 +74,31 @@ public static class ServiceExtensions
|
||||||
public static AuthenticationBuilder AddYavscJwtBearer(
|
public static AuthenticationBuilder AddYavscJwtBearer(
|
||||||
this AuthenticationBuilder builder,
|
this AuthenticationBuilder builder,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
Action<JwtBearerOptions>? configure = null,
|
|
||||||
string schemeName = "Bearer")
|
string schemeName = "Bearer")
|
||||||
{
|
{
|
||||||
var authority = configuration.GetSection("Site")["Authority"]
|
var authority = configuration.GetSection("Site")["Authority"]
|
||||||
?? throw new InvalidOperationException(
|
?? throw new InvalidOperationException(
|
||||||
"Site:Authority is required to configure Yavsc JWT Bearer authentication.");
|
"Site:Authority is required to configure Yavsc JWT Bearer authentication.");
|
||||||
|
|
||||||
return builder.AddJwtBearer(schemeName, options =>
|
|
||||||
|
string[] audiences = configuration.GetSection("Site").GetSection("Audience").Get<string[]>() ?? Array.Empty<string>();
|
||||||
|
AuthenticationBuilder result = builder;
|
||||||
|
foreach (var audience in audiences)
|
||||||
|
{
|
||||||
|
result = builder.AddJwtBearer(schemeName, options =>
|
||||||
{
|
{
|
||||||
options.IncludeErrorDetails = true;
|
options.IncludeErrorDetails = true;
|
||||||
options.Authority = authority;
|
options.Authority = authority;
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
{
|
{
|
||||||
ValidateAudience = false,
|
ValidateAudience = true,
|
||||||
RoleClaimType = YavscConstants.RoleClaimType
|
ValidAudience = audience,
|
||||||
|
RoleClaimType = YavscConstants.RoleClaimType,
|
||||||
|
NameClaimType = YavscConstants.NameClaimType,
|
||||||
};
|
};
|
||||||
options.MapInboundClaims = true;
|
options.MapInboundClaims = true;
|
||||||
|
options.ClaimsIssuer = authority;
|
||||||
|
options.Audience = audience;
|
||||||
|
|
||||||
// Dev: every Yavsc resource service (Yavsc.Api, Yavsc.Blogs,
|
// Dev: every Yavsc resource service (Yavsc.Api, Yavsc.Blogs,
|
||||||
// Yavsc.Org itself) validates JWTs against the OP that runs
|
// Yavsc.Org itself) validates JWTs against the OP that runs
|
||||||
|
|
@ -115,7 +123,10 @@ public static class ServiceExtensions
|
||||||
(_, _, _, _) => true
|
(_, _, _, _) => true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
configure?.Invoke(options);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace cli
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
public string ClientSecret { get; set; }
|
public string ClientSecret { get; set; }
|
||||||
public string Authority { get; set; }
|
public string Authority { get; set; }
|
||||||
public string Audience { get; set; }
|
public string[] Audience { get; set; }
|
||||||
public string SiteAccessSheme { get; set; } = "http";
|
public string SiteAccessSheme { get; set; } = "http";
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
public string Scope { get; set; } = "profile";
|
public string Scope { get; set; } = "profile";
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"UserConnection": {
|
|
||||||
"UserName": "Paul",
|
|
||||||
"AccessToken": "IvvrnJye2b7CSFp2Hj3mEEK1-7EMbLLGJATQHAwOlRt5sIcm9aMH85kJMAxDb4yIzL76G7maoIlaWuSyhhS3qfcIB04WcVnCVdmw22ncMs8rk_L0yGuLdNBnF3HuhZXpjD-AjpLJ1TdE0q3c-yakkP_EWTjM9I00a1gGop4bgE_-LAa2uoLeaCj0dbe95OSvVKJWJ4MU0fjlvqAaUx-EC4HYicUMEQvJviR0FyyMKPYYyx4jyu_bgYbhmKX9LoE5VeEDEMsyXZE0fxqdfnflICduUqrprCvQfLoG4DZ8o7ivjoak3-xiP7CFaF1vou89mO1c9BcJYUjcZXPgNYC7K9QHwFC5sPDkOHdijUo9xfieRaaqge5tEHlZAs3H_u-bGWft7xjxHOVUPSRzzYygR27alVSUIt6rt28FoLsEGYQaVK5QNzIbOE0RVU40vQb5a6JzcTcjTtRxCMn3FneKZtilEHb2TooUy4YbmhbnDIKsa0ZMMBEshyEel8oCWz9SITjm24FbdCmUvSKOlkHhIcnSM8oez9qhDlzzcsKzahbNeO-EBINW-6qBlKISQbFmfy-zO134JEkcpfA9NybGcYPZWLWu1IrF9pDzO66X2Rh-H45pHQWRWFodHcoQh0p9ZBNwo5k_EkU731uwQZF5zgGyZnUU2VpxdjorzrpexZXpStzYnYRbGGK7kGAUZH9v16zL-nB4t55Mu12iK9jsUIS7cmqOSTj4mJWFd03dwe4xkNrLgcGSGPebmsfSWYaIk7qAmWMsPKKv_vnOpi-1sZuOgdVyH-RmuyW83IPCUiEAf63a40PuqpVxFiMmbcRqSKvh5TedjWUiEZvBvz786-atYF_b0dxCj8fDQbyWiMj-4Lj7FV4gUJFvrDX4DsRns6wL6Cs3urL4PmKHLEhRma-i589pEKmzinO7l4S2atB6uqMS_xNU7Y0um_GQ51oPk8PxxCggI2aLR4PJbuBGSJBoTDW1OV9HNa_BybrKamN8cuc8IT3LBJiHH_ImHyW1n94C2oFcaUJ1dVVt6JDJqt4EVvFiwk15SlRJMXSLWQWxPKeOTCGb-So2Gcy_DwGu8_AlVL4mOdQI0GiGRkpaWNIF3N6ek-B_7Lz1zxKX7BCx1ISurAzG7jK1FDydovJ2LOHO6QbqVH1JKRdRDCLOKZl3TpcAyOQHDo5rAl84pwf5UROMb5SfVDJtdekb7SRR",
|
|
||||||
"TokenType": "bearer",
|
|
||||||
"ExpiresIn": "1199",
|
|
||||||
"RefreshToken": "CfDJ8LSG6cXzxTtFuur3SY2RDINpvQVezgrIru8TEIfKUpNmUXe5lA4tCQ_nlkklgarH5UocJ6b95NLRon0uvVy5mE-7EY3ld_-bjLgjDnV9oPxY7Xdgb94_5HdDWcyG_Zaw67T0G_t21bvNEgtw0zewbdisPpjKopfH7avQWxlRrMbN9Wboj2ZXYVCbmu2EkeyG5665-B16UEQFF7dVT6qU4qnSldIfhx5ex8Ii5aGg0pDAEnRUNla_iObls2yAf18bmTAfF-34kmClqqLCr7z4Cy65DwQ8EHNA9oIEvgCEuj04IG5wC79vycZrw0NLQWAz7fTahRreD_WsmbIKdUqkvlDjV1W3Dq7KUCi4bAk7oAJuqdl3qZg4SohmQ31IKD08aKSOPa4_jtJ-eKOlT6fdDhpoaP3DyKS09OkvAwbMA86937IrCCFZsGBhHAm-yszHXjVjPCr7gAJYaBjneAUAoseEYK0GaOVGXfhxQcURXtM9TyH3pgHjccOzq300Djv-BpfQZcSZnQf59kulL_gt--451r8UIw3wxQ6BD5fGVF_MrilUluLyhoqoGZJbiHFyL-miKjW7feGFuogVyee0nIO1Me-7T-aTQnn-LivP9avyHab4eGwg1nfUbEspA21vmz2UXkUvKvT-JRGmSxlYineeJURQMcGGbcvr9GbFy1A_vbImUSw_Tx0u7_7jwxkDwlTt5WvGVsFFHsj9vgtNSnWHRzbGhbOSBocg0eWylgmYy3yZtdajRx6xQluRUewP_K66GsmA6xVmekUo0_ZzUPj61VQzTMR-knYE-pCd6V_qGS4qtUNeQ5nPLWT6hRPvnd3kK7CS22ijEErm3LaOY2DogGYIoBLvmdande226KW48hUgQPxsmOLoUl1tXMYsiRqHKAnWlzg4-e_BfRe3YsMUwlNPcqYf0hQ-mE-j4fVo79XJFFSWF8WxYKed-imDYeK9b6bQPP3ZPaqiMy7_d9Fxnb3i2Oo4XQPmrTpDkHbMovslBfBoJW4RSpXo3cn0QqcCDG2KfFS8HIYr68jXnyx7Ws3MeswdyEFSqx-XWmZa"
|
|
||||||
},
|
|
||||||
"Connection": {
|
|
||||||
"ClientId": "53f4d5da-93a9-4584-82f9-b8fdf243b002",
|
|
||||||
"ClientSecret": "blouh",
|
|
||||||
"Authority": "localhost",
|
|
||||||
"Audience": "localhost",
|
|
||||||
"SiteAccessSheme": "http",
|
|
||||||
"Port": 5000,
|
|
||||||
"Scope": "profile"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue