IdentityServer4 从 .net framework 4.6 开始。

4
我的问题是关于Identity Server 4和从已有的.NET框架MVC应用程序调用它。
我已经按照ID4的“快速入门”指南进行操作,使其可运行并正确响应示例.NET Core MVC应用程序。
作为一个快速测试,我创建了一个基本的.NET Framework MVC应用程序,并创建了一个启动.cs文件...
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
using System.Collections.Generic;
using System.IdentityModel.Tokens;

[assembly: OwinStartup(typeof(MVC_OWIN_Client.Startup))]

namespace MVC_OWIN_Client
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            string baseClientAddress = "http://localhost:44301/";

            var authority = JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

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

            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId = "mvc.standard",
                Authority = "http://localhost:5000/",
                RedirectUri = baseClientAddress + "signin-oidc",
                PostLogoutRedirectUri = baseClientAddress + "signout-callback-oidc",
                ResponseType = "code id_token",
                Scope = "openid api1 offline_access",

                UseTokenLifetime = false,
                SignInAsAuthenticationType = "Cookies"
            });
        }
    }
}

在ID4配置中,我创建了一个客户端以匹配...
 public static IEnumerable<Client> GetClients()
 {

    ...

    new Client
        {
        ClientId = "mvc.standard",
            ClientName = "MVC Client2",
            AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },

            RedirectUris           = { "http://localhost:44301/signin-oidc" },
            PostLogoutRedirectUris = { "http://localhost:44301/signout-callback-oidc" },

            AllowedScopes =
            {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "api1"
            },
            AllowOfflineAccess = true
    }
};

应用程序将通过登录和权限页面进行进度,最终ID4指示用户已登录....
info: IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator[0]
      User consented to scopes: openid, api1, offline_access
info: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint[0]
      Authorize endpoint response
      {
        "SubjectId": "2",
        "ClientId": "mvc.standard",
        "RedirectUri": "http://localhost:44301/signin-oidc",
        "State": "OpenIdConnect.AuthenticationProperties=pnxKmthLCWSNS1Tj8sBS1K4K-Erxq8_W3Sfj1gg3zXhTCqP-gKV-Hsfgh_pRLPYQcIdVJONhzA3VMdBNv4xqE7y8uX-pzEmeNKBYb0cPAh6Q9lm5knIS5ds9gccYKubK1U0NpnGAW7tw38brRzD7dEG-EkSgXqjnEGeS4pMCrFaG2CFwq08_-KyA85VufscpT3y9sL0hTLLYYbRiJhWIZBOM427piwaHpR-jbl7KXGo",
        "Scope": "openid api1 offline_access"
      }
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[10]
      AuthenticationScheme: idsrv signed in.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 152.1613ms 200 text/html; charset=UTF-8

就是这样。MVC应用程序从未被恢复,它一直存在直到超时。

有没有人有Identity Server的经验并能告诉我是否有遗漏的内容?提前感谢您的时间,Andy。


你能解释一下“它会一直等待直到超时”是什么意思吗?你的代码看起来很好。 - Camilo Terevinto
在登录和权限请求页面之后,浏览器会变成空白,并在地址栏中显示以下内容:"http://localhost:5000/connect/authorize/callback?client_id=mvc.framework&redirect_uri=http%3A%2F%2Flocalhost%3A44301%2Fsignin-... &x-client-SKU=ID_NET&x-client-ver=1.0.40306.1554"。直到浏览器超时之前,它都会保持空白状态。 - Andy Walker
确实很奇怪。您应该在Identity Server的Github上发布一个bug,他们应该能够更快地发现问题。 - Camilo Terevinto
1
超时后,我的浏览器地址栏中显示了http://localhost:44301/signin-oidc,并在浏览器中显示ERR_CONNECTION_RESET。我已经阅读过MS Owin(Katana Bug#197)中存在一个错误,因此我添加了一个调用app.UseKentorOwinCookieSaver(),但这也没有任何效果。 - Andy Walker
1
哈哈... https://github.com/IdentityServer/IdentityServer4/issues/2059 - Andy Walker
4个回答

