mirror of
https://github.com/nsnail/IGeekFan.AspNetCore.Knife4jUI.git
synced 2025-04-13 19:52:50 +08:00
parent
1d63f2c585
commit
8ea53827f5
@ -22,6 +22,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SwaggerUI_IndexStream_Knife
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IGeekFan.AspNetCore.Knife4jUI", "src\IGeekFan.AspNetCore.Knife4jUI\IGeekFan.AspNetCore.Knife4jUI.csproj", "{6C784918-BE29-4FEF-8AC3-9D34A38DE822}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebSites", "WebSites", "{86851B6C-3504-4879-8464-1DB422D46BA0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OAuth2Integration", "test\WebSites\OAuth2Integration\OAuth2Integration.csproj", "{9E8D8F42-33F0-4F2D-9B56-1AB1B33DE1FA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -44,6 +48,10 @@ Global
|
||||
{6C784918-BE29-4FEF-8AC3-9D34A38DE822}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C784918-BE29-4FEF-8AC3-9D34A38DE822}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C784918-BE29-4FEF-8AC3-9D34A38DE822}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9E8D8F42-33F0-4F2D-9B56-1AB1B33DE1FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E8D8F42-33F0-4F2D-9B56-1AB1B33DE1FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9E8D8F42-33F0-4F2D-9B56-1AB1B33DE1FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9E8D8F42-33F0-4F2D-9B56-1AB1B33DE1FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -53,6 +61,8 @@ Global
|
||||
{86A24FA0-E85D-4BDD-97D7-B990C50A40A9} = {75C51574-4CBD-403B-8182-8BF2A6DCFD43}
|
||||
{1D6FD5CA-5D58-4895-8545-A93099CE1AD4} = {C146A419-15E0-4475-9623-706C5E2DCE0B}
|
||||
{6C784918-BE29-4FEF-8AC3-9D34A38DE822} = {929BB2D7-C678-4BE8-8AA9-F271A2AE4545}
|
||||
{86851B6C-3504-4879-8464-1DB422D46BA0} = {75C51574-4CBD-403B-8182-8BF2A6DCFD43}
|
||||
{9E8D8F42-33F0-4F2D-9B56-1AB1B33DE1FA} = {86851B6C-3504-4879-8464-1DB422D46BA0}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9D77CCB4-F597-421B-9EF9-52D4B0AC382D}
|
||||
|
@ -11,14 +11,14 @@
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/luoyunchong/IGeekFan.AspNetCore.Knife4jUI.git</RepositoryUrl>
|
||||
<RootNamespace>IGeekFan.AspNetCore.Knife4jUI</RootNamespace>
|
||||
<Version>0.0.4</Version>
|
||||
<Version>0.0.6</Version>
|
||||
<Company />
|
||||
<Authors>igeekfan;xiaoym;</Authors>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Copyright>Apache License 2.0</Copyright>
|
||||
<PackageLicenseExpression></PackageLicenseExpression>
|
||||
<AssemblyVersion>0.0.4.0</AssemblyVersion>
|
||||
<FileVersion>0.0.4.0</FileVersion>
|
||||
<AssemblyVersion>0.0.6.0</AssemblyVersion>
|
||||
<FileVersion>0.0.6.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
|
@ -6,16 +6,17 @@
|
||||
<meta name=viewport content="width=device-width,initial-scale=1">
|
||||
<link rel=icon href=favicon.ico>
|
||||
<title>%(DocumentTitle)</title>
|
||||
<link href=knife4j/css/app.b2e62e71.css rel=preload as= style>
|
||||
<link href=knife4j/js/app.ed7acb83.js rel=preload as=script>
|
||||
<link href=knife4j/css/app.8efd8010.css rel=preload as= style>
|
||||
<link href=knife4j/js/app.765df824.js rel=preload as=script>
|
||||
<link href=knife4j/js/chunk-vendors.e86fea24.js rel=preload as=script>
|
||||
<link href=knife4j/css/app.b2e62e71.css rel=stylesheet>
|
||||
<link href=knife4j/css/app.8efd8010.css rel=stylesheet>
|
||||
%(HeadContent)
|
||||
</head>
|
||||
<body>
|
||||
<noscript><strong>We're sorry but knife4j-vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div>
|
||||
<noscript><strong>We're sorry but knife4j-vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript>
|
||||
<div id=app></div>
|
||||
<script src=knife4j/js/chunk-vendors.e86fea24.js></script>
|
||||
<script src=knife4j/js/app.ed7acb83.js></script>
|
||||
<script src=knife4j/js/app.765df824.js></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 306 KiB After Width: | Height: | Size: 306 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
File diff suppressed because one or more lines are too long
BIN
src/IGeekFan.AspNetCore.Knife4jUI/knife4j/js/app.765df824.js.gz
Normal file
BIN
src/IGeekFan.AspNetCore.Knife4jUI/knife4j/js/app.765df824.js.gz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
57
test/WebSites/OAuth2Integration/AuthServer/Config.cs
Normal file
57
test/WebSites/OAuth2Integration/AuthServer/Config.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System.Collections.Generic;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Test;
|
||||
|
||||
namespace OAuth2Integration.AuthServer
|
||||
{
|
||||
public static class Config
|
||||
{
|
||||
internal static IEnumerable<Client> Clients()
|
||||
{
|
||||
yield return new Client
|
||||
{
|
||||
ClientId = "test-id",
|
||||
ClientName = "Test client (Code with PKCE)",
|
||||
|
||||
RedirectUris = new[] {
|
||||
"http://localhost:55202/resource-server/swagger/oauth2-redirect.html", // IIS Express
|
||||
"http://localhost:5000/resource-server/swagger/oauth2-redirect.html", // Kestrel
|
||||
},
|
||||
|
||||
ClientSecrets = { new Secret("test-secret".Sha256()) },
|
||||
RequireConsent = true,
|
||||
|
||||
AllowedGrantTypes = GrantTypes.Code,
|
||||
RequirePkce = true,
|
||||
AllowedScopes = new[] { "readAccess", "writeAccess" },
|
||||
};
|
||||
}
|
||||
|
||||
internal static IEnumerable<ApiResource> ApiResources()
|
||||
{
|
||||
yield return new ApiResource
|
||||
{
|
||||
Name = "api",
|
||||
DisplayName = "API",
|
||||
Scopes = new[]
|
||||
{
|
||||
new Scope("readAccess", "Access read operations"),
|
||||
new Scope("writeAccess", "Access write operations")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
internal static List<TestUser> TestUsers()
|
||||
{
|
||||
return new List<TestUser>
|
||||
{
|
||||
new TestUser
|
||||
{
|
||||
SubjectId = "joebloggs",
|
||||
Username = "joebloggs",
|
||||
Password = "pass123"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using IdentityServer4;
|
||||
using IdentityServer4.Test;
|
||||
|
||||
namespace OAuth2Integration.AuthServer.Controllers
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
[Route("account")]
|
||||
public class AccountController : Controller
|
||||
{
|
||||
private readonly TestUserStore _userStore;
|
||||
|
||||
public AccountController()
|
||||
{
|
||||
_userStore = new TestUserStore(Config.TestUsers());
|
||||
}
|
||||
|
||||
[HttpGet("login")]
|
||||
public IActionResult Login(string returnUrl)
|
||||
{
|
||||
var viewModel = new LoginViewModel { Username = "joebloggs", Password = "pass123", ReturnUrl = returnUrl };
|
||||
|
||||
return View("/AuthServer/Views/Login.cshtml", viewModel);
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> Login([FromForm]LoginViewModel viewModel)
|
||||
{
|
||||
if (!_userStore.ValidateCredentials(viewModel.Username, viewModel.Password))
|
||||
{
|
||||
ModelState.AddModelError("", "Invalid username or password");
|
||||
viewModel.Password = string.Empty;
|
||||
return View("/AuthServer/Views/Login.cshtml", viewModel);
|
||||
}
|
||||
|
||||
// Use an IdentityServer-compatible ClaimsPrincipal
|
||||
var identityServerUser = new IdentityServerUser(viewModel.Username);
|
||||
identityServerUser.DisplayName = viewModel.Username;
|
||||
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, identityServerUser.CreatePrincipal());
|
||||
|
||||
return Redirect(viewModel.ReturnUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public class LoginViewModel
|
||||
{
|
||||
public string ReturnUrl { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using IdentityServer4.Stores;
|
||||
using IdentityServer4.Services;
|
||||
using IdentityServer4.Models;
|
||||
|
||||
namespace OAuth2Integration.AuthServer.Controllers
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public class ConsentController : Controller
|
||||
{
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly IClientStore _clientStore;
|
||||
private readonly IResourceStore _resourceStore;
|
||||
|
||||
public ConsentController(
|
||||
IIdentityServerInteractionService interaction,
|
||||
IClientStore clientStore,
|
||||
IResourceStore resourceStore)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_clientStore = clientStore;
|
||||
_resourceStore = resourceStore;
|
||||
}
|
||||
|
||||
[HttpGet("consent")]
|
||||
public async Task<IActionResult> Consent(string returnUrl)
|
||||
{
|
||||
var request = await _interaction.GetAuthorizationContextAsync(returnUrl);
|
||||
var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
|
||||
var resource = await _resourceStore.FindApiResourceAsync("api");
|
||||
|
||||
var viewModel = new ConsentViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl,
|
||||
ClientName = client.ClientName,
|
||||
ScopesRequested = resource.Scopes.Where(s => request.ScopesRequested.Contains(s.Name))
|
||||
};
|
||||
|
||||
return View("/AuthServer/Views/Consent.cshtml", viewModel);
|
||||
}
|
||||
|
||||
[HttpPost("consent")]
|
||||
public async Task<IActionResult> Consent([FromForm]ConsentViewModel viewModel)
|
||||
{
|
||||
var request = await _interaction.GetAuthorizationContextAsync(viewModel.ReturnUrl);
|
||||
|
||||
// Communicate outcome of consent back to identityserver
|
||||
var consentResponse = new ConsentResponse
|
||||
{
|
||||
ScopesConsented = viewModel.ScopesConsented
|
||||
};
|
||||
await _interaction.GrantConsentAsync(request, consentResponse);
|
||||
|
||||
return Redirect(viewModel.ReturnUrl);
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsentViewModel
|
||||
{
|
||||
public string ReturnUrl { get; set; }
|
||||
public string ClientName { get; set; }
|
||||
public IEnumerable<Scope> ScopesRequested { get; set; }
|
||||
public string[] ScopesConsented { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
@model OAuth2Integration.AuthServer.Controllers.ConsentViewModel
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
<h1>Consent</h1>
|
||||
<p>
|
||||
@Model.ClientName is requesting your permission to ...
|
||||
</p>
|
||||
<form asp-controller="Consent" asp-action="Consent">
|
||||
<input type="hidden" asp-for="ReturnUrl" />
|
||||
<fieldset>
|
||||
<ul>
|
||||
@foreach (var scope in Model.ScopesRequested)
|
||||
{
|
||||
<li>
|
||||
<label>
|
||||
<input name="ScopesConsented" type="checkbox" value="@scope.Name" checked />@scope.DisplayName
|
||||
</label>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</fieldset>
|
||||
<button type="submit">Grant Access</button>
|
||||
</form>
|
@ -0,0 +1,23 @@
|
||||
@model OAuth2Integration.AuthServer.Controllers.LoginViewModel
|
||||
|
||||
<style>
|
||||
input {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Login</h1>
|
||||
<form asp-controller="Account" asp-action="Login">
|
||||
<input type="hidden" asp-for="ReturnUrl" />
|
||||
<fieldset>
|
||||
<label>
|
||||
Username:
|
||||
<input type="text" asp-for="Username" />
|
||||
</label>
|
||||
<label>
|
||||
Password:
|
||||
<input type="text" asp-for="Password" />
|
||||
</label>
|
||||
</fieldset>
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
@ -0,0 +1 @@
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
17
test/WebSites/OAuth2Integration/OAuth2Integration.csproj
Normal file
17
test/WebSites/OAuth2Integration/OAuth2Integration.csproj
Normal file
@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="IdentityServer4" Version="3.0.2" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="5.5.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="5.5.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
26
test/WebSites/OAuth2Integration/Program.cs
Normal file
26
test/WebSites/OAuth2Integration/Program.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace OAuth2Integration
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:55202",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "resource-server/swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"OAuth2Integration": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "resource-server/swagger",
|
||||
"applicationUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace OAuth2Integration.ResourceServer.Controllers
|
||||
{
|
||||
[Route("products")]
|
||||
[Authorize(AuthenticationSchemes = "Bearer")]
|
||||
public class ProductsController : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize("readAccess")]
|
||||
public IEnumerable<Product> GetProducts()
|
||||
{
|
||||
yield return new Product
|
||||
{
|
||||
Id = 1,
|
||||
SerialNo = "ABC123",
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("readAccess")]
|
||||
public Product GetProduct(int id)
|
||||
{
|
||||
return new Product
|
||||
{
|
||||
Id = 1,
|
||||
SerialNo = "ABC123",
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize("writeAccess")]
|
||||
public void CreateProduct([FromBody]Product product)
|
||||
{
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize("writeAccess")]
|
||||
public void DeleteProduct(int id)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Product
|
||||
{
|
||||
public int Id { get; internal set; }
|
||||
public string SerialNo { get; set; }
|
||||
public ProductStatus Status { get; set; }
|
||||
}
|
||||
|
||||
public enum ProductStatus
|
||||
{
|
||||
InStock, ComingSoon
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace OAuth2Integration.ResourceServer.Swagger
|
||||
{
|
||||
public class SecurityRequirementsOperationFilter : IOperationFilter
|
||||
{
|
||||
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||
{
|
||||
// Policy names map to scopes
|
||||
var requiredScopes = context.MethodInfo
|
||||
.GetCustomAttributes(true)
|
||||
.OfType<AuthorizeAttribute>()
|
||||
.Select(attr => attr.Policy)
|
||||
.Distinct();
|
||||
|
||||
if (requiredScopes.Any())
|
||||
{
|
||||
operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
|
||||
operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
|
||||
|
||||
var oAuthScheme = new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
|
||||
};
|
||||
|
||||
operation.Security = new List<OpenApiSecurityRequirement>
|
||||
{
|
||||
new OpenApiSecurityRequirement
|
||||
{
|
||||
[ oAuthScheme ] = requiredScopes.ToList()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
144
test/WebSites/OAuth2Integration/Startup.cs
Normal file
144
test/WebSites/OAuth2Integration/Startup.cs
Normal file
@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
||||
namespace OAuth2Integration
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// Register IdentityServer services to power OAuth2.0 flows
|
||||
services.AddIdentityServer()
|
||||
.AddDeveloperSigningCredential()
|
||||
.AddInMemoryClients(AuthServer.Config.Clients())
|
||||
.AddInMemoryApiResources(AuthServer.Config.ApiResources())
|
||||
.AddTestUsers(AuthServer.Config.TestUsers());
|
||||
|
||||
// The auth setup is a little nuanced because this app provides the auth-server & the resource-server
|
||||
// Use the "Cookies" scheme by default & explicitly require "Bearer" in the resource-server controllers
|
||||
// See https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?tabs=aspnetcore2x
|
||||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||
.AddCookie()
|
||||
.AddIdentityServerAuthentication(c =>
|
||||
{
|
||||
c.Authority = "http://localhost:55202/auth-server/";
|
||||
c.RequireHttpsMetadata = false;
|
||||
c.ApiName = "api";
|
||||
});
|
||||
|
||||
// Configure named auth policies that map directly to OAuth2.0 scopes
|
||||
services.AddAuthorization(c =>
|
||||
{
|
||||
c.AddPolicy("readAccess", p => p.RequireClaim("scope", "readAccess"));
|
||||
c.AddPolicy("writeAccess", p => p.RequireClaim("scope", "writeAccess"));
|
||||
});
|
||||
|
||||
services.AddControllersWithViews();
|
||||
|
||||
services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "Test API V1" });
|
||||
|
||||
// Define the OAuth2.0 scheme that's in use (i.e. Implicit Flow)
|
||||
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
|
||||
{
|
||||
Type = SecuritySchemeType.OAuth2,
|
||||
Flows = new OpenApiOAuthFlows
|
||||
{
|
||||
AuthorizationCode = new OpenApiOAuthFlow
|
||||
{
|
||||
AuthorizationUrl = new Uri("/auth-server/connect/authorize", UriKind.Relative),
|
||||
TokenUrl = new Uri("/auth-server/connect/token", UriKind.Relative),
|
||||
Scopes = new Dictionary<string, string>
|
||||
{
|
||||
{ "readAccess", "Access read operations" },
|
||||
{ "writeAccess", "Access write operations" }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
|
||||
},
|
||||
new[] { "readAccess", "writeAccess" }
|
||||
}
|
||||
});
|
||||
|
||||
// Assign scope requirements to operations based on AuthorizeAttribute
|
||||
//c.OperationFilter<SecurityRequirementsOperationFilter>();
|
||||
});
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.Map("/auth-server", authServer =>
|
||||
{
|
||||
authServer.UseRouting();
|
||||
|
||||
authServer.UseAuthentication();
|
||||
|
||||
authServer.UseIdentityServer();
|
||||
|
||||
authServer.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
app.Map("/resource-server", resourceServer =>
|
||||
{
|
||||
resourceServer.UseRouting();
|
||||
|
||||
resourceServer.UseAuthentication();
|
||||
|
||||
resourceServer.UseAuthorization();
|
||||
|
||||
resourceServer.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
|
||||
resourceServer.UseSwagger();
|
||||
resourceServer.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/resource-server/swagger/v1/swagger.json", "My API V1");
|
||||
c.EnableDeepLinking();
|
||||
|
||||
// Additional OAuth settings (See https://github.com/swagger-api/swagger-ui/blob/v3.10.0/docs/usage/oauth2.md)
|
||||
c.OAuthClientId("test-id");
|
||||
c.OAuthClientSecret("test-secret");
|
||||
c.OAuthAppName("test-app");
|
||||
c.OAuthScopeSeparator(" ");
|
||||
c.OAuthUsePkce();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
10
test/WebSites/OAuth2Integration/appsettings.json
Normal file
10
test/WebSites/OAuth2Integration/appsettings.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
1
test/WebSites/OAuth2Integration/tempkey.rsa
Normal file
1
test/WebSites/OAuth2Integration/tempkey.rsa
Normal file
@ -0,0 +1 @@
|
||||
{"KeyId":"08433185bdf583112d2df84b15adc5fe","Parameters":{"D":"G5yB2Ha3ktEmpXH+1qIuJ/dJ8TJKFAj2j1qMLl/Zu0jI1GZJlCyeWHEM0B0IFlbkUq2W82ym9dJUaSGXC3FxSZ/JHwNzgonpv9ELQZDnAwvO0kpnJTw+SQWwDxUxItGNT8giqqm5LcSYWhv+QexepyEOwKr6Efh6hHrTsjxk/2t3xPhZJbutifcBrAaHb0wjV/mw442wXol1cjWmG5qVOj54n16kU2Pxr1i9oukZBJMYLltg8NB99KgvZSVvOoctXiPszEHel4kNdSv0R3yt2lBad+OEZykCgzgbZYmA2aIvUmB8r+yxFUiXEDuM9Wjp3gxBLdAWAdutPhtcXqPXGw==","DP":"fVcFyftVuEEFERT6UzfnIhDW/2A1ckzwutVQAYOjRwC+FyRIGyN6kzc1SSIhpuMECcibvPBp0wbyx0JsUbcUVlo6uKXaYx5h6Qcv4fIrqfFOUfVNuQ2W8mltwpDdFuquwOAEz08zMtkVavZxfghmJgYNeqqQvvuvetjAuL6Tdws=","DQ":"whD6E1yg5fe3FDcq+cVQnj3xeSWB7pYURNIYAI2Oo1y2fCfH7/TDaQbGpIr0nO/RiH2SxH1vJ5O5foKG0JES3wCe7qflJOviOzb3SNlXm3gCdvNZyAruA2k9wyro5hauDMU51saed6xAy3dL+Q5fKE+0fmKOBxVZr2RPMnglTc0=","Exponent":"AQAB","InverseQ":"tQt+mEXZQq9YpAU6Q7/8gpPBy+F3B52KmP3e5bcnvilSDIXOUjye8NMTd8WeX+NmOje+g+5aYW5kVyiXhwoVM1Bz3Iwyq51Kix3JMmaiFBPaC/r9jF/2JveiT3iKlzgi0RJcOM4rnA1pHakr3rz6nVoxpBGe8OMUTrg4cVkM4HU=","Modulus":"y6F+tcOmGz6DAYfooFDMtkeG5/7TqOpW3U3eSu4KmuoCMdc8hiJwspcwu6Yu6OGVbYKW1nZTEP2SizpTixy6W/TYFMIQZC08iBxR8mDlp2HXeGiOTMFJQFdgT+Qe0xgZ9yPdOSbBmih6dATK61k4QvDbrhAf8j7mv7JW4s5T6WCjmx0UOyo9medzP/YhCL6lnaxP3hWA61ncVK38BGHFzo/sZSyA79EXo/091CKm1V0VpZMhpZIt6wyXPg8bLyJh1edXFCqEYDXvVcfuFFhmILfB/g5CUz/YCJu2Z1VDG4OOXPtg6xJMAbcl/67yH0wu/HSNoUcLN1cJkYXAUsg1yQ==","P":"6Tl+cOLjTwUiQbTiVtC4v2uO4FcjsuKbWlqKiqJ7veMJQHdP/AOPNtLq9eKrpKfc6f0eRQHYLf//o1ntweFFBhZ3lgCAdD3gQw02meMCxSPt+BMgylFkNZXW0TfISx/a3q4XGBSLTmu0d5uN3FNxRDNmAKeL8xgvb/ikKQSHnGM=","Q":"34Qr0kjiZkXvxHY6pxfBmzwYitC/bBwxwOrLq8S30FN5G2QQ/KWc7EJnOJz3C+yX9Vep2Fslu5xYAoBjbEofVMRlvsu2T4c+d/KfUQLaualXNlQiR4TKqW13Dau+ZEDEh71NFdJwqhKzJb8ojiRMcMHD1M5AmDApDUfqAOoybuM="}}
|
Loading…
x
Reference in New Issue
Block a user