Reputation: 27
I have configured my Elsa client app with Identity Server 4. Below is the extension method for Authentication.
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();
}
And here is the extension method for Authorization
public static void AddCustomAuthorization(this IServiceCollection services)
{
services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
I am calling both above extension methods in my Startup.cs When I run the application, it asks for username and password. and after the successfull authentication I am expecting the access token from Identity Server 4 to be stored in my HttpContext.
Objective
I have a web API protected by identity server. Which means the client app (elsa app in my case) must send a bearer token to be able to call this API.
My Approach
I though I would be able to extract my access token from HttpContext which I can Inject in my client app. And then using that access token I can call any protected APIs. For this purpose I wanted to extend the javascript so that I can use accessToken function as expression evaluator for Authorization input field of SendHttpRequest activity in Elsa dashboard while designing the workflow. Here is the code for 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);
}
}
To inject HttpContext following line was added to my Startup.cs
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
Problem
When I run the code and trigger the workflow that is supposed to evaluate the JavaScript expression. I get the following error message.
Looks like the HttpContextAccessor is returning null.
I need to know the best way to call an API from within Elsa workflow using SendHttpRequest while carrying Bearer token. Any help would be appreciated.
Upvotes: 0
Views: 884
Reputation: 1163
It looks like you trying to implement some kind of machine-to-machine interaction.
In this case you can consider using client credentials flow instead of authorization code
flow which you are currently using.
That means you need to add another client into IdentityServer4 config with corresponding settings. And then instead of passing your frontend's accessToken everywhere you start using new IdentityServer client, server-side one in this particular case.
Talking about disadvantages. Well, most likely you need some information about current user and your new server-side accessToken won't have such kind of details inside (because it's not a user who is starting a process here, but a service).
In this case I might suggest adding another method or controller with some new parameters like userId
, for example. This method or controller can be made accessible from only specified IdentiyServer4 clients through policies.
Upvotes: 3