c# - 在同一应用程序项目上对 API 使用 Bearer Token 身份验证,对 MVC 使用 OpenId 身份验证

标签 c# asp.net-mvc-4 oauth-2.0 openid owin

我正在尝试通过 Identity Server 在我的应用程序上同时使用 OpenId 和 Bearer token 身份验证。

目前的问题是,一旦我对用户进行了身份验证,我仍然需要获得不记名 token 才能为我的 Asp.Net MVC 应用程序调用任何操作方法。

这是我的应用程序的启动文件

 public class Startup
{
     public void Configuration(IAppBuilder app)
     {            
         AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
         JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
         app.UseCookieAuthentication(new CookieAuthenticationOptions
         {
            AuthenticationType = "Cookies"
         });

         app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
         {
            Authority = "https://localhost:44301/identity",
            ClientId = "baseballStats",
            Scope = "openid profile roles baseballStatsApi",
            RedirectUri = "https://localhost:44300/",
            ResponseType = "id_token token",
            SignInAsAuthenticationType = "Cookies",
            UseTokenLifetime = false,
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = async n =>
                {
                    var userInfoClient = new UserInfoClient(
                                 new Uri(n.Options.Authority + "/connect/userinfo"),
                                 n.ProtocolMessage.AccessToken);

                    var userInfo = await userInfoClient.GetAsync();

                    // create new identity and set name and role claim type
                    var nid = new ClaimsIdentity(
                       n.AuthenticationTicket.Identity.AuthenticationType,
                        Constants.ClaimTypes.GivenName,
                        Constants.ClaimTypes.Role);

                    userInfo.Claims.ToList().ForEach(c => nid.AddClaim(new Claim(c.Item1, c.Item2)));

                    // keep the id_token for logout
                    nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                    // add access token for sample API
                    nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                    // keep track of access token expiration
                    nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                    // add some other app specific claim
                    nid.AddClaim(new Claim("app_specific", "some data"));

                    n.AuthenticationTicket = new AuthenticationTicket(
                        nid,
                        n.AuthenticationTicket.Properties);
                }
            }
         });



         app.UseResourceAuthorization(new AuthorizationManager());

         app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
         {
             Authority = "https://localhost:44301/identity",
             RequiredScopes = new[] { "baseballStatsApi" }
         });

         var config = new HttpConfiguration();
         config.MapHttpAttributeRoutes();
         app.UseWebApi(config);           
     }
}

我想将不记名 token 身份验证限制为仅对我的 api url 进行身份验证,并对其他所有内容使用 openID 身份验证。有办法吗?

最佳答案

好的,我在下面的帖子中找到了一些信息

https://github.com/IdentityServer/IdentityServer3/issues/487

可以在此处找到实现链接中讨论的概念的 github 存储库

https://github.com/B3nCr/IdentityServer-Sample/blob/master/B3nCr.Communication/Startup.cs

基本上,您需要使用 app.Map() 将 api url 映射到不同的配置。就我而言,我将启动文件更改为如下所示。

 public class Startup
{
     public void Configuration(IAppBuilder app)
     {
         AntiForgeryConfig.UniqueClaimTypeIdentifier = Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Subject;
         JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

         app.UseCookieAuthentication(new CookieAuthenticationOptions
         {
             AuthenticationType = "Cookies"
         });

         var openIdConfig = new OpenIdConnectAuthenticationOptions
         {
             Authority = "https://localhost:44301/identity",
             ClientId = "baseballStats",
             Scope = "openid profile roles baseballStatsApi",
             RedirectUri = "https://localhost:44300/",
             ResponseType = "id_token token",
             SignInAsAuthenticationType = "Cookies",                 
             UseTokenLifetime = false,
             Notifications = new OpenIdConnectAuthenticationNotifications
             {
                 SecurityTokenValidated = async n =>
                 {
                     var userInfoClient = new UserInfoClient(
                                  new Uri(n.Options.Authority + "/connect/userinfo"),
                                  n.ProtocolMessage.AccessToken);

                     var userInfo = await userInfoClient.GetAsync();

                     // create new identity and set name and role claim type
                     var nid = new ClaimsIdentity(
                        n.AuthenticationTicket.Identity.AuthenticationType,
                         Thinktecture.IdentityServer.Core.Constants.ClaimTypes.GivenName,
                         Thinktecture.IdentityServer.Core.Constants.ClaimTypes.Role);

                     userInfo.Claims.ToList().ForEach(c => nid.AddClaim(new Claim(c.Item1, c.Item2)));

                     // keep the id_token for logout
                     nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                     // add access token for sample API
                     nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                     // keep track of access token expiration
                     nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                     // add some other app specific claim
                     nid.AddClaim(new Claim("app_specific", "some data"));

                     n.AuthenticationTicket = new AuthenticationTicket(
                         nid,
                         n.AuthenticationTicket.Properties);

                     n.Request.Headers.SetValues("Authorization ", new string[] { "Bearer ", n.ProtocolMessage.AccessToken });
                 }
             }
         };

         app.UseOpenIdConnectAuthentication(openIdConfig);

         app.UseResourceAuthorization(new AuthorizationManager());

         app.Map("/api", inner =>
         {
             var bearerTokenOptions = new IdentityServerBearerTokenAuthenticationOptions
             {
                 Authority = "https://localhost:44301/identity",
                 RequiredScopes = new[] { "baseballStatsApi" }
             };

             inner.UseIdentityServerBearerTokenAuthentication(bearerTokenOptions);
             var config = new HttpConfiguration();
             config.MapHttpAttributeRoutes();
             inner.UseWebApi(config);
         });                                                 
     }
}

这解决了我的问题。我现在可以使用基于 cookie 的身份验证访问 MVC 页面,并使用不记名 token 身份验证调用 API。

关于c# - 在同一应用程序项目上对 API 使用 Bearer Token 身份验证,对 MVC 使用 OpenId 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30881720/

相关文章:

asp.net-mvc - Razor v2 中的条件属性

c# - MVC 路由去掉 URL 中的/Index

authentication - SimpleMembership 在本地工作但发布时找不到 SqlServier 实例

java - 从字符串在 Android 上创建 X509Certificate

c# - ASP.Net C# - 动态删除控件

c# - 如何等待 BackgroundWorker 完成然后退出控制台应用程序

node.js - 如何撤销 Google OAuth 提供的 token ? NodeJS

security - 如何通过 OAuth2 身份验证保护私有(private)数据?

c# - 免费的 OCR SDK for .net 可以将文本、表格格式和图像提取到 Office word 文档中

c# - Linq Reverse - 它是改变变量还是复制