如何使用不记名令牌从 ELSA 工作流的 SendHttpRequest activity 中调用身份服务器保护的 API 资源

How to call an identity server protected API resource from within ELSA workflow's SendHttpRequest activity using bearer token

我已经使用 Identity Server 4 配置我的 Elsa 客户端应用程序。下面是身份验证的扩展方法。

 public static void AddCustomAuthentication(this IServiceCollection services, IConfiguration Configuration)
        {
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie(options =>
            {
                options.Cookie.Name = "myElsaApp";
            })
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = "https://localhost:5000";

                options.ClientId = "myElsaApp"; 
                options.ClientSecret = "secretpassword"; 
                options.ResponseType = "code";
                options.SaveTokens = true;

                // request access to scopes
                ...

                // get claims
                options.GetClaimsFromUserInfoEndpoint = true;
            });

            var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        }

这里是授权的扩展方法

 public static void AddCustomAuthorization(this IServiceCollection services)
        {
            services.AddAuthorization(options =>
            {
                options.FallbackPolicy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
            });
        }

我在 Startup.cs 中调用了上述两种扩展方法 当我 运行 应用程序时,它要求输入用户名和密码。在身份验证成功后,我希望来自 Identity Server 4 的访问令牌存储在我的 HttpContext 中。

Objective

我有一个受身份服务器保护的网站 API。这意味着客户端应用程序(在我的例子中是 elsa 应用程序)必须发送不记名令牌才能调用此 API.

我的方法

虽然我可以从 HttpContext 中提取我的访问令牌,但我可以将其注入到我的客户端应用程序中。然后使用该访问令牌我可以调用任何受保护的 APIs。为此,我想 extend the javascript 以便我可以使用 accessToken 函数作为 Authorization 输入字段的表达式求值器 SendHttpRequest activity 在设计工作流程时在 Elsa 仪表板中。这是 GetAccessToken.cs

的代码
public class GetAccessToken : INotificationHandler<EvaluatingJavaScriptExpression>
    {
        private HttpContext _HttpContext;
        public GetAccessToken(IHttpContextAccessor HttpContextAccessor)
        {
            _HttpContext = HttpContextAccessor.HttpContext;
        }
        public async Task Handle(EvaluatingJavaScriptExpression notification, CancellationToken cancellationToken)
        {
            var engine = notification.Engine;
            var accessToken = await _HttpContext.GetTokenAsync("Cookies", "access_token");
            engine.SetValue("accessToken", accessToken);
        }
    }

注入 HttpContext 以下行已添加到我的 Startup.cs

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

问题

当我 运行 代码并触发应该计算 JavaScript 表达式的工作流时。我收到以下错误消息。

看起来 HttpContextAccessor 正在返回 null。

我需要知道在携带 Bearer 令牌时使用 SendHttpRequest 从 Elsa 工作流中调用 API 的最佳方式。 任何帮助将不胜感激。

您似乎在尝试实现某种 machine-to-machine 交互。
在这种情况下,您可以考虑使用 client credentials flow 而不是您当前使用的 authorization code 流。
这意味着您需要将另一个 client 添加到具有相应设置的 IdentityServer4 配置中。然后开始使用新的 IdentityServer 客户端,而不是在任何地方传递前端的 accessToken,在这种特殊情况下是服务器端客户端。

说缺点。好吧,很可能您需要有关当前用户的一些信息,而您的新服务器端 accessToken 内部不会有此类详细信息(因为它不是用户在这里启动进程,而是服务)。
在这种情况下,我可能会建议添加另一个方法或控制器,其中包含一些新参数,例如 userId。可以通过 policies.

仅从指定的 IdentiyServer4 客户端访问此方法或控制器