[英]IdentityServer: Check if scopes present in a policy for authentication in OpenId Connect
我有一个基于策略的身份验证的控制器:
[ApiController]
[Route("[controller]")]
[Authorize(Policy ="SomePolicy")]
public class BankController : ControllerBase
{
...
}
说明“范围”的策略身份验证代码应该是“读取”或“完全访问”。 见下面的代码:
services.AddAuthorization(options =>
{
options.AddPolicy("SomePolicy", policy =>
{
policy.RequireClaim("scope", "read", "fullaccess");
});
});
“读取”和“完全访问”是在 appsetting.json 上定义的 ApiScopes,并从那里提供给 IdentityServer 4。
"IdentityServerSettings": {
"ApiScopes": [
{
"Name": "read"
},
{
"Name": "fullaccess"
}
],
...
}
该代码在邮递员测试中运行良好。
问题是如何在 OpenId Connect 上实现。 我所有的尝试似乎都失败了。
我试过了:
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://localhost:5001";
options.ClientId = "postman";
options.ResponseType = "code";
options.Scope.Add("read");
options.Scope.Add("fullaccess");
options.SaveTokens = true;
});
但它不起作用? 请帮忙?
我想我可以在这里分享我的集成步骤来帮助您解决问题。
单击此处查看相关博客。
首先,我创建了一个 asp.net core 3.1 mvc 项目,并安装了这些包:
<ItemGroup>
<PackageReference Include="IdentityServer4" Version="4.1.2" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.17" />
</ItemGroup>
然后添加一个名为Config.cs的文件,请注意在我的项目中,https的默认端口是5001,参见launchSetting.json:
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Test;
using System.Collections.Generic;
using System.Security.Claims;
namespace WebApplication1
{
public class Config
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource
{
Name = "role",
UserClaims = new List<string> {"role"}
}
};
}
public static IEnumerable<ApiScope> GetApiScopes()
{
return new List<ApiScope>
{
new ApiScope("api1.read", "Read Access to API #1"),
new ApiScope("api1.write", "Write Access to API #1")
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource> {
new ApiResource
{
Name = "api1",
DisplayName = "API #1",
Description = "Allow the application to access API #1 on your behalf",
Scopes = new List<string> {"api1.read", "api1.write"},
ApiSecrets = new List<Secret> {new Secret("ScopeSecret".Sha256())},
UserClaims = new List<string> {"role"}
}
};
}
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
// other clients omitted...
new Client
{
ClientId = "oidcClient",
ClientName = "Example Client Application",
ClientSecrets = new List<Secret> {new Secret("SuperSecretPassword".Sha256())}, // change me!
AllowedGrantTypes = GrantTypes.Code,
RedirectUris = new List<string> {"https://localhost:5001/signin-oidc"},
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"role",
"api1.read"
},
RequirePkce = true,
AllowPlainTextPkce = false
},
new Client
{
ClientId = "oauthClient",
ClientName = "Example client application using client credentials",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = new List<Secret> {new Secret("SuperSecretPassword".Sha256())}, // change me!
AllowedScopes = new List<string> {"api1.read"}
}
};
}
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser {
SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
Username = "tiny",
Password = "111",
Claims = new List<Claim> {
new Claim(JwtClaimTypes.Email, "tiny@gmail.com"),
new Claim(JwtClaimTypes.Role, "admin")
}
}
};
}
}
}
接下来,我们可以使用powershell运行命令在我们的项目中安装默认身份服务器4 ui ,用于登录部分。 因为它还会提供一个HomeController.cs,所以我们可以在创建项目的时候重命名或者删除原来的HomeController。 进入项目根目录,打开powershell,运行:
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/main/getmain.ps1'))
然后我们需要修改startup.cs,这是我的文件:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication1
{
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)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
services.AddControllersWithViews();
//If we only need to enable the token validation for api, use the code commented below
//services.AddAuthentication("Bearer")
//.AddIdentityServerAuthentication("Bearer", options =>
//{
// options.ApiName = "api1";
// options.Authority = "https://localhost:5001";
//});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("cookie")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://localhost:5001";
options.ClientId = "oidcClient";
options.ClientSecret = "SuperSecretPassword";
options.ResponseType = "code";
options.UsePkce = true;
options.ResponseMode = "query";
options.CallbackPath = "/signin-oidc"; // default redirect URI
// options.Scope.Add("oidc"); // default scope
// options.Scope.Add("profile"); // default scope
options.Scope.Add("api1.read");
options.SaveTokens = true;
});
}
// 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();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
最后,让我们评论 HomeController 中的[AllowAnonymous]
属性,并为隐私页面添加一个操作:
[Authorize]
public IActionResult Privacy() => View();
我们还可以添加一个新控制器使其像 api 一样工作并在该控制器上添加[Authorize]
,例如
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers
{
[Authorize]
public class HelloController : Controller
{
public string Index()
{
return "hello world";
}
}
}
然后启动程序,我们可以直接看到首页,但是如果我们访问https://localhost:5001/hello/index
, https://localhost:5001/home/privacy
,会重定向到登录页面,之后登录(用户名和密码在 config.cs 中定义)我们可以看到私人页面或响应消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.