OpenID 配置步骤

允许客户端基于授权服务器执行的身份验证来验证最终用户的身份,以及以可互操作和类似REST的方式获取关于最终用户的基本配置文件信息。

创建一个MVC客户端

1.新建一个ASP.NET Core MVC应用程序

2.配置 OpenID Connect 认证

在类StartupConfigureServices方法中添加以下代码:

 

 1 public void ConfigureServices(IServiceCollection services)
 2 {
 3     services.AddMvc();
 4 
 5     JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
 6 
 7     services.AddAuthentication(options =>
 8     {
 9         options.DefaultScheme = "Cookies";
10         options.DefaultChallengeScheme = "oidc";
11     })
12     .AddCookie("Cookies")
13     .AddOpenIdConnect("oidc", options =>
14     {
15         options.SignInScheme = "Cookies";
16 
17         options.Authority = "http://localhost:5000";
18         options.RequireHttpsMetadata = false;
19 
20         options.ClientId = "mvc";
21         options.SaveTokens = true;
22     });
23 }

AddAuthentication将认证服务添加到依赖注入容器中,使用Cookie作为验证用户的主要方法(通过"Cookies"作为 DefaultScheme)。

DefaultChallengeScheme 设置为"oidc"(OIDC是OpenID Connect的简称),因为当我们需要用户登录时,我们将使用OpenID Connect方案。

然后我们使用AddCookie添加可以处理Cookie的处理程序。

最后,AddOpenIdConnect用于配置执行OpenID Connect协议的处理程序。Authority表示id4服务的地址。 然后我们通过ClientId识别该客户端。SignInScheme 用于在OpenID Connect协议完成后使用cookie处理程序发出cookie。 而SaveTokens用于在Cookie中保存IdentityServer中的令牌(稍后将需要)。

然后确保在每个请求上执行认证服务,在Startup中的Configure方法添加UseAuthentication

 1 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
 2 {
 3     if (env.IsDevelopment())
 4     {
 5         app.UseDeveloperExceptionPage();
 6     }
 7     else
 8     {
 9         app.UseExceptionHandler("/Home/Error");
10     }
11 
12     app.UseAuthentication();
13 
14     app.UseStaticFiles();
15     app.UseMvcWithDefaultRoute();
16 }

验证中间件应该在MVC之前添加。

最后一步是触发认证。为了进入HomeController,并在其中一个Action上添加特性[Authorize]

还要修改该Action的View以显示用户的信息,例如:

1 <dl>
2     @foreach (var claim in User.Claims)
3     {
4         <dt>@claim.Type</dt>
5         <dd>@claim.Value</dd>
6     }
7 </dl>

如果您现在使用浏览器访问HomeController,将会导致重定向到IdentityServer,这将导致错误,因为MVC客户端尚未注册。

添加OpenID Connect Identity Scopes的支持

与OAuth 2.0类似,OpenID Connect也使用Scopes概念。 再次,Scopes代表您想要保护的客户端希望访问的内容。 与OAuth相反,OIDC中的范围不代表API,而是代表用户ID,姓名或电子邮件地址等身份信息。

Config.cs中添加如下代码:

1 public static IEnumerable<IdentityResource> GetIdentityResources()
2 {
3     return new List<IdentityResource>
4     {
5         new IdentityResources.OpenId(),
6         new IdentityResources.Profile(),
7     };
8 }

所有标准Scopes及其相应的声明都可以在OpenID Connect规范中找到。

然后,您需要将这些身份资源添加到Startup.cs中的IdentityServer配置中。使用AddInMemoryIdentityResources扩展方法调用AddIdentityServer()

 1 public void ConfigureServices(IServiceCollection services)
 2 {
 3     services.AddMvc();
 4 
 5     // configure identity server with in-memory stores, keys, clients and scopes
 6     services.AddIdentityServer()
 7         .AddDeveloperSigningCredential()
 8         .AddInMemoryIdentityResources(Config.GetIdentityResources())
 9         .AddInMemoryApiResources(Config.GetApiResources())
10         .AddInMemoryClients(Config.GetClients())
11         .AddTestUsers(Config.GetUsers());
12 }

为OpenID Connect implicit flow 添加客户端