1

对于那些在此方面苦苦挣扎,无法找到清晰指导的人,答案是根本不要使用UseOpenIdConnectAuthentication。在您的.net框架mvc应用程序中使用WSFederationAuthentication...

Startup.cs :-

using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.WsFederation;
using Owin;

[assembly: OwinStartup(typeof(MvcOwinWsFederation.Startup))]

namespace MvcOwinWsFederation
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
            {
                MetadataAddress = "http://localhost:5000/wsfederation",
                Wtrealm = "urn:owinrp",

                SignInAsAuthenticationType = "Cookies"
            });
        }
    }
}

在IdentityServer4中设置一个客户端以进行测试:

public static IEnumerable<Client> GetClients()
        {
            return new[]
            {
                new Client
                {
                    ClientId = "urn:owinrp",
                    ProtocolType = ProtocolTypes.WsFederation,

                    RedirectUris = { "http://localhost:10313/" },
                    FrontChannelLogoutUri = "http://localhost:10313/home/signoutcleanup",
                    IdentityTokenLifetime = 36000,

                    AllowedScopes = { "openid", "profile" }
                }
            }
         }

确保身份验证服务器4在其startup.cs中启用了此功能...
public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            var cert = new X509Certificate2(Path.Combine(Directory.GetCurrentDirectory(), "idsrvtest.pfx"), "idsrv3test");

            services.AddIdentityServer()
                .AddSigningCredential(cert)
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddTestUsers(TestUsers.Users)
                **.AddWsFederation();**
...
}

应该都可以工作。在这里找到了这个...

https://leastprivilege.com/2017/03/03/extending-identityserver4-with-ws-federation-support/

安迪。


Open Id Connect 是一种协议,它被所有服务器端技术所支持。在某些技术中,例如 asp.net core 中,你可以直接使用它,而无需额外实现。但如果在 asp.net .net framework 中没有现成的解决方案,我们就需要自己来实现。 - Ashish Patel

1
请使用以下设置将Identity Server 4 OpenID Connect与ASP.NET MVC .NET Framework cookie基础身份验证集成。
请确保已安装以下NuGet包。

Microsoft.Owin.Security

Microsoft.Owin.Security.Cookies

Microsoft.Owin.Security.OpenIdConnect

注意:将端口号更新为您的应用程序本地主机端口
public void Configuration(IAppBuilder app)
            {
   app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions {});

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            AuthenticationType = "oidc",
            SignInAsAuthenticationType = "Cookies",
            Authority = "http://localhost:5000/",
            RedirectUri = "http://localhost:44301/signin-oidc",
            PostLogoutRedirectUri = "http://localhost:44301/signout-callback-oidc",
            ClientId = "CP",
            ResponseType = "id_token",
            Scope = "openid profile",
            UseTokenLifetime = false,
            RequireHttpsMetadata = false,
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = (context) =>
                {
                    var identity = context.AuthenticationTicket.Identity;
                    var name = identity.Claims.FirstOrDefault(c => c.Type == identity.NameClaimType)?.Value;

                    return Task.FromResult(0);
                }
            }
        });
    }

