Intro / context
I have a .NET Core application and I know nothing about .NET Core which puts me in prime position for not finding a solution to this for me way too complex problem.
The application is built in a standard way. There is a Startup.cs
where all kind of configuration for the dependency injection magic is done.
There is also a configuration for a downstream API.
services
.AddMicrosoftIdentityWebApiAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamWebApi(
"MyDownstreamApi",
Configuration.GetSection("MyDownstreamApi"))
.AddInMemoryTokenCaches()
Initial situation
I have a very long running process that is executed in one method of a controller. Namely the "handle" for a simple GET request that starts some heavy logic and at some point will return with a result. The method in the controller is waiting for this and only returns 200 AFTER that process is finished. That process involves calling a downstream API on-behalf-of the requesting user. In principle this works and worked in the past with current setup and configuration. BUT, in some cases the process takes too long and runs into the overall hardcoded timeout in .NET. OF COURSE, it is really bad practise in REST to keep a client waiting for 30seconds until you return a result.
Naive refactoring
So, I refactored this in a hacky way (just want to see it working in principle) and theoretically the code looks good to me.
- the method
X
in the controller starts the taskA
containing the logic that takes way too much time X
also registersA
in a singleton registry- singleton registry returns a
<guid>
as a price back toX
X
returns now back to client with 200 and<guid>
=> Now, the client can come back to API anytime with that <guid>
to request current status of the task and eventually result of the task.
For this the API now has (pseudo endpoints).
PUT /long-running-logic
(starts and returns<guid>
)GET /long-running-logic/status/<guid>
(for getting status)GET /long-running-logic/<guid>
(for getting the result after status told you "I am done")
Problem
The way-too-much-time-logic involves calling the downstream API on-behalf-of the user at some point. Sadly that point of time is when the request was already answered and user context is gone in API (that is my interpretation of Microsoft.Identity.Client.MsalUiRequiredException , ErrorCode: user_null
).
So I went back to research / documentation / ... I found long-running OBO processes. This has to be it, I think. But how in hell do I wire this together so it works? Here I am done and defeated.
Keep in mind, I have the additional point of the downstream API that isn't covered there.
I found out how to create a IConfidentialClientApplication
(I added that one to Startup.cs
) but the code I added doesn't really make any sense to me. It would be more than magic if that would work - so I expected it to not work and it doesn't work ouf course. There is the Microsoft.Identity.Client.MsalUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application with ID ...
error.
Is there somewhere a working example of such a use case?
In Node.js I would just keep the access_token
when user requests for the first time somewhere and request a new one on-behalf-of at the time I need it for calling my downstream API in such a long running process... simple as that... But, here in .NET Core with all this blackbox magic configuration interface what-ever things going on I am completely lost and don't know which documentation I have to find to finally understand this .... :(
Btw. I have now the idea of just taking an approach bypassing all that .NET Core magic and just using simple HttpClient calls, doing the requesting on-behalf-of token by myself, controlling initial users access_token
also by myself.
Any hints / help?
Thanks!