MVC客户端(IdentityServer)自动获取access_token

Automatically get access_token in MVC client (IdentityServer)

我像在“创建 MVC 客户端”中一样编写“MVC 客户端”https://identityserver4.readthedocs.io/en/latest/quickstarts/2_interactive_aspnetcore.html#creating-an-mvc-client 我的主要目标是在 access_token 过期时用 refresh_token 获得新的。 我需要它不是为了 API 访问,而是为了“MVC 客户端”authentication/authorization.

所以,我想在“MVC 客户端”问题重定向到 IdentityServer 到它的登录页面之前(http://localhost:5000/connect/authorize?client_id=mvc&redirect_uri=bla,bla,bla)只是拦截它并发送而不是它只是获取新的 access_token(使用 refresh_token) w/o 用户需要输入他的凭据。

所以,我只需要在“MVC 客户端”决定 access_token 不再有效并尝试重定向到 IdentityServer 登录之前获取任何事件。

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";

        })                
            .AddCookie("Cookies", options => {
                options.Cookie.Name = "MyCookie";
                options.Cookie.MaxAge = new TimeSpan(0, 0, 60);
                options.ExpireTimeSpan = new TimeSpan(0, 0, 60);
                options.SlidingExpiration = false;

                //options.Cookie.s ExpireTimeSpan   = new TimeSpan(0, 0, 1);


                options.Events = new Func<CookieAuthenticationEvents>(() =>
                {
                    var cookieAuthenticationEvents = new CookieAuthenticationEvents( );

                    var f = cookieAuthenticationEvents.OnRedirectToLogin;
                    var f1 = cookieAuthenticationEvents.OnValidatePrincipal;
                    var f2 = cookieAuthenticationEvents.OnSignedIn;

                    cookieAuthenticationEvents.OnRedirectToLogin = ( context ) =>
                    {
                        return f(context);
                    };
                    cookieAuthenticationEvents.OnValidatePrincipal = ( context ) =>
                    {
                        return f1(context);
                    };
                    cookieAuthenticationEvents.OnSignedIn = ( context ) =>
                    {
                        return f2(context);
                    };

                    return cookieAuthenticationEvents;
                }
                )( );
            })
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = "http://localhost:5000";
                options.RequireHttpsMetadata = false;

                options.ClientId = "mvc";
                options.ClientSecret = "secret";
                options.ResponseType = "code";       
                options.SaveTokens = true;

                options.Scope.Add("email");
                options.Scope.Add("api1");
                options.Scope.Add("offline_access");


      //          options.Events = new Func<>


            options.Events = new Func<OpenIdConnectEvents>(() =>
            {
                var openIdConnectEvents = new OpenIdConnectEvents( );
                var f = openIdConnectEvents.OnAuthenticationFailed;
                var f1 = openIdConnectEvents.OnAccessDenied;
                var f2 = openIdConnectEvents.OnTokenValidated;
                var f3 = openIdConnectEvents.OnAccessDenied;
                openIdConnectEvents.OnAuthenticationFailed = ( context ) =>
                {
                    return f(context);
                };
                openIdConnectEvents.OnAccessDenied = ( context ) =>
                {
                    return f1(context);
                };
                openIdConnectEvents.OnTokenValidated = ( context ) =>
                {
                    return f2(context);
                };
                openIdConnectEvents.OnAccessDenied = ( context ) =>
                {
                    return f3(context);
                };

                return openIdConnectEvents;
            }
                )( );

            });
    }

"return f3(context);" 的每一行上,我都设置了断点,希望在到达 IdentityServer 的登录页面之前击中它——运气不好。

这是客户端配置。

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

                AllowedGrantTypes = GrantTypes.Code,
                RequireConsent = false,
                RequirePkce = true,

                // where to redirect to after login
                RedirectUris = { "http://localhost:5002/signin-oidc" },

                // where to redirect to after logout
                PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

                AllowedScopes = new List<string>
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.Email,
                    "api1"
                },

                AlwaysIncludeUserClaimsInIdToken = true,
                AllowOfflineAccess = true,

                AccessTokenLifetime = 150,
                AuthorizationCodeLifetime = 150,
                UserSsoLifetime = 150
            }

如何操作 - 自动刷新令牌w/o MVC 客户端身份验证的用户交互(不适用于 API 访问)

我找到了解决办法。这里是: https://github.com/leastprivilege/AspNetCoreSecuritySamples/tree/aspnetcore21/AutomaticTokenManagement

这里的重点是重写这个方法

public override async Task ValidatePrincipal ( CookieValidatePrincipalContext context )

来自 class

Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents