Search code examples
javascriptauthenticationchartsamchartsamcharts4

AmCharts JS Bearer Authentication


I have a .NET Core server with an API that I am trying to request data from via the AmCharts "default" loading method.

The server side endpoint looks like this:

[Authorize]
    public class StocksController : ApiController {
        [HttpGet("{id}")]
        public async Task<ActionResult<string>> GetStockIntraday1min(string id) {
            return await Mediator.Send(new GetStockHistoryQuery { Symbol = id, Interval = "1min" });
        }
    }
}

I know the server-part works just fine as I can request the data via a JS Fetch request like the one below and it works just fine.

let response = await fetch("api/stocks/getstockintraday1min/tsla", {
    headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`
    }
})

When I however try to do the same thing the way you are supposed to via AmCharts, I get a 401 Unauthorized Request in the FireFox console like this: XHR GET https://localhost:44397/api/stocks/getstockintraday1min/tsla [HTTP/2 401 Unauthorized 8ms]

Like the AmCharts documentation suggests (https://www.amcharts.com/docs/v4/reference/datasource/#Properties scroll down to "requestOptions"), I have tried to set up a request-header with my bearer authorization token like one should, but it is refusing to work. I have tried the following:

// Apply themes
am4core.useTheme(am4themes_animated) // Animations
am4core.useTheme(am4themes_dark) // Colors

// Create chart
let chart = am4core.create("chartdiv", am4charts.XYChart)
chart.padding(5, 15, 5, 15)
// Add data source information
console.log(authToken) // To verify token actually is set
let myHeaders = new Headers({
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": `Bearer ${authToken}`
})
chart.dataSource.url = "api/stocks/getstockintraday1min/tsla"
chart.dataSource.requestOptions.requestHeaders = myHeaders
// chart.dataSource.requestOptions.withCredentials = true // seems to do nothing?
chart.dataSource.parser = new am4core.JSONParser()

What's shown above doesn't work if I use only the "Authorization": Bearer ${authToken} I also tried:

// Apply themes
am4core.useTheme(am4themes_animated) // Animations
am4core.useTheme(am4themes_dark) // Colors

// Create chart
let chart = am4core.create("chartdiv", am4charts.XYChart)
chart.padding(5, 15, 5, 15)
// Add data source information
console.log(authToken) // To verify token actually is set
chart.dataSource.url = "api/stocks/getstockintraday1min/tsla"
chart.dataSource.requestOptions.requestHeaders = [{
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": `Bearer ${authToken}`
}]
// chart.dataSource.requestOptions.withCredentials = true // seems to do nothing?
chart.dataSource.parser = new am4core.JSONParser()

The above with with just the Authorization: Bearer row, or without the [] surrounding the JSON Object doesn't work either.

Searching YouTube has also yielded nothing, so if anyone has any clue as to what I am missing that would be greatly appreciated.


Solution

  • So it turns out that the DataSource object takes an array of requestHeaders as it's requestOptions. The correct way to get it to read your headers is to add them like this:

    chart.dataSource.requestOptions.requestHeaders = [
        {key: "Authorization", value: `Bearer ${accessToken}`}
    ]
    

    The docs also specifies this, but it didn't click in my head when I read it at the time. Docs source: https://www.amcharts.com/docs/v4/reference/datasource/