如何在 c# asp.net 中从私有提供商实现 OpenID Connect
how to implement OpenID Connect from a private provider in the c# asp.net
我有一个 ASP.NET MVC 应用程序需要集成来自 Private OpenID Connect (OIDC) Provider 的 OpenID Connect 身份验证,流程包括以下步骤:
用户点击登录
它将使用以下 HTTP GET
请求将用户重定向到私有 OIDC 站点进行身份验证:
成功登录私有 OIDC 站点后,它将重定向回我的站点并获取带有 code
结果的 uri,如下所示:
然后我将需要使用上面的 code
并对私有 ODIC 令牌端点进行 HTTP POST
调用以获取该用户的访问令牌。
所以,我的 questions #1
是:如何在 c# asp.net 应用程序中实现它?
另外,我在 Postman 的“Get New Access Token”中尝试了这个,我得到了令牌。
如您所见,在我提供所有参数并单击“请求令牌”后,它会弹出登录 winnow,
登录成功后显示token
我的 questions #2
是:与问题 #1 类似,是否可以在 c# asp.net 应用程序中实现它?
就像在 asp.net mvc 应用程序中一样,在第一个图像中添加一个带有 url 的 link 按钮,当用户单击它时,它将使用 code
,然后使用此代码在 stpe3.
中进行 HTTP POST 调用
设置 IdentifyServer4:IdentityServer4 是 ASP.NET
的 OpenID Connect 和 OAuth 2.0 框架
您可以在此处找到有关如何使用 IdentifyServer4 的文档:
https://identityserver4.readthedocs.io/en/latest/
https://identityserver4.readthedocs.io/en/latest/quickstarts/3_aspnetcore_and_apis.html
IdentityServer4 提供的一些功能是:
Authentication as a Service
Centralized login logic and workflow for all of your applications (web, native, mobile, services). IdentityServer is an officially certified implementation of OpenID Connect.
Single Sign-on / Sign-out
Single sign-on (and out) over multiple application types.
Access Control for APIs
Issue access tokens for APIs for various types of clients, e.g. server to server, web applications, SPAs and native/mobile apps.
Federation Gateway
Support for external identity providers like Azure Active Directory, Google, Facebook etc. This shields your applications from the details of how to connect to these external providers.
Focus on Customization
The most important part - many aspects of IdentityServer can be customized to fit your needs. Since IdentityServer is a framework and not a boxed product or a SaaS, you can write code to adapt the system the way it makes sense for your scenarios.
Mature Open Source
IdentityServer uses the permissive Apache 2 license that allows building commercial products on top of it. It is also part of the .NET Foundation which provides governance and legal backing.
Free and Commercial Support
您可以找到一个 open source example of this on GitHub。该许可证非常宽松,并且有据可查。我已经在各种研讨会和培训中使用过它,所以大部分错误都已解决。我建议你深入研究一下。为了完整起见,我将在这里描述一般过程,并以此作为解释的基础。
任何实现 OpenID Connect 代码流的 Web 应用程序都将包括两部分:
- 流程的开始和
- 回调的处理
执行这两件事的应用程序称为“客户端”或“依赖方”。此客户端使用 OpenID Connect 协议与之通信的对象称为 OpenID Connect 提供程序 (OP),通常也称为身份提供程序 (IdP)。
客户端实现的第一部分将显示一个包含按钮的视图。此按钮将是典型的“登录”或“登录”按钮。请注意,这是可选的,如果应用程序检测到用户没有会话,它可能会立即将用户重定向到 OP。然而,鉴于您上面的问题,这对您来说并非如此,客户端将首先呈现一个显示此类按钮的视图。视图可能看起来像这样:
<div>
@if(Session.Count == 0) {
<p>
This is a demo application to demonstrate the use for OAuth2
and OpenID Connect.
</p>
<p>
Pressing Sign In will redirect you to @ViewData["server_name"]
and authorize the application to access your profile info. The
data will only be used to demonstrate the possibilities of the
OpenID Connect protocol and will not be stored. Be sure to
revoke access when you are satisfied.
</p>
<div>
<a href="/login">Sign In</a>
</div>
} else {
// ...
}
</div>
这个视图将由一个非常基本的控制器呈现,该控制器连接在 Global.asax.cs
中建立的路由配置中。单击登录按钮后,OpenID Connect 部件将启动。处理此请求的控制器将简单地重定向到 OP 的授权端点。在最基本的情况下,这可能看起来像这样:
public class LoginController : Controller
{
private static string start_oauth_endpoint = Helpers.Client.Instance.GetAuthnReqUrl();
public ActionResult Index()
{
return Redirect(start_oauth_endpoint);
}
}
有趣的部分是如何获取授权端点。这可以是 hard-coded,在 Web.config
中定义,或者从 OP 的元数据中获取。在我上面引用的示例中,它在应用程序启动时获取 OP 的元数据。这是在位于 Web 应用程序 App_Start
目录中的 AppConfig
中完成的。这会对发行者 ID(位于 Web.config
)执行 HTTP GET 请求,使用 /.well-known/openid-configuration
)。在应用程序启动时获取此元数据而不是将其全部放入配置中的原因是为了减少 OP 和客户端的耦合。
在上面的片段中执行的重定向将有几个重要的查询字符串参数。其中一些将在 design-time 上公开,并将进行硬编码。其他将在Web.config
中配置。有些将在 run-time 处动态计算。下面列出了这些:
client_id
- 此 MVC Web 应用程序的客户端 ID。
response_type
-
- OP 应使用的响应类型。在您的情况下,这将始终是
code
。
scope
- 客户端请求的访问范围。这将至少包括
openid
.
redirect_uri
- OP 在对客户端进行身份验证和授权后将用户发送到的重定向 URI。
也可以发送其他请求参数。为了帮助您确定要发送的内容以及它们对流程的影响,请查看 oauth.tools。这就像“OAuth 和 OpenID Connect 的邮递员”。这是梦幻般的;你会爱上它。在那里,您可以使用各种参数形成各种 OAuth 和 OpenID 连接流。
一旦重定向到 OP,用户将进行身份验证。用户可能还必须同意客户端访问他们受保护的资源。无论如何,OP 之后会将用户重定向到回调。这是实现的第二部分。
在这里,我们将有一个 CallbackController
(或类似的东西)。它看起来像这样(最简单的形式):
public class CallbackController : Controller
{
public ActionResult Index()
{
try
{
string responseString = Helpers.Client.Instance
.GetToken(Request.QueryString["code"]);
SaveDataToSession(responseString);
}
catch (Exception e)
{
Session["error"] = e.Message;
}
return Redirect("/");
}
}
此代码段的重要部分是它从查询字符串中获取 code
,并向 OP 的令牌端点发出 HTTP POST 请求(也可通过解析 OP 的元数据)。如果成功,它会将响应保存在会话中供以后使用。 GetToken
方法看起来像这样:
public String GetToken(String code)
{
var values = new Dictionary<string, string>
{
{ "grant_type", "authorization_code" },
{ "client_id", client_id},
{ "client_secret", client_secret },
{ "code" , code },
{ "redirect_uri", redirect_uri}
};
HttpClient tokenClient = new HttpClient();
var content = new FormUrlEncodedContent(values);
var response = tokenClient.PostAsync(token_endpoint, content).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
return responseContent.ReadAsStringAsync().Result;
}
throw new OAuthClientException("Token request failed with status code: " + response.StatusCode);
}
这会将代码发送到 OP 并获得访问令牌、ID 令牌,也许还有刷新令牌作为交换。此代码的重要部分是:
- 内容是URL-encoded不是JSON的形式。这是一个常见的错误。
- 再次包含先前发送的相同 重定向 URI。这是为了匹配 OP 中的两个请求。
grant_Type
总是authorization_code
。
- 客户端以某种方式进行身份验证。在这种情况下,通过在请求中包含与先前发送的相同
client_id
以及 client_secret
表单元素中的秘密。
- 使用的 HTTP 方法(正如我上面所说的)是 POST,而不是 GET。这也是一个常见的错误。
在我上面的示例中,我重定向回默认值 HomeController
。现在,执行 if 语句的 else 条件。在这里,它可以找到令牌:
<div>
@if(Session.Count == 0) {
// ...
} else {
@if(Session["id_token"] != null) {
<div>
ID Token:<br>
<pre>@Session["id_token"]</pre>
</div>
}
@if(Session["access_token"] != null) {
<div>
Access Token:<br>
<pre>@Session["access_token"]</pre>
</div>
}
@if(Session["refresh_token"] != null) {
<div>
Refresh Token:<br>
<pre>@Session["refresh_token"]</pre>
</div>
}
}
</div>
例子比较详细 t一个这个,但它希望能给你一个想法。通读一遍,查看自述文件,并享受学习更多关于 OpenID Connect 的乐趣!
您需要在不同的地方添加一些配置。我会尽力展示你需要的所有拼图。
在我的示例中,我将使用 OIDC 的 public IdentityServer4 演示版本,因此您可以与工作版本进行比较。
API
在任何控制器(或方法)中,添加 [Authorize]
属性,因此这将需要有效的身份验证。
如果您想更具体地说明用户可以执行的操作,您还可以添加策略。类似于:
[Authorize(Policy = "Read")]
[ApiController]
[Route("[controller]")]
public class HelloWorldsController : ControllerBase
{
[HttpGet]
public string Get()
{
return "Hello, World!";
}
}
在Startup.cs
的ConfigureServices
方法中,你需要添加类似这样的配置:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = "https://demo.identityserver.io";
options.Audience = "api";
});
// In case you want to work with policies
services.AddAuthorization(options =>
{
options.AddPolicy("Read", policy => policy.RequireClaim("scope", "api"));
});
以上配置要编译,需要添加NuGet包Microsoft.AspNetCore.Authentication.JwtBearer
。
在 Startup.cs
的 Configure
方法中,您需要在 app.UseAuthorization();
.
之前添加 app.UseAuthentication();
MVC
在任何控制器(或方法)中,添加 [Authorize]
属性。每当您的 MVC 应用程序的用户点击具有此属性的方法时,都会自动触发登录过程。
为了演示这一点,我将把这个属性添加到一个方法中:
[Authorize]
public async Task<IActionResult> Privacy()
{
var httpClient = _httpClientFactory.CreateClient("ApiClient");
var apiResult = await httpClient.SendAsync(
new HttpRequestMessage(HttpMethod.Get, "/helloworlds"),
HttpCompletionOption.ResponseHeadersRead);
if (apiResult.IsSuccessStatusCode)
{
var content = await apiResult.Content.ReadAsStringAsync();
ViewData.Add("apiResult", content); // Just to demonstrate
}
return View();
}
在Startup.cs
的ConfigureServices
方法中,你需要添加类似这样的配置:
services.AddHttpContextAccessor();
services.AddTransient<BearerTokenHandler>();
services
.AddHttpClient("ApiClient", client =>
{
client.BaseAddress = new Uri("https://localhost:5001");
})
.AddHttpMessageHandler<BearerTokenHandler>();
services.AddHttpClient("IDPClient", client =>
{
client.BaseAddress = new Uri("https://demo.identityserver.io");
});
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = "https://demo.identityserver.io";
options.ClientId = "interactive.confidential";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("api");
});
要编译上述配置,您应该添加 NuGet 包 Microsoft.AspNetCore.Authentication.Cookies
和 Microsoft.AspNetCore.Authentication.OpenIdConnect
.
在 Startup.cs
的 Configure
方法中,您需要在 app.UseAuthorization();
.
之前添加 app.UseAuthentication();
由于 BearerTokenHandler
相当大,您可以从 a GitHub repository 复制它。您需要 IdentityModel
.
的 NuGet 包参考
此存储库还包含您要求的设置的完整工作示例。
最后,您可能想让用户可以注销。
您可以通过在您的视图中添加一个 link 来做到这一点:
@if (User.Identity.IsAuthenticated)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Logout">Logout</a>
</li>
}
为此匹配的控制器方法:
public IActionResult Logout()
{
return SignOut(
CookieAuthenticationDefaults.AuthenticationScheme,
OpenIdConnectDefaults.AuthenticationScheme);
}
应该是这样。希望您能够跟上所有的拼图。
如果有什么不清楚的地方,请告诉我。
没有足够的声誉向 IdentityServer4 答案添加评论,所以我就在这里提一下。
IS4 将不再免费用于商业用途:
The Future of IdentityServer
The current version (IdentityServer4 v4.x) will be the last version we work on as free open source. We will keep supporting IdentityServer4 until the end of life of .NET Core 3.1 in November 2022.
To continue our work, we have formed a new company Duende Software, and IdentityServer4 will be rebranded as Duende IdentityServer. Duende IdentityServer will contain all new feature work and will target .NET Core 3.1 and .NET 5 (and all versions beyond).
This new product will remain open source but will be offered with a dual license (RPL and commercial). The RPL (reciprocal public license) keeps Duende IdentityServer free if you are also doing free open source work. If you are using Duende IdentityServer in a commercial scenario, then a commercial license will be required. We offer a variety of ways to license Duende IdentityServer in an attempt to accommodate the different company sizes and usage models. Including an RPL license is important to us because it allows us to recognize and express our gratitude to the open source community and our contributors.
我有一个 ASP.NET MVC 应用程序需要集成来自 Private OpenID Connect (OIDC) Provider 的 OpenID Connect 身份验证,流程包括以下步骤:
用户点击登录
它将使用以下
HTTP GET
请求将用户重定向到私有 OIDC 站点进行身份验证:成功登录私有 OIDC 站点后,它将重定向回我的站点并获取带有
code
结果的 uri,如下所示:然后我将需要使用上面的
code
并对私有 ODIC 令牌端点进行HTTP POST
调用以获取该用户的访问令牌。
所以,我的 questions #1
是:如何在 c# asp.net 应用程序中实现它?
另外,我在 Postman 的“Get New Access Token”中尝试了这个,我得到了令牌。
如您所见,在我提供所有参数并单击“请求令牌”后,它会弹出登录 winnow,
我的 questions #2
是:与问题 #1 类似,是否可以在 c# asp.net 应用程序中实现它?
就像在 asp.net mvc 应用程序中一样,在第一个图像中添加一个带有 url 的 link 按钮,当用户单击它时,它将使用 code
,然后使用此代码在 stpe3.
设置 IdentifyServer4:IdentityServer4 是 ASP.NET
的 OpenID Connect 和 OAuth 2.0 框架您可以在此处找到有关如何使用 IdentifyServer4 的文档: https://identityserver4.readthedocs.io/en/latest/ https://identityserver4.readthedocs.io/en/latest/quickstarts/3_aspnetcore_and_apis.html
IdentityServer4 提供的一些功能是:
Authentication as a Service
Centralized login logic and workflow for all of your applications (web, native, mobile, services). IdentityServer is an officially certified implementation of OpenID Connect.
Single Sign-on / Sign-out
Single sign-on (and out) over multiple application types.
Access Control for APIs Issue access tokens for APIs for various types of clients, e.g. server to server, web applications, SPAs and native/mobile apps.
Federation Gateway
Support for external identity providers like Azure Active Directory, Google, Facebook etc. This shields your applications from the details of how to connect to these external providers.
Focus on Customization
The most important part - many aspects of IdentityServer can be customized to fit your needs. Since IdentityServer is a framework and not a boxed product or a SaaS, you can write code to adapt the system the way it makes sense for your scenarios.
Mature Open Source
IdentityServer uses the permissive Apache 2 license that allows building commercial products on top of it. It is also part of the .NET Foundation which provides governance and legal backing. Free and Commercial Support
您可以找到一个 open source example of this on GitHub。该许可证非常宽松,并且有据可查。我已经在各种研讨会和培训中使用过它,所以大部分错误都已解决。我建议你深入研究一下。为了完整起见,我将在这里描述一般过程,并以此作为解释的基础。
任何实现 OpenID Connect 代码流的 Web 应用程序都将包括两部分:
- 流程的开始和
- 回调的处理
执行这两件事的应用程序称为“客户端”或“依赖方”。此客户端使用 OpenID Connect 协议与之通信的对象称为 OpenID Connect 提供程序 (OP),通常也称为身份提供程序 (IdP)。
客户端实现的第一部分将显示一个包含按钮的视图。此按钮将是典型的“登录”或“登录”按钮。请注意,这是可选的,如果应用程序检测到用户没有会话,它可能会立即将用户重定向到 OP。然而,鉴于您上面的问题,这对您来说并非如此,客户端将首先呈现一个显示此类按钮的视图。视图可能看起来像这样:
<div>
@if(Session.Count == 0) {
<p>
This is a demo application to demonstrate the use for OAuth2
and OpenID Connect.
</p>
<p>
Pressing Sign In will redirect you to @ViewData["server_name"]
and authorize the application to access your profile info. The
data will only be used to demonstrate the possibilities of the
OpenID Connect protocol and will not be stored. Be sure to
revoke access when you are satisfied.
</p>
<div>
<a href="/login">Sign In</a>
</div>
} else {
// ...
}
</div>
这个视图将由一个非常基本的控制器呈现,该控制器连接在 Global.asax.cs
中建立的路由配置中。单击登录按钮后,OpenID Connect 部件将启动。处理此请求的控制器将简单地重定向到 OP 的授权端点。在最基本的情况下,这可能看起来像这样:
public class LoginController : Controller
{
private static string start_oauth_endpoint = Helpers.Client.Instance.GetAuthnReqUrl();
public ActionResult Index()
{
return Redirect(start_oauth_endpoint);
}
}
有趣的部分是如何获取授权端点。这可以是 hard-coded,在 Web.config
中定义,或者从 OP 的元数据中获取。在我上面引用的示例中,它在应用程序启动时获取 OP 的元数据。这是在位于 Web 应用程序 App_Start
目录中的 AppConfig
中完成的。这会对发行者 ID(位于 Web.config
)执行 HTTP GET 请求,使用 /.well-known/openid-configuration
)。在应用程序启动时获取此元数据而不是将其全部放入配置中的原因是为了减少 OP 和客户端的耦合。
在上面的片段中执行的重定向将有几个重要的查询字符串参数。其中一些将在 design-time 上公开,并将进行硬编码。其他将在Web.config
中配置。有些将在 run-time 处动态计算。下面列出了这些:
client_id
- 此 MVC Web 应用程序的客户端 ID。
response_type
- OP 应使用的响应类型。在您的情况下,这将始终是
code
。 - 客户端请求的访问范围。这将至少包括
openid
. - OP 在对客户端进行身份验证和授权后将用户发送到的重定向 URI。
scope
redirect_uri
也可以发送其他请求参数。为了帮助您确定要发送的内容以及它们对流程的影响,请查看 oauth.tools。这就像“OAuth 和 OpenID Connect 的邮递员”。这是梦幻般的;你会爱上它。在那里,您可以使用各种参数形成各种 OAuth 和 OpenID 连接流。
一旦重定向到 OP,用户将进行身份验证。用户可能还必须同意客户端访问他们受保护的资源。无论如何,OP 之后会将用户重定向到回调。这是实现的第二部分。
在这里,我们将有一个 CallbackController
(或类似的东西)。它看起来像这样(最简单的形式):
public class CallbackController : Controller
{
public ActionResult Index()
{
try
{
string responseString = Helpers.Client.Instance
.GetToken(Request.QueryString["code"]);
SaveDataToSession(responseString);
}
catch (Exception e)
{
Session["error"] = e.Message;
}
return Redirect("/");
}
}
此代码段的重要部分是它从查询字符串中获取 code
,并向 OP 的令牌端点发出 HTTP POST 请求(也可通过解析 OP 的元数据)。如果成功,它会将响应保存在会话中供以后使用。 GetToken
方法看起来像这样:
public String GetToken(String code)
{
var values = new Dictionary<string, string>
{
{ "grant_type", "authorization_code" },
{ "client_id", client_id},
{ "client_secret", client_secret },
{ "code" , code },
{ "redirect_uri", redirect_uri}
};
HttpClient tokenClient = new HttpClient();
var content = new FormUrlEncodedContent(values);
var response = tokenClient.PostAsync(token_endpoint, content).Result;
if (response.IsSuccessStatusCode)
{
var responseContent = response.Content;
return responseContent.ReadAsStringAsync().Result;
}
throw new OAuthClientException("Token request failed with status code: " + response.StatusCode);
}
这会将代码发送到 OP 并获得访问令牌、ID 令牌,也许还有刷新令牌作为交换。此代码的重要部分是:
- 内容是URL-encoded不是JSON的形式。这是一个常见的错误。
- 再次包含先前发送的相同 重定向 URI。这是为了匹配 OP 中的两个请求。
grant_Type
总是authorization_code
。- 客户端以某种方式进行身份验证。在这种情况下,通过在请求中包含与先前发送的相同
client_id
以及client_secret
表单元素中的秘密。 - 使用的 HTTP 方法(正如我上面所说的)是 POST,而不是 GET。这也是一个常见的错误。
在我上面的示例中,我重定向回默认值 HomeController
。现在,执行 if 语句的 else 条件。在这里,它可以找到令牌:
<div>
@if(Session.Count == 0) {
// ...
} else {
@if(Session["id_token"] != null) {
<div>
ID Token:<br>
<pre>@Session["id_token"]</pre>
</div>
}
@if(Session["access_token"] != null) {
<div>
Access Token:<br>
<pre>@Session["access_token"]</pre>
</div>
}
@if(Session["refresh_token"] != null) {
<div>
Refresh Token:<br>
<pre>@Session["refresh_token"]</pre>
</div>
}
}
</div>
例子比较详细 t一个这个,但它希望能给你一个想法。通读一遍,查看自述文件,并享受学习更多关于 OpenID Connect 的乐趣!
您需要在不同的地方添加一些配置。我会尽力展示你需要的所有拼图。
在我的示例中,我将使用 OIDC 的 public IdentityServer4 演示版本,因此您可以与工作版本进行比较。
API
在任何控制器(或方法)中,添加 [Authorize]
属性,因此这将需要有效的身份验证。
如果您想更具体地说明用户可以执行的操作,您还可以添加策略。类似于:
[Authorize(Policy = "Read")]
[ApiController]
[Route("[controller]")]
public class HelloWorldsController : ControllerBase
{
[HttpGet]
public string Get()
{
return "Hello, World!";
}
}
在Startup.cs
的ConfigureServices
方法中,你需要添加类似这样的配置:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = "https://demo.identityserver.io";
options.Audience = "api";
});
// In case you want to work with policies
services.AddAuthorization(options =>
{
options.AddPolicy("Read", policy => policy.RequireClaim("scope", "api"));
});
以上配置要编译,需要添加NuGet包Microsoft.AspNetCore.Authentication.JwtBearer
。
在 Startup.cs
的 Configure
方法中,您需要在 app.UseAuthorization();
.
app.UseAuthentication();
MVC
在任何控制器(或方法)中,添加 [Authorize]
属性。每当您的 MVC 应用程序的用户点击具有此属性的方法时,都会自动触发登录过程。
为了演示这一点,我将把这个属性添加到一个方法中:
[Authorize]
public async Task<IActionResult> Privacy()
{
var httpClient = _httpClientFactory.CreateClient("ApiClient");
var apiResult = await httpClient.SendAsync(
new HttpRequestMessage(HttpMethod.Get, "/helloworlds"),
HttpCompletionOption.ResponseHeadersRead);
if (apiResult.IsSuccessStatusCode)
{
var content = await apiResult.Content.ReadAsStringAsync();
ViewData.Add("apiResult", content); // Just to demonstrate
}
return View();
}
在Startup.cs
的ConfigureServices
方法中,你需要添加类似这样的配置:
services.AddHttpContextAccessor();
services.AddTransient<BearerTokenHandler>();
services
.AddHttpClient("ApiClient", client =>
{
client.BaseAddress = new Uri("https://localhost:5001");
})
.AddHttpMessageHandler<BearerTokenHandler>();
services.AddHttpClient("IDPClient", client =>
{
client.BaseAddress = new Uri("https://demo.identityserver.io");
});
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = "https://demo.identityserver.io";
options.ClientId = "interactive.confidential";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true;
options.Scope.Add("api");
});
要编译上述配置,您应该添加 NuGet 包 Microsoft.AspNetCore.Authentication.Cookies
和 Microsoft.AspNetCore.Authentication.OpenIdConnect
.
在 Startup.cs
的 Configure
方法中,您需要在 app.UseAuthorization();
.
app.UseAuthentication();
由于 BearerTokenHandler
相当大,您可以从 a GitHub repository 复制它。您需要 IdentityModel
.
的 NuGet 包参考
此存储库还包含您要求的设置的完整工作示例。
最后,您可能想让用户可以注销。
您可以通过在您的视图中添加一个 link 来做到这一点:
@if (User.Identity.IsAuthenticated)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Logout">Logout</a>
</li>
}
为此匹配的控制器方法:
public IActionResult Logout()
{
return SignOut(
CookieAuthenticationDefaults.AuthenticationScheme,
OpenIdConnectDefaults.AuthenticationScheme);
}
应该是这样。希望您能够跟上所有的拼图。
如果有什么不清楚的地方,请告诉我。
没有足够的声誉向 IdentityServer4 答案添加评论,所以我就在这里提一下。
IS4 将不再免费用于商业用途: The Future of IdentityServer
The current version (IdentityServer4 v4.x) will be the last version we work on as free open source. We will keep supporting IdentityServer4 until the end of life of .NET Core 3.1 in November 2022.
To continue our work, we have formed a new company Duende Software, and IdentityServer4 will be rebranded as Duende IdentityServer. Duende IdentityServer will contain all new feature work and will target .NET Core 3.1 and .NET 5 (and all versions beyond).
This new product will remain open source but will be offered with a dual license (RPL and commercial). The RPL (reciprocal public license) keeps Duende IdentityServer free if you are also doing free open source work. If you are using Duende IdentityServer in a commercial scenario, then a commercial license will be required. We offer a variety of ways to license Duende IdentityServer in an attempt to accommodate the different company sizes and usage models. Including an RPL license is important to us because it allows us to recognize and express our gratitude to the open source community and our contributors.