3

I am trying to store a cookie on a client browser, using a JS Interop.

I am however getting a persistent error, which this answer does not help alleviate, and I can't find any possible solution on the net that has worked.

I have the following code in my Index.razor file:

@page "/"
@using Blazored.LocalStorage
@inject HttpClient Http
@inject Blazored.LocalStorage.ISyncLocalStorageService localStorage
@inject IJSRuntime JSRuntime
@test



@code{
    private string test { get; set; }
    protected override async Task OnInitializedAsync()
    {
        try
        {
            await JSRuntime.InvokeAsync<bool>("methods.WriteCookie", "test cookie", "test cookie value", 2);
            
        }catch(Exception e)
        {
            test = e.ToString();
        }
    }
}

I have the following code in my index.html file, in the wwwroot folder:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>OptionalyticsFrontend</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/app.css" rel="stylesheet" />
</head>

<body>
    <app>Loading...</app>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss"></a>
    </div>
    <script src="_framework/blazor.webassembly.js"></script>
    <script src="optionalyticsExtensions.js"></script>
</body>

</html>

And I have the following code in my optionalyticsExtensions.js file:

window.methods = {
    WriteCookie: function(name, value, days) {

        var expires;
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = "; expires=" + date.toGMTString();
        }
        else {
            expires = "";
        }
        document.cookie = name + "=" + value + expires + "; path=/";
        return true;
    }
}

This is my wwwroot file structure; index.html should be having no issues locating optionalyticsExtensions.js:

Why are we here? Just to suffer?

Yet, I get this error, consistently:

Microsoft.JSInterop.JSException: Could not find 'methods' in 'window'.
Error: Could not find 'methods' in 'window'.
    at https://localhost:44375/_framework/blazor.webassembly.js:1:9130
    at Array.forEach (<anonymous>)
    at p (https://localhost:44375/_framework/blazor.webassembly.js:1:9090)
    at https://localhost:44375/_framework/blazor.webassembly.js:1:9800
    at new Promise (<anonymous>)
    at Object.beginInvokeJSFromDotNet (https://localhost:44375/_framework/blazor.webassembly.js:1:9773)
    at _mono_wasm_invoke_js_marshalled (https://localhost:44375/_framework/wasm/dotnet.3.2.0.js:1:171294)
    at do_icall (<anonymous>:wasm-function[6049]:0x10f8b1)
    at do_icall_wrapper (<anonymous>:wasm-function[1896]:0x50b6a)
    at interp_exec_method (<anonymous>:wasm-function[1120]:0x2588e)
  at System.Threading.Tasks.ValueTask`1[TResult].get_Result () <0x2d9e7c8 + 0x00034> in <filename unknown>:0 
  at OptionalyticsFrontend.Client.Pages.Index.OnInitializedAsync () [0x0004c] in C:\Users\codef\source\repos\OptionalyticsFrontend\OptionalyticsFrontend\Client\Pages\Index.razor:24 
  at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync () <0x2baa8e8 + 0x0013a> in <filename unknown>:0 
  at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask (System.Threading.Tasks.Task taskToHandle) <0x2d167d0 + 0x000b6> in <filename unknown>:0 

I have tried:

  • Naming the JS class/function something else
  • Writing the script directly in index.html, instead of referencing a .js file
  • Writing a simple JS function that only took 1 argument and wrote it to the console, instead of this cookie function
  • Getting rid of the try/catch statement in Index.razor, in case that was messing it up somehow
  • Changing the type of the JSRuntime.InvokeAsync call
  • Changing what is returned by the JS function

Nothing seems to work.

What is the problem here?

Codefun64
  • 593
  • 2
  • 9
  • 18
  • 1
    I'm thinking your window.methods is just not defined when you run the script. The error looks similar to a basic "x is undefined" – Rohan Feb 01 '21 at 01:21
  • @Rohan I tried tying this to a button rather than component initialization, but it still gave me the same error. Though based on our talk I'm probably going to shift to using an httponly cookie instead of trying to set client cookies for anything. – Codefun64 Feb 01 '21 at 01:44
  • Curious that it still didn't run, but yes I think it's a non-issue after realizing the cookie was for authentication. I've put my advice for re-structuring your auth flow into an answer anyway. – Rohan Feb 01 '21 at 02:48

1 Answers1

3

If you're using this cookie for any kind of authentication you will not want to be storing them with the client. Those cookies are not secure. You need to be setting a HTTPOnly cookie from your server after the user authenticates.

HTTPOnly cookies disallow the client side (and any extensions or other 3rd parties) from viewing or modifying it, the client will basically not know it exists. You can then include it in your headers on any future API request you make, allowing the back-end to verify your token before proceeding.

Rohan
  • 456
  • 3
  • 16