你的“解决方案”并不起作用,但你却对一个使用ws-federation并且是由身份服务器的一位作者提供示例的解决方案进行了投票。 - Andy Walker
提到解决方案已经在我的应用程序中正常工作,我认为您可能遗漏了某些东西,请分享我们的代码以进一步调查。 - Ashish Patel
你使用什么作为授权属性?我想在控制器上执行策略,但我不知道该如何做... :( - user2173353
你好,你可以使用以下事件生成身份验证的 Cookie 或会话来管理应用程序级别的用户策略。 SecurityTokenValidated = (context) => { var identity = context.AuthenticationTicket.Identity; var name = identity.Claims.FirstOrDefault(c => c.Type == identity.NameClaimType)?.Value; //TODO: 生成身份验证票据、Cookie 或会话 return Task.FromResult(0); } - Ashish Patel

1
我使用了.NET框架4.6.1创建Web API,身份提供者方面,我使用Identity Server 4(之前使用的是Identity Server 3)。一开始我遇到了问题,但我想出了这个解决方法,它对我非常有效。请注意,我正在使用ClientCredentials授权流程。
我正在使用相同的IdentityServer3.AccessTokenValidation库进行令牌验证。诀窍是针对Introspection端点进行定位。以下是我使用的配置。
这是Web API的配置,设置ValidationMode属性至关重要。
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
        {
            Authority = ConfigurationManager.AppSettings["AuthServerURI"],
            RequiredScopes = new[] { "comp-read", "stats-read" },
            ClientId = "apiname",
            ClientSecret = "apisecret",
            ValidationMode = ValidationMode.ValidationEndpoint,
            EnableValidationResultCache = true
        });

这是我的IDP中配置APIResource和Client的方式。
new ApiResource
            {
                Name = "apiname",
                DisplayName = "Web API",
                Description = "Access to Web API Services",
                ApiSecrets = new List<Secret> {new Secret("apisecret".Sha256())},
                Scopes = new List<Scope> {
                    new Scope("comp-read", "Read access to Comp Db API"),
                    new Scope("stats-read", "Read access to Stats API")
                }

这是一个客户端的配置方式。
new Client
            {
                ClientName = "name of the client",
                ClientId = "clientname",
                Enabled = true,
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                ClientSecrets = new List<Secret> {
                    new Secret("secretforclient".Sha256())
                },
                AllowedScopes = new List<string>
                {
                    "stats-read"
                },
                AccessTokenLifetime = 1000
            }

希望这有所帮助。谢谢。


使用IdentityServer4时,您不能再使用IdentityServer3.AccessTokenValidation。虽然它可以编译通过,但由于版本/引用的一些内部问题,它无法加载。那么,如何在没有对IdentityServer3.AccessTokenValidation NuGet的引用的情况下完成此操作呢? - nivs1978
我正在使用它,它的工作方式就像一个宝石一样。我的API是使用.NET Framework 4.6.1编写的。在这个项目中,我正在使用IdentityServer3.AccessTokenValidation来验证从IdentityServer4的Introspection端点生成的令牌。 - Vinay Kumar
我一直没能找到任何可用的样例。我有一个Web UI(MVC),控制器正在调用另一个API(rest/json)。我需要使用Identity Server 4保护Web UI,并从控制器中解析令牌到rest/json API。全部在.NET 4.x中实现。但我无法找到任何可用的样例或让它起作用。我已经苦苦挣扎了几天。但如果您使用Identity Server 3 NuGet包使其正常工作,我会再次尝试。 - nivs1978
@Vinay 我尝试了你的解决方案,但我仍然收到未经授权的错误。 - DevSay
@nivs1978 你是否成功解决了这个问题,或者如果你还记得的话,有没有可行的例子? - Prany
@Prany 是的,我会在周一尝试找到示例。不过我发现WinForm可以在.Net 6中编译,这使得事情变得更加容易。但是我会为你找到一个可用的.Net 4.6示例。 - nivs1978

0

这是一个关于如何在NET4.6中实现IndentityServer4的更新示例(2020年),包括PKCE。

博客:刷新您的传统ASP.NET IdentityServer客户端应用程序(使用PKCE)
Github:ScottBrady91.BlogExampleCode.AspNetPkce

PKCE部分太长了,但基本配置如下。请注意,在URL配置中没有signin-oidc / signout-callback-oidc后缀!

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "cookie"
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            ClientId = "mvc.owin",
            Authority = "http://localhost:5000",
            RedirectUri = "http://localhost:5001/",
            ResponseType = "code id_token",
            Scope = "openid profile api1",

            SignInAsAuthenticationType = "cookie",

            UseTokenLifetime = false,

            RedeemCode = true,
            SaveTokens = true,
            ClientSecret = "secret"
        });
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接