Implicit Flow指的是使用OAuth2的Implicit流程获取Id Token和Access Token

最后一步是将MVC客户端的配置添加到IdentityServer。

基于OpenID Connect的客户端与我们迄今添加的OAuth 2.0客户端非常相似。 但是由于OIDC中的流程始终是交互式的,我们需要在配置中添加一些重定向URL。

将以下内容添加到您的客户端配置:

 1 public static IEnumerable<Client> GetClients()
 2 {
 3     return new List<Client>
 4     {
 5         // other clients omitted...
 6 
 7         // OpenID Connect implicit flow client (MVC)
 8         new Client
 9         {
10             ClientId = "mvc",
11             ClientName = "MVC Client",
12             AllowedGrantTypes = GrantTypes.Implicit,
13 
14             // where to redirect to after login
15             RedirectUris = { "http://localhost:5002/signin-oidc" },
16 
17             // where to redirect to after logout
18             PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
19 
20             AllowedScopes = new List<string>
21             {
22                 IdentityServerConstants.StandardScopes.OpenId,
23                 IdentityServerConstants.StandardScopes.Profile
24             }
25         }
26     };
27 }

测试客户端

通过访问受保护的Action来触发身份验证握手。 你应该看到重定向到IdentityServer的登录页面。

成功登录后,用户将看到同意画面。 在这里,用户可以决定是否要将他的身份信息发布到客户端应用程序。

可以使用客户端对象上的RequireConsent属性以每个客户端为基础关闭同意询问。

最后浏览器重定向到客户端应用程序,该应用程序显示了用户的声明。

在开发过程中,您有时可能会看到一个异常,说明令牌无法验证。 这是因为签名密钥信息是即时创建的,并且只保存在内存中。 当客户端和IdentityServer不同步时,会发生此异常。 只需在客户端重复操作,下次元数据已经追上,一切都应该正常工作。

添加注销

最后一步是给MVC客户端添加注销功能。

使用IdentityServer等身份验证服务,仅清除本地应用程序Cookie是不够的。 此外,您还需要往身份服务器交互,以清除单点登录会话。

确切的协议步骤在OpenID Connect中间件内实现,只需将以下代码添加到某个控制器即可触发注销:

1 public async Task Logout()
2 {
3     await HttpContext.SignOutAsync("Cookies");
4     await HttpContext.SignOutAsync("oidc");
5 }

这将清除本地cookie,然后重定向到IdentityServer。 IdentityServer将清除它的cookie,然后给用户一个链接返回到MVC应用程序。

进一步实验

如上所述,OpenID Connect中间件默认要求配置 profile scope。 这个scope还包括像名字或网站这样的声明。

让我们将这些声明添加到用户,以便IdentityServer可以将它们放入身份令牌中:

 1 public static List<TestUser> GetUsers()
 2 {
 3     return new List<TestUser>
 4     {
 5         new TestUser
 6         {
 7             SubjectId = "1",
 8             Username = "alice",
 9             Password = "password",
10 
11             Claims = new []
12             {
13                 new Claim("name", "Alice"),
14                 new Claim("website", "https://alice.com")
15             }
16         },
17         new TestUser
18         {
19             SubjectId = "2",
20             Username = "bob",
21             Password = "password",
22 
23             Claims = new []
24             {
25                 new Claim("name", "Bob"),
26                 new Claim("website", "https://bob.com")
27             }
28         }
29     };
30 }

下一次您进行身份验证时,你的声明页面现在将显示额外的声明。

OpenID Connect中间件上的Scope属性是您配置哪些Scope将在身份验证期间发送到IdentityServer。

值得注意的是,对令牌中身份信息的遍历是一个扩展点 - IProfileService。因为我们正在使用 AddTestUser,所以默认使用的是 TestUserProfileService。你可以检出这里的源代码来查看它的工作原理。

Demo下载地址

https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/3_ImplicitFlowAuthentication

参考官方文档:https://identityserver4.readthedocs.io/en/release/quickstarts/3_interactive_login.html

官方的Demo已经更新到最新的.NET Core 2.0

posted @ 2018-05-29 09:27  努力的喵喵喵  阅读(817)  评论(0编辑  收藏  举报