mirror of
https://github.com/DuendeSoftware/products
synced 2026-05-24 09:28:24 +00:00
Merge pull request #2306 from DuendeSoftware/mb/templates
Update templates to .NET 10 and latest IdentityServer 7.4.x
This commit is contained in:
commit
91d2565cb2
102 changed files with 302 additions and 397 deletions
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>IdentityServerTemplate</RootNamespace>
|
||||
|
|
@ -12,13 +12,13 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework" version="7.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.6" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework" version="7.4.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.6">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@
|
|||
Admin Dashboard
|
||||
</h1>
|
||||
<span class="text-muted">
|
||||
Get a high-level overview of your Duende IdentityServer instance.
|
||||
Click <a href="/.well-known/openid-configuration" target="_blank">here</a> to access the Discovery Document.
|
||||
Get a high-level overview of your Duende IdentityServer instance.<br/>
|
||||
Click <a href="/.well-known/openid-configuration" target="_blank">here</a> to access the Discovery Document.<br/>
|
||||
<a asp-page-handler="Diagnostics">Download diagnostics data</a>
|
||||
</span>
|
||||
</header>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<h2 class="my-3">System Information</h2>
|
||||
|
|
@ -55,10 +55,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
|
||||
<h2 class="my-3">License Usage</h2>
|
||||
<vc:license-summary></vc:license-summary>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,23 @@
|
|||
using System.Reflection;
|
||||
using Duende.IdentityServer;
|
||||
using Duende.IdentityServer.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerTemplate.Pages.Admin;
|
||||
|
||||
[Authorize(Config.Policies.Admin)]
|
||||
public class Index(IdentityServerLicense? license = null) : PageModel
|
||||
public class Index(DiagnosticDataService? diagnosticDataService = null) : PageModel
|
||||
{
|
||||
public string Version => typeof(Duende.IdentityServer.Hosting.IdentityServerMiddleware).Assembly
|
||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
|
||||
?.InformationalVersion.Split('+').First()
|
||||
?? "unavailable";
|
||||
public async Task<IActionResult> OnGetDiagnostics()
|
||||
{
|
||||
if (diagnosticDataService == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
public IdentityServerLicense? License { get; } = license;
|
||||
var diagnosticsJson = await diagnosticDataService.GetJsonStringAsync();
|
||||
|
||||
Response.Headers.ContentDisposition = "attachment; filename=diagnostics.json";
|
||||
return Content(diagnosticsJson, "application/json");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.Buffers.Text;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Duende.IdentityModel;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace IdentityServerTemplate.Pages.Diagnostics;
|
||||
|
|
@ -15,7 +15,7 @@ public class ViewModel
|
|||
{
|
||||
if (encoded != null)
|
||||
{
|
||||
var bytes = Base64Url.Decode(encoded);
|
||||
var bytes = Base64Url.DecodeFromChars(encoded);
|
||||
var value = Encoding.UTF8.GetString(bytes);
|
||||
Clients = JsonSerializer.Deserialize<string[]>(value) ?? Enumerable.Empty<string>();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Duende.IdentityServer.Models;
|
||||
|
||||
namespace IdentityServerAspNetIdentity;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
public static class Config
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||
using Serilog;
|
||||
using Serilog.Filters;
|
||||
|
||||
namespace IdentityServerAspNetIdentity;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
internal static class HostingExtensions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>IdentityServerHost</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer.AspNetIdentity" version="7.3.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.11" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer.AspNetIdentity" version="7.4.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Login.Index
|
||||
@model IdentityServerHost.Pages.Account.Login.Index
|
||||
|
||||
<div class="login-page">
|
||||
<div class="lead">
|
||||
|
|
@ -86,4 +86,4 @@
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Identity;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public class InputModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public static class LoginOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public class ViewModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Logout.Index
|
||||
@model IdentityServerHost.Pages.Account.Logout.Index
|
||||
|
||||
<div class="logout-page">
|
||||
<div class="lead">
|
||||
|
|
@ -14,4 +14,4 @@
|
|||
<button class="btn btn-primary">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Identity;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Logout.LoggedOut
|
||||
@model IdentityServerHost.Pages.Account.Logout.LoggedOut
|
||||
|
||||
<div class="logged-out-page">
|
||||
<h1>
|
||||
|
|
@ -27,4 +27,4 @@
|
|||
{
|
||||
<script src="~/js/signout-redirect.js"></script>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using Duende.IdentityServer.Services;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
public class LoggedOutViewModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
public static class LogoutOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.Buffers.Text;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Duende.IdentityModel;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace IdentityServerHost.Pages.Diagnostics;
|
||||
|
|
@ -15,7 +15,7 @@ public class ViewModel
|
|||
{
|
||||
if (encoded != null)
|
||||
{
|
||||
var bytes = Base64Url.Decode(encoded);
|
||||
var bytes = Base64Url.DecodeFromChars(encoded);
|
||||
var value = Encoding.UTF8.GetString(bytes);
|
||||
Clients = JsonSerializer.Deserialize<string[]>(value) ?? Enumerable.Empty<string>();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public class Index : PageModel
|
|||
|
||||
public async Task OnGet(string? errorId)
|
||||
{
|
||||
// retrieve error details from identityserver
|
||||
// retrieve error details from IdentityServer
|
||||
var message = await _interaction.GetErrorContextAsync(errorId);
|
||||
if (message != null)
|
||||
{
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Home.Index
|
||||
@model IdentityServerHost.Pages.Index
|
||||
|
||||
<div class="welcome-page">
|
||||
<h1>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Duende.IdentityServer;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Home;
|
||||
namespace IdentityServerHost.Pages;
|
||||
|
||||
[AllowAnonymous]
|
||||
public class Index : PageModel
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
@using IdentityServerHost.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Duende.IdentityServer.Licensing;
|
||||
using IdentityServerAspNetIdentity;
|
||||
using IdentityServerHost;
|
||||
using Serilog;
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Identity;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Serilog;
|
||||
|
||||
namespace IdentityServerAspNetIdentity;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
public class SeedData
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,5 +21,15 @@
|
|||
{
|
||||
"path": "IdentityServerEmpty.csproj"
|
||||
}
|
||||
]
|
||||
],
|
||||
"symbols": {
|
||||
"RenameCommonNamespace": {
|
||||
"datatype": "string",
|
||||
"displayName": "Fix common host namespace.",
|
||||
"replaces": "IdentityServerHost",
|
||||
"type": "derived",
|
||||
"valueSource": "name",
|
||||
"valueTransform": "safe_namespace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Duende.IdentityServer.Models;
|
||||
|
||||
namespace IdentityServerEmpty;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
public static class Config
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System.Globalization;
|
|||
using Serilog;
|
||||
using Serilog.Filters;
|
||||
|
||||
namespace IdentityServerEmpty;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
internal static class HostingExtensions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>IdentityServerHost</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer" version="7.3.0" />
|
||||
<PackageReference Include="Duende.IdentityServer" version="7.4.3" />
|
||||
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Duende.IdentityServer.Licensing;
|
||||
using IdentityServerEmpty;
|
||||
using IdentityServerHost;
|
||||
using Serilog;
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Duende.IdentityServer.Models;
|
||||
|
||||
namespace IdentityServerEntityFramework;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
public static class Config
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.Globalization;
|
||||
using Duende.IdentityServer;
|
||||
using IdentityServerHost;
|
||||
using IdentityServerHost.Pages;
|
||||
using IdentityServerHost.Pages.Admin.ApiScopes;
|
||||
using IdentityServerHost.Pages.Admin.Clients;
|
||||
using IdentityServerHost.Pages.Admin.IdentityScopes;
|
||||
|
|
@ -10,7 +10,7 @@ using Microsoft.IdentityModel.Tokens;
|
|||
using Serilog;
|
||||
using Serilog.Filters;
|
||||
|
||||
namespace IdentityServerEntityFramework;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
internal static class HostingExtensions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>IdentityServerHost</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework" version="7.3.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
<PackageReference Include="Duende.IdentityServer.EntityFramework" version="7.4.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore"
|
||||
Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.11" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
|
||||
#nullable disable
|
||||
|
||||
using Duende.IdentityServer.EntityFramework.DbContexts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace IdentityServerEntityFramework.Migrations.ConfigurationDb
|
||||
namespace IdentityServerHost.Migrations.ConfigurationDb
|
||||
{
|
||||
[DbContext(typeof(ConfigurationDbContext))]
|
||||
[Migration("20240123193245_Configuration")]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace IdentityServerEntityFramework.Migrations.ConfigurationDb;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace IdentityServerHost.Migrations.ConfigurationDb;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class Configuration : Migration
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
|
||||
#nullable disable
|
||||
|
||||
using Duende.IdentityServer.EntityFramework.DbContexts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace IdentityServerEntityFramework.Migrations.PersistedGrantDb
|
||||
namespace IdentityServerHost.Migrations.PersistedGrantDb
|
||||
{
|
||||
[DbContext(typeof(PersistedGrantDbContext))]
|
||||
[Migration("20240123193240_Grants")]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace IdentityServerEntityFramework.Migrations.PersistedGrantDb;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace IdentityServerHost.Migrations.PersistedGrantDb;
|
||||
|
||||
/// <inheritdoc />
|
||||
public partial class Grants : Migration
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Create.Index
|
||||
@model IdentityServerHost.Pages.Account.Create.Index
|
||||
|
||||
<div class="login-page">
|
||||
<div class="lead">
|
||||
|
|
@ -37,4 +37,4 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Create;
|
||||
namespace IdentityServerHost.Pages.Account.Create;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IdentityServerHost.Pages.Create;
|
||||
namespace IdentityServerHost.Pages.Account.Create;
|
||||
|
||||
public class InputModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Login.Index
|
||||
@model IdentityServerHost.Pages.Account.Login.Index
|
||||
|
||||
<div class="login-page">
|
||||
<div class="lead">
|
||||
|
|
@ -86,4 +86,4 @@
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public class InputModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public static class LoginOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public class ViewModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Logout.Index
|
||||
@model IdentityServerHost.Pages.Account.Logout.Index
|
||||
|
||||
<div class="logout-page">
|
||||
<div class="lead">
|
||||
|
|
@ -14,4 +14,4 @@
|
|||
<button class="btn btn-primary">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Logout.LoggedOut
|
||||
@model IdentityServerHost.Pages.Account.Logout.LoggedOut
|
||||
|
||||
<div class="logged-out-page">
|
||||
<h1>
|
||||
|
|
@ -27,4 +27,4 @@
|
|||
{
|
||||
<script src="~/js/signout-redirect.js"></script>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using Duende.IdentityServer.Services;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
public class LoggedOutViewModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
public static class LogoutOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.Buffers.Text;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Duende.IdentityModel;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace IdentityServerHost.Pages.Diagnostics;
|
||||
|
|
@ -11,11 +11,11 @@ public class ViewModel
|
|||
{
|
||||
AuthenticateResult = result;
|
||||
|
||||
if (result?.Properties?.Items.TryGetValue("client_list", out var encoded) == true)
|
||||
if (result.Properties?.Items.TryGetValue("client_list", out var encoded) == true)
|
||||
{
|
||||
if (encoded != null)
|
||||
{
|
||||
var bytes = Base64Url.Decode(encoded);
|
||||
var bytes = Base64Url.DecodeFromChars(encoded);
|
||||
var value = Encoding.UTF8.GetString(bytes);
|
||||
Clients = JsonSerializer.Deserialize<string[]>(value) ?? Enumerable.Empty<string>();
|
||||
return;
|
||||
|
|
@ -25,5 +25,6 @@ public class ViewModel
|
|||
}
|
||||
|
||||
public AuthenticateResult AuthenticateResult { get; }
|
||||
|
||||
public IEnumerable<string> Clients { get; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Home.Index
|
||||
@model IdentityServerHost.Pages.Index
|
||||
|
||||
<div class="welcome-page">
|
||||
<h1>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using Duende.IdentityServer;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Home;
|
||||
namespace IdentityServerHost.Pages;
|
||||
|
||||
[AllowAnonymous]
|
||||
public class Index : PageModel
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Duende.IdentityModel;
|
|||
using Duende.IdentityServer;
|
||||
using Duende.IdentityServer.Test;
|
||||
|
||||
namespace IdentityServerHost;
|
||||
namespace IdentityServerHost.Pages;
|
||||
|
||||
public static class TestUsers
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
@using IdentityServerHost.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Duende.IdentityServer.Licensing;
|
||||
using IdentityServerEntityFramework;
|
||||
using IdentityServerHost;
|
||||
using Serilog;
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Duende.IdentityServer.Models;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Serilog;
|
||||
|
||||
namespace IdentityServerEntityFramework;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
public class SeedData
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using Duende.IdentityServer.Models;
|
||||
|
||||
namespace IdentityServerInMem;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
public static class Config
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
using System.Globalization;
|
||||
using Duende.IdentityServer;
|
||||
using IdentityServerHost;
|
||||
using IdentityServerHost.Pages;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Serilog;
|
||||
using Serilog.Filters;
|
||||
|
||||
namespace IdentityServerInMem;
|
||||
namespace IdentityServerHost;
|
||||
|
||||
internal static class HostingExtensions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>IdentityServerHost</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer" version="7.3.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
|
||||
<PackageReference Include="Duende.IdentityServer" version="7.4.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Create.Index
|
||||
@model IdentityServerHost.Pages.Account.Create.Index
|
||||
|
||||
<div class="login-page">
|
||||
<div class="lead">
|
||||
|
|
@ -37,4 +37,4 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,27 +6,21 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Create;
|
||||
namespace IdentityServerHost.Pages.Account.Create;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
public class Index : PageModel
|
||||
public class Index(
|
||||
IIdentityServerInteractionService interaction,
|
||||
TestUserStore? users = null)
|
||||
: PageModel
|
||||
{
|
||||
private readonly TestUserStore _users;
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly TestUserStore _users = users ?? throw new InvalidOperationException("Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.");
|
||||
|
||||
[BindProperty]
|
||||
public InputModel Input { get; set; } = default!;
|
||||
|
||||
public Index(
|
||||
IIdentityServerInteractionService interaction,
|
||||
TestUserStore? users = null)
|
||||
{
|
||||
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
|
||||
_users = users ?? throw new InvalidOperationException("Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.");
|
||||
|
||||
_interaction = interaction;
|
||||
}
|
||||
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
|
||||
|
||||
public IActionResult OnGet(string? returnUrl)
|
||||
{
|
||||
|
|
@ -37,7 +31,7 @@ public class Index : PageModel
|
|||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
// check if we are in the context of an authorization request
|
||||
var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);
|
||||
var context = await interaction.GetAuthorizationContextAsync(Input.ReturnUrl);
|
||||
|
||||
// the user clicked the "cancel" button
|
||||
if (Input.Button != "create")
|
||||
|
|
@ -47,7 +41,7 @@ public class Index : PageModel
|
|||
// if the user cancels, send a result back into IdentityServer as if they
|
||||
// denied the consent (even if this client does not require consent).
|
||||
// this will send back an access denied OIDC error response to the client.
|
||||
await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);
|
||||
await interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);
|
||||
|
||||
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
|
||||
if (context.IsNativeClient())
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IdentityServerHost.Pages.Create;
|
||||
namespace IdentityServerHost.Pages.Account.Create;
|
||||
|
||||
public class InputModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Login.Index
|
||||
@model IdentityServerHost.Pages.Account.Login.Index
|
||||
|
||||
<div class="login-page">
|
||||
<div class="lead">
|
||||
|
|
@ -86,4 +86,4 @@
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,38 +9,26 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
public class Index : PageModel
|
||||
public class Index(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IAuthenticationSchemeProvider schemeProvider,
|
||||
IIdentityProviderStore identityProviderStore,
|
||||
IEventService events,
|
||||
TestUserStore? users = null)
|
||||
: PageModel
|
||||
{
|
||||
private readonly TestUserStore _users;
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly IEventService _events;
|
||||
private readonly IAuthenticationSchemeProvider _schemeProvider;
|
||||
private readonly IIdentityProviderStore _identityProviderStore;
|
||||
private readonly TestUserStore _users = users ?? throw new InvalidOperationException("Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.");
|
||||
|
||||
public ViewModel View { get; set; } = default!;
|
||||
|
||||
[BindProperty]
|
||||
public InputModel Input { get; set; } = default!;
|
||||
|
||||
public Index(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IAuthenticationSchemeProvider schemeProvider,
|
||||
IIdentityProviderStore identityProviderStore,
|
||||
IEventService events,
|
||||
TestUserStore? users = null)
|
||||
{
|
||||
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
|
||||
_users = users ?? throw new InvalidOperationException("Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.");
|
||||
|
||||
_interaction = interaction;
|
||||
_schemeProvider = schemeProvider;
|
||||
_identityProviderStore = identityProviderStore;
|
||||
_events = events;
|
||||
}
|
||||
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
|
||||
|
||||
public async Task<IActionResult> OnGet(string? returnUrl)
|
||||
{
|
||||
|
|
@ -58,7 +46,7 @@ public class Index : PageModel
|
|||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
// check if we are in the context of an authorization request
|
||||
var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);
|
||||
var context = await interaction.GetAuthorizationContextAsync(Input.ReturnUrl);
|
||||
|
||||
// the user clicked the "cancel" button
|
||||
if (Input.Button != "login")
|
||||
|
|
@ -71,7 +59,7 @@ public class Index : PageModel
|
|||
// if the user cancels, send a result back into IdentityServer as if they
|
||||
// denied the consent (even if this client does not require consent).
|
||||
// this will send back an access denied OIDC error response to the client.
|
||||
await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);
|
||||
await interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);
|
||||
|
||||
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
|
||||
if (context.IsNativeClient())
|
||||
|
|
@ -96,7 +84,7 @@ public class Index : PageModel
|
|||
if (_users.ValidateCredentials(Input.Username, Input.Password))
|
||||
{
|
||||
var user = _users.FindByUsername(Input.Username);
|
||||
await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username, clientId: context?.Client.ClientId));
|
||||
await events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username, clientId: context?.Client.ClientId));
|
||||
Telemetry.Metrics.UserLogin(context?.Client.ClientId, IdentityServerConstants.LocalIdentityProvider);
|
||||
|
||||
// only set explicit expiration here if user chooses "remember me".
|
||||
|
|
@ -149,7 +137,7 @@ public class Index : PageModel
|
|||
}
|
||||
|
||||
const string error = "invalid credentials";
|
||||
await _events.RaiseAsync(new UserLoginFailureEvent(Input.Username, error, clientId: context?.Client.ClientId));
|
||||
await events.RaiseAsync(new UserLoginFailureEvent(Input.Username, error, clientId: context?.Client.ClientId));
|
||||
Telemetry.Metrics.UserLoginFailure(context?.Client.ClientId, IdentityServerConstants.LocalIdentityProvider, error);
|
||||
ModelState.AddModelError(string.Empty, LoginOptions.InvalidCredentialsErrorMessage);
|
||||
}
|
||||
|
|
@ -166,10 +154,10 @@ public class Index : PageModel
|
|||
ReturnUrl = returnUrl
|
||||
};
|
||||
|
||||
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
|
||||
var context = await interaction.GetAuthorizationContextAsync(returnUrl);
|
||||
if (context?.IdP != null)
|
||||
{
|
||||
var scheme = await _schemeProvider.GetSchemeAsync(context.IdP);
|
||||
var scheme = await schemeProvider.GetSchemeAsync(context.IdP);
|
||||
if (scheme != null)
|
||||
{
|
||||
var local = context.IdP == Duende.IdentityServer.IdentityServerConstants.LocalIdentityProvider;
|
||||
|
|
@ -191,7 +179,7 @@ public class Index : PageModel
|
|||
return;
|
||||
}
|
||||
|
||||
var schemes = await _schemeProvider.GetAllSchemesAsync();
|
||||
var schemes = await schemeProvider.GetAllSchemesAsync();
|
||||
|
||||
var providers = schemes
|
||||
.Where(x => x.DisplayName != null)
|
||||
|
|
@ -201,7 +189,7 @@ public class Index : PageModel
|
|||
displayName: x.DisplayName ?? x.Name
|
||||
)).ToList();
|
||||
|
||||
var dynamicSchemes = (await _identityProviderStore.GetAllSchemeNamesAsync())
|
||||
var dynamicSchemes = (await identityProviderStore.GetAllSchemeNamesAsync())
|
||||
.Where(x => x.Enabled)
|
||||
.Select(x => new ViewModel.ExternalProvider
|
||||
(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public class InputModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public static class LoginOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Login;
|
||||
namespace IdentityServerHost.Pages.Account.Login;
|
||||
|
||||
public class ViewModel
|
||||
{
|
||||
|
|
@ -11,15 +11,9 @@ public class ViewModel
|
|||
public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;
|
||||
public string? ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
|
||||
|
||||
public class ExternalProvider
|
||||
public class ExternalProvider(string authenticationScheme, string? displayName = null)
|
||||
{
|
||||
public ExternalProvider(string authenticationScheme, string? displayName = null)
|
||||
{
|
||||
AuthenticationScheme = authenticationScheme;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
public string? DisplayName { get; set; }
|
||||
public string AuthenticationScheme { get; set; }
|
||||
public string? DisplayName { get; set; } = displayName;
|
||||
public string AuthenticationScheme { get; set; } = authenticationScheme;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Logout.Index
|
||||
@model IdentityServerHost.Pages.Account.Logout.Index
|
||||
|
||||
<div class="logout-page">
|
||||
<div class="lead">
|
||||
|
|
@ -14,4 +14,4 @@
|
|||
<button class="btn btn-primary">Yes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,24 +7,16 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
public class Index : PageModel
|
||||
public class Index(IIdentityServerInteractionService interaction, IEventService events)
|
||||
: PageModel
|
||||
{
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly IEventService _events;
|
||||
|
||||
[BindProperty]
|
||||
public string? LogoutId { get; set; }
|
||||
|
||||
public Index(IIdentityServerInteractionService interaction, IEventService events)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_events = events;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGet(string? logoutId)
|
||||
{
|
||||
LogoutId = logoutId;
|
||||
|
|
@ -38,7 +30,7 @@ public class Index : PageModel
|
|||
}
|
||||
else
|
||||
{
|
||||
var context = await _interaction.GetLogoutContextAsync(LogoutId);
|
||||
var context = await interaction.GetLogoutContextAsync(LogoutId);
|
||||
if (context?.ShowSignoutPrompt == false)
|
||||
{
|
||||
// it's safe to automatically sign-out
|
||||
|
|
@ -63,7 +55,7 @@ public class Index : PageModel
|
|||
// if there's no current logout context, we need to create one
|
||||
// this captures necessary info from the current logged in user
|
||||
// this can still return null if there is no context needed
|
||||
LogoutId ??= await _interaction.CreateLogoutContextAsync();
|
||||
LogoutId ??= await interaction.CreateLogoutContextAsync();
|
||||
|
||||
// delete local authentication cookie
|
||||
await HttpContext.SignOutAsync();
|
||||
|
|
@ -72,7 +64,7 @@ public class Index : PageModel
|
|||
var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value;
|
||||
|
||||
// raise the logout event
|
||||
await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
|
||||
await events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName()));
|
||||
Telemetry.Metrics.UserLogout(idp);
|
||||
|
||||
// if it's a local login we can ignore this workflow
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Logout.LoggedOut
|
||||
@model IdentityServerHost.Pages.Account.Logout.LoggedOut
|
||||
|
||||
<div class="logged-out-page">
|
||||
<h1>
|
||||
|
|
@ -27,4 +27,4 @@
|
|||
{
|
||||
<script src="~/js/signout-redirect.js"></script>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,18 @@ using Duende.IdentityServer.Services;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
[SecurityHeaders]
|
||||
[AllowAnonymous]
|
||||
public class LoggedOut : PageModel
|
||||
public class LoggedOut(IIdentityServerInteractionService interactionService) : PageModel
|
||||
{
|
||||
private readonly IIdentityServerInteractionService _interactionService;
|
||||
|
||||
public LoggedOutViewModel View { get; set; } = default!;
|
||||
|
||||
public LoggedOut(IIdentityServerInteractionService interactionService) => _interactionService = interactionService;
|
||||
|
||||
public async Task OnGet(string? logoutId)
|
||||
{
|
||||
// get context information (client name, post logout redirect URI and iframe for federated signout)
|
||||
var logout = await _interactionService.GetLogoutContextAsync(logoutId);
|
||||
var logout = await interactionService.GetLogoutContextAsync(logoutId);
|
||||
|
||||
View = new LoggedOutViewModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
public class LoggedOutViewModel
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
namespace IdentityServerHost.Pages.Logout;
|
||||
namespace IdentityServerHost.Pages.Account.Logout;
|
||||
|
||||
public static class LogoutOptions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,13 +7,10 @@ namespace IdentityServerHost.Pages.Ciba;
|
|||
|
||||
[SecurityHeaders]
|
||||
[Authorize]
|
||||
public class AllModel : PageModel
|
||||
public class AllModel(IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService)
|
||||
: PageModel
|
||||
{
|
||||
public IEnumerable<BackchannelUserLoginRequest> Logins { get; set; } = default!;
|
||||
|
||||
private readonly IBackchannelAuthenticationInteractionService _backchannelAuthenticationInteraction;
|
||||
|
||||
public AllModel(IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService) => _backchannelAuthenticationInteraction = backchannelAuthenticationInteractionService;
|
||||
|
||||
public async Task OnGet() => Logins = await _backchannelAuthenticationInteraction.GetPendingLoginRequestsForCurrentUserAsync();
|
||||
public async Task OnGet() => Logins = await backchannelAuthenticationInteractionService.GetPendingLoginRequestsForCurrentUserAsync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,22 +11,12 @@ namespace IdentityServerHost.Pages.Ciba;
|
|||
|
||||
[Authorize]
|
||||
[SecurityHeaders]
|
||||
public class Consent : PageModel
|
||||
public class Consent(
|
||||
IBackchannelAuthenticationInteractionService interaction,
|
||||
IEventService events,
|
||||
ILogger<Consent> logger)
|
||||
: PageModel
|
||||
{
|
||||
private readonly IBackchannelAuthenticationInteractionService _interaction;
|
||||
private readonly IEventService _events;
|
||||
private readonly ILogger<Consent> _logger;
|
||||
|
||||
public Consent(
|
||||
IBackchannelAuthenticationInteractionService interaction,
|
||||
IEventService events,
|
||||
ILogger<Consent> logger)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_events = events;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public ViewModel View { get; set; } = default!;
|
||||
|
||||
[BindProperty]
|
||||
|
|
@ -50,10 +40,10 @@ public class Consent : PageModel
|
|||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
// validate return url is still valid
|
||||
var request = await _interaction.GetLoginRequestByInternalIdAsync(Input.Id ?? throw new ArgumentNullException(nameof(Input.Id)));
|
||||
var request = await interaction.GetLoginRequestByInternalIdAsync(Input.Id ?? throw new ArgumentNullException(nameof(Input.Id)));
|
||||
if (request == null || request.Subject.GetSubjectId() != User.GetSubjectId())
|
||||
{
|
||||
_logger.InvalidId(Input.Id);
|
||||
logger.InvalidId(Input.Id);
|
||||
return RedirectToPage("/Home/Error/Index");
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +55,7 @@ public class Consent : PageModel
|
|||
result = new CompleteBackchannelLoginRequest(Input.Id);
|
||||
|
||||
// emit event
|
||||
await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
|
||||
await events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
|
||||
Telemetry.Metrics.ConsentDenied(request.Client.ClientId, request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName));
|
||||
}
|
||||
// user clicked 'yes' - validate the data
|
||||
|
|
@ -87,7 +77,7 @@ public class Consent : PageModel
|
|||
};
|
||||
|
||||
// emit event
|
||||
await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, result.ScopesValuesConsented, false));
|
||||
await events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, result.ScopesValuesConsented, false));
|
||||
Telemetry.Metrics.ConsentGranted(request.Client.ClientId, result.ScopesValuesConsented, false);
|
||||
var denied = request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName).Except(result.ScopesValuesConsented);
|
||||
Telemetry.Metrics.ConsentDenied(request.Client.ClientId, denied);
|
||||
|
|
@ -105,7 +95,7 @@ public class Consent : PageModel
|
|||
if (result != null)
|
||||
{
|
||||
// communicate outcome of consent back to identityserver
|
||||
await _interaction.CompleteLoginRequestAsync(result);
|
||||
await interaction.CompleteLoginRequestAsync(result);
|
||||
|
||||
return RedirectToPage("/Ciba/All");
|
||||
}
|
||||
|
|
@ -122,7 +112,7 @@ public class Consent : PageModel
|
|||
{
|
||||
ArgumentNullException.ThrowIfNull(id);
|
||||
|
||||
var request = await _interaction.GetLoginRequestByInternalIdAsync(id);
|
||||
var request = await interaction.GetLoginRequestByInternalIdAsync(id);
|
||||
if (request != null && request.Subject.GetSubjectId() == User.GetSubjectId())
|
||||
{
|
||||
View = CreateConsentViewModel(request);
|
||||
|
|
@ -130,7 +120,7 @@ public class Consent : PageModel
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.NoMatchingBackchannelLoginRequest(id);
|
||||
logger.NoMatchingBackchannelLoginRequest(id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,25 +8,19 @@ namespace IdentityServerHost.Pages.Ciba;
|
|||
|
||||
[AllowAnonymous]
|
||||
[SecurityHeaders]
|
||||
public class IndexModel : PageModel
|
||||
public class IndexModel(
|
||||
IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService,
|
||||
ILogger<IndexModel> logger)
|
||||
: PageModel
|
||||
{
|
||||
public BackchannelUserLoginRequest LoginRequest { get; set; } = default!;
|
||||
|
||||
private readonly IBackchannelAuthenticationInteractionService _backchannelAuthenticationInteraction;
|
||||
private readonly ILogger<IndexModel> _logger;
|
||||
|
||||
public IndexModel(IBackchannelAuthenticationInteractionService backchannelAuthenticationInteractionService, ILogger<IndexModel> logger)
|
||||
{
|
||||
_backchannelAuthenticationInteraction = backchannelAuthenticationInteractionService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnGet(string id)
|
||||
{
|
||||
var result = await _backchannelAuthenticationInteraction.GetLoginRequestByInternalIdAsync(id);
|
||||
var result = await backchannelAuthenticationInteractionService.GetLoginRequestByInternalIdAsync(id);
|
||||
if (result == null)
|
||||
{
|
||||
_logger.InvalidBackchannelLoginId(id);
|
||||
logger.InvalidBackchannelLoginId(id);
|
||||
return RedirectToPage("/Home/Error/Index");
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -12,22 +12,12 @@ namespace IdentityServerHost.Pages.Consent;
|
|||
|
||||
[Authorize]
|
||||
[SecurityHeaders]
|
||||
public class Index : PageModel
|
||||
public class Index(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IEventService events,
|
||||
ILogger<Index> logger)
|
||||
: PageModel
|
||||
{
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly IEventService _events;
|
||||
private readonly ILogger<Index> _logger;
|
||||
|
||||
public Index(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IEventService events,
|
||||
ILogger<Index> logger)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_events = events;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public ViewModel View { get; set; } = default!;
|
||||
|
||||
[BindProperty]
|
||||
|
|
@ -51,7 +41,7 @@ public class Index : PageModel
|
|||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
// validate return url is still valid
|
||||
var request = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl);
|
||||
var request = await interaction.GetAuthorizationContextAsync(Input.ReturnUrl);
|
||||
if (request == null)
|
||||
{
|
||||
return RedirectToPage("/Home/Error/Index");
|
||||
|
|
@ -65,7 +55,7 @@ public class Index : PageModel
|
|||
grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied };
|
||||
|
||||
// emit event
|
||||
await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
|
||||
await events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
|
||||
Telemetry.Metrics.ConsentDenied(request.Client.ClientId, request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName));
|
||||
}
|
||||
// user clicked 'yes' - validate the data
|
||||
|
|
@ -88,7 +78,7 @@ public class Index : PageModel
|
|||
};
|
||||
|
||||
// emit event
|
||||
await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
|
||||
await events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
|
||||
Telemetry.Metrics.ConsentGranted(request.Client.ClientId, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent);
|
||||
var denied = request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName).Except(grantedConsent.ScopesValuesConsented);
|
||||
Telemetry.Metrics.ConsentDenied(request.Client.ClientId, denied);
|
||||
|
|
@ -108,7 +98,7 @@ public class Index : PageModel
|
|||
ArgumentNullException.ThrowIfNull(Input.ReturnUrl, nameof(Input.ReturnUrl));
|
||||
|
||||
// communicate outcome of consent back to identityserver
|
||||
await _interaction.GrantConsentAsync(request, grantedConsent);
|
||||
await interaction.GrantConsentAsync(request, grantedConsent);
|
||||
|
||||
// redirect back to authorization endpoint
|
||||
if (request.IsNativeClient() == true)
|
||||
|
|
@ -133,7 +123,7 @@ public class Index : PageModel
|
|||
{
|
||||
ArgumentNullException.ThrowIfNull(returnUrl);
|
||||
|
||||
var request = await _interaction.GetAuthorizationContextAsync(returnUrl);
|
||||
var request = await interaction.GetAuthorizationContextAsync(returnUrl);
|
||||
if (request != null)
|
||||
{
|
||||
View = CreateConsentViewModel(request);
|
||||
|
|
@ -141,7 +131,7 @@ public class Index : PageModel
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.NoConsentMatchingRequest(returnUrl);
|
||||
logger.NoConsentMatchingRequest(returnUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,21 +14,13 @@ namespace IdentityServerHost.Pages.Device;
|
|||
|
||||
[SecurityHeaders]
|
||||
[Authorize]
|
||||
public class Index : PageModel
|
||||
public class Index(
|
||||
IDeviceFlowInteractionService interaction,
|
||||
IEventService eventService,
|
||||
IOptions<IdentityServerOptions> options)
|
||||
: PageModel
|
||||
{
|
||||
private readonly IDeviceFlowInteractionService _interaction;
|
||||
private readonly IEventService _events;
|
||||
private readonly IOptions<IdentityServerOptions> _options;
|
||||
|
||||
public Index(
|
||||
IDeviceFlowInteractionService interaction,
|
||||
IEventService eventService,
|
||||
IOptions<IdentityServerOptions> options)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_events = eventService;
|
||||
_options = options;
|
||||
}
|
||||
private readonly IOptions<IdentityServerOptions> _options = options;
|
||||
|
||||
public ViewModel View { get; set; } = default!;
|
||||
|
||||
|
|
@ -58,7 +50,7 @@ public class Index : PageModel
|
|||
|
||||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
var request = await _interaction.GetAuthorizationContextAsync(Input.UserCode ?? throw new ArgumentNullException(nameof(Input.UserCode)));
|
||||
var request = await interaction.GetAuthorizationContextAsync(Input.UserCode ?? throw new ArgumentNullException(nameof(Input.UserCode)));
|
||||
if (request == null)
|
||||
{
|
||||
return RedirectToPage("/Home/Error/Index");
|
||||
|
|
@ -75,7 +67,7 @@ public class Index : PageModel
|
|||
};
|
||||
|
||||
// emit event
|
||||
await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
|
||||
await eventService.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues));
|
||||
Telemetry.Metrics.ConsentDenied(request.Client.ClientId, request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName));
|
||||
}
|
||||
// user clicked 'yes' - validate the data
|
||||
|
|
@ -98,7 +90,7 @@ public class Index : PageModel
|
|||
};
|
||||
|
||||
// emit event
|
||||
await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
|
||||
await eventService.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent));
|
||||
Telemetry.Metrics.ConsentGranted(request.Client.ClientId, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent);
|
||||
var denied = request.ValidatedResources.ParsedScopes.Select(s => s.ParsedName).Except(grantedConsent.ScopesValuesConsented);
|
||||
Telemetry.Metrics.ConsentDenied(request.Client.ClientId, denied);
|
||||
|
|
@ -116,7 +108,7 @@ public class Index : PageModel
|
|||
if (grantedConsent != null)
|
||||
{
|
||||
// communicate outcome of consent back to identityserver
|
||||
await _interaction.HandleRequestAsync(Input.UserCode, grantedConsent);
|
||||
await interaction.HandleRequestAsync(Input.UserCode, grantedConsent);
|
||||
|
||||
// indicate that's it ok to redirect back to authorization endpoint
|
||||
return RedirectToPage("/Device/Success");
|
||||
|
|
@ -133,7 +125,7 @@ public class Index : PageModel
|
|||
|
||||
private async Task<bool> SetViewModelAsync(string userCode)
|
||||
{
|
||||
var request = await _interaction.GetAuthorizationContextAsync(userCode);
|
||||
var request = await interaction.GetAuthorizationContextAsync(userCode);
|
||||
if (request != null)
|
||||
{
|
||||
View = CreateConsentViewModel(request);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System.Buffers.Text;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Duende.IdentityModel;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace IdentityServerHost.Pages.Diagnostics;
|
||||
|
|
@ -15,7 +15,7 @@ public class ViewModel
|
|||
{
|
||||
if (encoded != null)
|
||||
{
|
||||
var bytes = Base64Url.Decode(encoded);
|
||||
var bytes = Base64Url.DecodeFromChars(encoded);
|
||||
var value = Encoding.UTF8.GetString(bytes);
|
||||
Clients = JsonSerializer.Deserialize<string[]>(value) ?? Enumerable.Empty<string>();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -6,28 +6,20 @@ namespace IdentityServerHost.Pages.Error;
|
|||
|
||||
[AllowAnonymous]
|
||||
[SecurityHeaders]
|
||||
public class Index : PageModel
|
||||
public class Index(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)
|
||||
: PageModel
|
||||
{
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
|
||||
public ViewModel View { get; set; } = new();
|
||||
|
||||
public Index(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_environment = environment;
|
||||
}
|
||||
|
||||
public async Task OnGet(string? errorId)
|
||||
{
|
||||
// retrieve error details from identityserver
|
||||
var message = await _interaction.GetErrorContextAsync(errorId);
|
||||
// retrieve error details from IdentityServer
|
||||
var message = await interaction.GetErrorContextAsync(errorId);
|
||||
if (message != null)
|
||||
{
|
||||
View.Error = message;
|
||||
|
||||
if (!_environment.IsDevelopment())
|
||||
if (!environment.IsDevelopment())
|
||||
{
|
||||
// only show in development
|
||||
message.ErrorDescription = null;
|
||||
|
|
@ -13,26 +13,16 @@ namespace IdentityServerHost.Pages.ExternalLogin;
|
|||
|
||||
[AllowAnonymous]
|
||||
[SecurityHeaders]
|
||||
public class Callback : PageModel
|
||||
public class Callback(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IEventService events,
|
||||
ILogger<Callback> logger,
|
||||
TestUserStore? users = null)
|
||||
: PageModel
|
||||
{
|
||||
private readonly TestUserStore _users;
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly ILogger<Callback> _logger;
|
||||
private readonly IEventService _events;
|
||||
private readonly TestUserStore _users = users ?? throw new InvalidOperationException("Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.");
|
||||
|
||||
public Callback(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IEventService events,
|
||||
ILogger<Callback> logger,
|
||||
TestUserStore? users = null)
|
||||
{
|
||||
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
|
||||
_users = users ?? throw new InvalidOperationException("Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController.");
|
||||
|
||||
_interaction = interaction;
|
||||
_logger = logger;
|
||||
_events = events;
|
||||
}
|
||||
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
|
||||
|
||||
public async Task<IActionResult> OnGet()
|
||||
{
|
||||
|
|
@ -46,10 +36,10 @@ public class Callback : PageModel
|
|||
var externalUser = result.Principal ??
|
||||
throw new InvalidOperationException("External authentication produced a null Principal");
|
||||
|
||||
if (_logger.IsEnabled(LogLevel.Debug))
|
||||
if (logger.IsEnabled(LogLevel.Debug))
|
||||
{
|
||||
var externalClaims = externalUser.Claims.Select(c => $"{c.Type}: {c.Value}");
|
||||
_logger.ExternalClaims(externalClaims);
|
||||
logger.ExternalClaims(externalClaims);
|
||||
}
|
||||
|
||||
// lookup our user and external provider info
|
||||
|
|
@ -101,8 +91,8 @@ public class Callback : PageModel
|
|||
var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";
|
||||
|
||||
// check if external login is in the context of an OIDC request
|
||||
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
|
||||
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client.ClientId));
|
||||
var context = await interaction.GetAuthorizationContextAsync(returnUrl);
|
||||
await events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client.ClientId));
|
||||
Telemetry.Metrics.UserLogin(context?.Client.ClientId, provider!);
|
||||
|
||||
if (context != null)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,8 @@ namespace IdentityServerHost.Pages.ExternalLogin;
|
|||
|
||||
[AllowAnonymous]
|
||||
[SecurityHeaders]
|
||||
public class Challenge : PageModel
|
||||
public class Challenge(IIdentityServerInteractionService interactionService) : PageModel
|
||||
{
|
||||
private readonly IIdentityServerInteractionService _interactionService;
|
||||
|
||||
public Challenge(IIdentityServerInteractionService interactionService) => _interactionService = interactionService;
|
||||
|
||||
public IActionResult OnGet(string scheme, string? returnUrl)
|
||||
{
|
||||
if (string.IsNullOrEmpty(returnUrl))
|
||||
|
|
@ -22,7 +18,7 @@ public class Challenge : PageModel
|
|||
}
|
||||
|
||||
// Abort on incorrect returnUrl - it is neither a local url nor a valid OIDC url.
|
||||
if (Url.IsLocalUrl(returnUrl) == false && _interactionService.IsValidReturnUrl(returnUrl) == false)
|
||||
if (Url.IsLocalUrl(returnUrl) == false && interactionService.IsValidReturnUrl(returnUrl) == false)
|
||||
{
|
||||
// user might have clicked on a malicious link - should be logged
|
||||
throw new ArgumentException("invalid return URL");
|
||||
|
|
|
|||
|
|
@ -10,37 +10,26 @@ namespace IdentityServerHost.Pages.Grants;
|
|||
|
||||
[SecurityHeaders]
|
||||
[Authorize]
|
||||
public class Index : PageModel
|
||||
public class Index(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IClientStore clients,
|
||||
IResourceStore resources,
|
||||
IEventService events)
|
||||
: PageModel
|
||||
{
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly IClientStore _clients;
|
||||
private readonly IResourceStore _resources;
|
||||
private readonly IEventService _events;
|
||||
|
||||
public Index(IIdentityServerInteractionService interaction,
|
||||
IClientStore clients,
|
||||
IResourceStore resources,
|
||||
IEventService events)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_clients = clients;
|
||||
_resources = resources;
|
||||
_events = events;
|
||||
}
|
||||
|
||||
public ViewModel View { get; set; } = default!;
|
||||
|
||||
public async Task OnGet()
|
||||
{
|
||||
var grants = await _interaction.GetAllUserGrantsAsync();
|
||||
var grants = await interaction.GetAllUserGrantsAsync();
|
||||
|
||||
var list = new List<GrantViewModel>();
|
||||
foreach (var grant in grants)
|
||||
{
|
||||
var client = await _clients.FindClientByIdAsync(grant.ClientId);
|
||||
var client = await clients.FindClientByIdAsync(grant.ClientId);
|
||||
if (client != null)
|
||||
{
|
||||
var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes);
|
||||
var resources1 = await resources.FindResourcesByScopeAsync(grant.Scopes);
|
||||
|
||||
var item = new GrantViewModel()
|
||||
{
|
||||
|
|
@ -51,8 +40,8 @@ public class Index : PageModel
|
|||
Description = grant.Description,
|
||||
Created = grant.CreationTime,
|
||||
Expires = grant.Expiration,
|
||||
IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(),
|
||||
ApiGrantNames = resources.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray()
|
||||
IdentityGrantNames = resources1.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(),
|
||||
ApiGrantNames = resources1.ApiScopes.Select(x => x.DisplayName ?? x.Name).ToArray()
|
||||
};
|
||||
|
||||
list.Add(item);
|
||||
|
|
@ -70,8 +59,8 @@ public class Index : PageModel
|
|||
|
||||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
await _interaction.RevokeUserConsentAsync(ClientId);
|
||||
await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), ClientId));
|
||||
await interaction.RevokeUserConsentAsync(ClientId);
|
||||
await events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), ClientId));
|
||||
Telemetry.Metrics.GrantsRevoked(ClientId);
|
||||
|
||||
return RedirectToPage("/Grants/Index");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page
|
||||
@model IdentityServerHost.Pages.Home.Index
|
||||
@model IdentityServerHost.Pages.Index
|
||||
|
||||
<div class="welcome-page">
|
||||
<h1>
|
||||
|
|
|
|||
|
|
@ -3,16 +3,14 @@ using Duende.IdentityServer;
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace IdentityServerHost.Pages.Home;
|
||||
namespace IdentityServerHost.Pages;
|
||||
|
||||
[AllowAnonymous]
|
||||
public class Index : PageModel
|
||||
public class Index(IdentityServerLicense? license = null) : PageModel
|
||||
{
|
||||
public Index(IdentityServerLicense? license = null) => License = license;
|
||||
|
||||
public string Version => typeof(Duende.IdentityServer.Hosting.IdentityServerMiddleware).Assembly
|
||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
|
||||
?.InformationalVersion.Split('+').First()
|
||||
?? "unavailable";
|
||||
public IdentityServerLicense? License { get; }
|
||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
|
||||
?.InformationalVersion.Split('+').First()
|
||||
?? "unavailable";
|
||||
public IdentityServerLicense? License { get; } = license;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,8 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
|
|||
|
||||
namespace IdentityServerHost.Pages.ServerSideSessions;
|
||||
|
||||
public class IndexModel : PageModel
|
||||
public class IndexModel(ISessionManagementService? sessionManagementService = null) : PageModel
|
||||
{
|
||||
private readonly ISessionManagementService? _sessionManagementService;
|
||||
|
||||
public IndexModel(ISessionManagementService? sessionManagementService = null) => _sessionManagementService = sessionManagementService;
|
||||
|
||||
public QueryResult<UserSession>? UserSessions { get; set; }
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
|
|
@ -37,9 +33,9 @@ public class IndexModel : PageModel
|
|||
return NotFound();
|
||||
}
|
||||
|
||||
if (_sessionManagementService != null)
|
||||
if (sessionManagementService != null)
|
||||
{
|
||||
UserSessions = await _sessionManagementService.QuerySessionsAsync(new SessionQuery
|
||||
UserSessions = await sessionManagementService.QuerySessionsAsync(new SessionQuery
|
||||
{
|
||||
ResultsToken = Token,
|
||||
RequestPriorResults = Prev == "true",
|
||||
|
|
@ -63,9 +59,9 @@ public class IndexModel : PageModel
|
|||
return NotFound();
|
||||
}
|
||||
|
||||
ArgumentNullException.ThrowIfNull(_sessionManagementService);
|
||||
ArgumentNullException.ThrowIfNull(sessionManagementService);
|
||||
|
||||
await _sessionManagementService.RemoveSessionsAsync(new RemoveSessionsContext
|
||||
await sessionManagementService.RemoveSessionsAsync(new RemoveSessionsContext
|
||||
{
|
||||
SessionId = SessionId,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using Duende.IdentityModel;
|
|||
using Duende.IdentityServer;
|
||||
using Duende.IdentityServer.Test;
|
||||
|
||||
namespace IdentityServerHost;
|
||||
namespace IdentityServerHost.Pages;
|
||||
|
||||
public static class TestUsers
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
@using IdentityServerHost.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Duende.IdentityServer.Licensing;
|
||||
using IdentityServerInMem;
|
||||
using IdentityServerHost;
|
||||
using Serilog;
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.AccessTokenManagement.OpenIdConnect" Version="3.2.0" />
|
||||
<PackageReference Include="Duende.IdentityModel" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.6" />
|
||||
<PackageReference Include="Duende.AccessTokenManagement.OpenIdConnect" Version="4.1.0" />
|
||||
<PackageReference Include="Duende.IdentityModel" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -82,10 +82,10 @@ void CopyFile(DirectoryInfo directoryInfo, FileInfo fileInfo)
|
|||
|
||||
bool TryFindFile(string fileName, [NotNullWhen(true)] out FileInfo? found)
|
||||
{
|
||||
var executingAssemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
|
||||
?? throw new InvalidOperationException("Failed to find executing assembly location");
|
||||
|
||||
|
||||
var currentDir = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
|
||||
?? throw new InvalidOperationException("Failed to find directory for current assembly"));
|
||||
var currentDir = new DirectoryInfo(executingAssemblyLocation);
|
||||
|
||||
while (currentDir != null && currentDir.Exists)
|
||||
{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue