Reputation: 141
I have one API and one Client app (Blazor web assembly) separately.
The client app authenticates users through the Azure active directory. In the client when I have saved any file through API, I am using static files configured on Startup.cs
such as :
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(@"c:\", @"Resources")),
RequestPath = new PathString("/secureFile"),
});
The problem is the client application is working fine. But if someone inspects the Html and gets the image source they can directly access the files through the browser like https://localhost:44397/secureFile/profile.jpg
On the other hand, because I am using Azure active directory login, the API does not save any user information. That's why I can't use the scenario like:
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(Path.Combine(@"c:\", @"Resources")),
RequestPath = new PathString("/secureFile"),
OnPrepareResponse = ctx =>
{
if (!ctx.Context.User.Identity.IsAuthenticated)
{
// respond HTTP 401 Unauthorized.
ctx.Context.Response.StatusCode = (int) HttpStatusCode.Unauthorized;
ctx.Context.Response.ContentLength = 0;
ctx.Context.Response.Body = Stream.Null;
// ctx.Context.Response.Redirect("/")
}
}
});
Here the !ctx.Context.User.Identity.IsAuthenticated
is always false even the client application is calling.
May Client application is Authenticating though :
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Audience = Configuration["AAD:ResourceId"];
options.Authority = $"{Configuration["AAD:InstanceId"]}{Configuration["AAD:TenantId"]}";
});
My goal is to give access to the https://localhost:44397/secureFile/profile.jpg
if the client application is calling the image source. But should block if anyone calls through the URL directly.
Any lead will help me a lot. I have already followed article but no use in my scenario because I am using AAD login.
Upvotes: 1
Views: 1874
Reputation: 3877
You mention that "the API does not save any user information," but regardless of the authentication flow, some authentication information has to be established even transiently for the individual request so that authorization can be evaluated.
In the example code you have listed, you're invoking a check on the HttpContext User claims principal to see if the user is authenticated, and you mention it's always coming back as false, even if it's coming from your client application. What's notable here is that something has to invoke the authentication flow in an application before authorization can be performed. Because nothing in the StaticFileMiddleware inherently does this, it probably never is happening during that request.
You can invoke that authentication flow yourself through the use of the ChallengeAsync()
method, which is intended to "challenge the current request using the default challenge scheme. An authentication challenge can be issued when an unauthenticated user requests an endpoint that requires authentication":
You may need to customize the behavior for your particular case, especially if you have to accommodate multiple schemes, but a general starting point would be adding a using Microsoft.AspNetCore.Authentication;
to ensure the HttpContext extensions are available, then adding a corresponding call to await ctx.Context.ChallengeAsync()
within your flow if the user is not authenticated.
Once that runs, you can check again whether the user is both authenticated and whether they meet the authorization requirements you would like to have for your secure static files.
Upvotes: 1