Solving Azure Static Web Apps Problem with Code Query Parameter

When adding an API callback to implement GitHub (OAuth) authentication for my Azure Static Web App, I had quite a bit of trouble. I found the reason was that the callback had a query parameter named code. In this article I will describe why it causes problems and how to solve it.

Code Example

In a Static Web App, you typically have static webpages and a backend API. With Azure Static Web Apps, the backend API is written as Azure Functions.

For example, I have this OAuth callback function (for GitHub authentication):

 1public static async Task<IActionResult> Callback(
 2    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
 3    ILogger log)
 4{
 5    var code = req.Query["code"].ToString();
 6    var state = req.Query["state"].ToString();
 7    // Add code to validate state here...
 8
 9    var client = new HttpClient();
10    var tokenParams = $"grant_type=authorization_code&code={code}&redirect_uri={RedirectUri}&client_id={ClientId}&client_secret={ClientSecret}";
11    var httpContent = new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes(tokenParams));
12    var response = await client.PostAsync(TokenUrl, httpContent);
13    var responseContent = await response.Content.ReadAsStringAsync();
14
15    // Add code to pass token to client here...
16    var script = CallbackScript("github", "success", $"{{\"token\":\"{token}\",\"provider\":\"github\"}}");
17
18    return new ContentResult { Content = script, ContentType = "text/html", StatusCode = 200 };
19}

The Problem

However, this function didn't work. After some testing, I found that it wasn't executed at all.

The URL of the callback is something like: https:/.../api/callback?code=......&state=.......

The reason? The query parameter (URL parameter) code=...... This is a kind of reserved query parameter in Azure Functions to pass an API Key. If you pass anything else in there, your query will be rejected.

This is also described in this GitHub issue: https://github.com/Azure/static-web-apps/issues/165

In my case, renaming the query parameter was not possible. It is part of the OAuth Authorization Code protocol and is always sent by OAuth providers like GitHub. What to do?

The Solution

Luckily there is a solution!

Azure Functions comes with something called Function Proxies. These can be used for modifying URLs.

By adding a proxies.json to the api folder, I can rename the code=..... parameter before it is being sent to the function.

 1{
 2    "$schema": "http://json.schemastore.org/proxies",
 3    "proxies": {
 4        "callback": {
 5            "matchCondition": {
 6                "methods": [ "GET" ],
 7                "route": "/api/callback"
 8            },
 9            "backendUri": "https://localhost/api/callback2",
10            "requestOverrides": {
11              "backend.request.querystring.code": "",
12              "backend.request.querystring._code": "{request.querystring.code}"
13            }
14        }
15    }
16}

This will redirect the query from /api/callback to /api/callback2 and rename code to _code.

I then did just the following changes to the callback function:

1public static async Task<IActionResult> Callback2(
2    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
3    ILogger log)
4{
5    var code = req.Query["_code"].ToString();

With these changes, it worked like a charm!

Do you want to see it in action? Just check out my quickstart template for Azure Static Web App / Hugo / Netlify CMS.

Related Posts