-2

Info: I'm using the default Visual Studio (16.10.0 Preview 1.0) ASP.NET hosted Blazor WASM template with IdentityServer4 individual accounts.(ASP.NET Core 6 Preview 1)

I'd like the video stream only to be accessible by authorized users but [Authorize] attribute doesn't work here on the controller, I'm getting a Status Code: 401, while the user has logged in and thus has been authorized by the application. [Authorize] works with controllers for database access for example.

I think maybe it doesn't work with the video tag because the client accesses the controller directly from the video tag option: <source src="/VideoStream/@videoFileName" so no authorization headers are being sent. I've seen the same problem when devs want to protect/authorize downloading a file. I've read some blogs on that topic and tried some code snippets, but none of them work in my Blazor WASM app.

Without the [Authorize] attribute and if you know the path to the controller and the filename of the video (e.q. /VideoStream/test.mp4) anybody can access/download the video by just putting the link in the browser.

In this example the video isn't served from the (client side) wwwroot folder, but from a server side folder, see: var videoPathFile

Client side video tag

<video id="videostream" poster="@videoPoster" class="videostyle" oncontextmenu="return false;" controls disablePictureInPicture controlsList="nodownload">
    <source src="/VideoStream/@videoFileName" type="@ContentType;codecs=@Codecs" />
    Your browser does not support the video tag.naar een nieuwere versie.
</video>

/Server/Controllers/VideoStreamController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using System.IO;

namespace Mediatheek.Server.Controllers
{
    //[ApiController] 
    [Route("[controller]")]
    public class VideoStreamController : ControllerBase
    {
        private readonly IWebHostEnvironment env;
        private readonly ILogger<VideoStreamController> logger;
        public VideoStreamController(ILogger<VideoStreamController> logger, IWebHostEnvironment env)
        {
            this.logger = logger;
            this.env = env;
        }

        //[Authorize] // Doesn't work here, even when [ApiController] is uncommented
        [HttpGet("{file}")]
        public IActionResult StreamVideo(string file)
        {
            var provider = new PhysicalFileProvider(env.ContentRootPath);
            var videoPathFile = Path.Combine(provider.Root, "Files", "Videos", $"{file}.mp4");
            var fileResponse = PhysicalFile(videoPathFile, "application/octet-stream");
            fileResponse.EnableRangeProcessing = true;
            fileResponse.FileDownloadName = "video.mp4"; // rename original filename, just for testing
            return fileResponse;
        }
    }
}
Jaap
  • 315
  • 4
  • 11
  • I really don't understand why some people think this question isn't useful or lacks research. Is it unclear? Without any comments I don't know what to do. Yesterday it made me question myself and it didn't feel good. But okay, it's a feature of this platform but I can't figure out why it exists in the first place, without having to leave a comment. – Jaap Mar 08 '21 at 13:16
  • Jaap, I for one think your question looks fine. I think your question is not related to Blazor but instead how to Authorize API call. I suggest Google something like "how to authorize web api request in c#". You will see a lot of examples that maybe can point you in the right direction. – Jason D Mar 08 '21 at 20:01
  • Jason, thank you for your comment. I've googled for a solution. The problem here, I think, is that the `[Authorize]` attribute doesn't work on a controller which is directly accessed from the ` – Jaap Mar 09 '21 at 10:15
  • And here: https://dev.to/j_sakamoto/how-can-i-protect-static-files-with-authorization-on-asp-net-core-4l0o#:~:text=We%20can%20protect%20static%20files,UseStaticFiles(...)%20. and here https://odetocode.com/blogs/scott/archive/2015/10/06/authorization-policies-and-middleware-in-asp-net-5.aspx – Jaap Mar 09 '21 at 10:17
  • Why these examples don't work is (I think) because the combination of Blazor WASM, and the controller. `options.FallbackPolicy` (https://docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-5.0#static-file-authorization) for example doesn't work in Blazor WASM (afaik) – Jaap Mar 09 '21 at 10:20
  • Minus Three on this question is actually to much for me to handle as a simple, but emotional, guy trying to do his best. When I submitted this question to SO I've worked for over an hour on the question alone English isn't my first language. Spend more than a day on googling stuff. When I first saw these negative responses (within a couple of minutes, how is that possible?) it made me angry. Now I'm just sad. I don't like being sad. I really don't. – Jaap Mar 09 '21 at 10:23
  • Yup: `AuthorizationOptions.FallbackPolicy` isn't support in Blazor WASM, see: https://docs.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/?view=aspnetcore-5.0#require-authorization-for-the-entire-app – Jaap Mar 09 '21 at 11:11
  • It sounds like you did a good job getting to the root cause of the problem. Unfortunately I don't have any experience with this FallbackPolicy requirement. Were you able to find a workaround? – Jason D Mar 09 '21 at 13:54
  • 1
    @JasonD Not yet, but I'm asking around When I've a solution I'll post it here. – Jaap Mar 09 '21 at 14:00

1 Answers1

0

Your issue is the authorization header isn't being sent with the request. As you stated yourself, it's not using a traditional HttpClient and loading via the browser, but problem is that it should be for [Authroize] to work as intended.

This means you'd need to convert the WASM code to read the .mp4 as a byte stream and then send that over to the browser using IJSRuntime and build the video using JavaScript but that is very clunky and a terrible experience.

A better option is to use HttpClient to request the video URL, at least that way you know the client is authorized to know what the file path to the mp4 is.

Cory Podojil
  • 596
  • 6
  • Yes, the problem lies in the use of the ` – Jaap Mar 20 '21 at 08:57