DEV Community

loading...
Cover image for From URL JWT token authentication & manually authorizing HttpContext in .Net core MVC

From URL JWT token authentication & manually authorizing HttpContext in .Net core MVC

Ali Alp
“Take it easy” is nonsense , take it as hard as you can and don’t let it go :)
Updated on ・2 min read

In a normal authentication with JWT the token will be in the “Auth header” of the request and the authentication will take place as explained here

ASP.NET Core Authentication with JWT and Angular - Part 1

Securing a web application is one of the most important to do and usually one of the hardest things to pull off. In this series, we are going tolearn how to implement authentication with Angular on the front end side and ASP.Net Core on the server side using the JSON web tokens (JWT).

But in case you need to authorize your requests with JWT token while the token is in the URL like this:

https://localhost:444/controller/action?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3VzZXJkYXRhIjoie1widXNlcm5hbWVcIjpcInRlYWNoZXJAa28uY29tXCIsXCJwZWVyVXNlck5hbWVcIjpcInN0dWRlbnRAa28uY29tXCIsXCJwbGF0Zm9ybUlkXCI6MCxcInRlbmFudElkXCI6XCI4M0IwM0RCQi0xQTEyLTQwQ0YtQjZDRS0wNDQ2RTA5RDFBNjcjZGV2b3AuYWxpQGdtYWlsLmNvbVwiLFwicGVlckRpc3BsYXlOYW1lXCI6XCJUZWFjaGVyIDFcIixcImRpc3BsYXlOYW1lXCI6XCJzdHVkZW50IDFcIixcInJ0Y1VybFwiOlwiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQ0L3dlYnJ0Yy9jYWxsXCIsXCJzZXJ2aWNlVXJsXCI6XCJodHRwczovL1NlcnZpY2UvTG9nL2xvZ1wifSIsImV4cCI6MTU0NzgxNzcxMiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQ0IiwiYXVkIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQ0In0.
DUzq0Im1nXLdGtZVI389NhuMXDe0YkGpZJTvOHytOoQ
Enter fullscreen mode Exit fullscreen mode

things will get a bit tricky. so I decided to make a quick tutorial to explain how I managed to implement it.

In a Nutshell

so let’s get to it :) your ConfigureServices method will be something like this :

services.Configure<CookiePolicyOptions>(options =>
{
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
Enter fullscreen mode Exit fullscreen mode

and your Configure method:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
    app.UseHttpsRedirection();
}

app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMiddleware(typeof(AuthorizationMiddleware));
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});
Enter fullscreen mode Exit fullscreen mode

the magic will happen in

app.UseMiddleware(typeof(AuthorizationMiddleware));
Enter fullscreen mode Exit fullscreen mode

Let’s have look at AuthorizationMiddleware’s invoke method in detail:

public async Task InvokeAsync(HttpContext context)
{
    //getting the token from the URL
    var queryString = HttpUtility.ParseQueryString(context.Request.QueryString.Value);

    //setting the validation parameters
    //warning : these parameters should be same with the token's issuer parameters 
    var validationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,

        ValidIssuer = _settings.Value.Jwt_valid_issuer,
        ValidAudience = _settings.Value.Jwt_valid_audience,
        IssuerSigningKey =
            new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_settings.Value.Jwt_issuer_key))
    };

    var validator = new JwtSecurityTokenHandler();

    if (!validator.CanReadToken(queryString.Get("token")))
        throw new UnauthorizedAccessException("token is not readable");
    try
    {
        //trying to parse the token 
        var principal =
            validator.ValidateToken(queryString.Get("token"), validationParameters, out var validatedToken);
        if (principal.HasClaim(c => c.Type == ClaimTypes.UserData))
        {
            var userData = principal.Claims.First(c => c.Type == ClaimTypes.UserData).Value;

            //setting AuthData to be used for later usages in other middlewares
            //as well as the controller which is in the MVC middleware 
            context.Items["AuthData"] = JsonConvert.DeserializeObject<LoginModel>(userData);

            //authorizing the http context 
            context.User.AddIdentity((ClaimsIdentity) principal.Identity);

            //invoking the next middleware 
            await _next.Invoke(context);
        }
    }
    catch (Exception e)
    {
        throw;
    }
}
Enter fullscreen mode Exit fullscreen mode

therefore if this Middleware reaches the

await _next.Invoke(context);
Enter fullscreen mode Exit fullscreen mode

it means that the token is valid and the HttpContext is authorized plus we have added the parsed version of the token to the HttpContext

context.Items["AuthData"] = JsonConvert.DeserializeObject<LoginModel>(userData);
Enter fullscreen mode Exit fullscreen mode

So you can implement your controller like you have used the default JwtBearer authentication:

[HttpGet,Authorize]
public IActionResult Action()
{
    //retrieve the parsed token 
    var loginModel = HttpContext.Items["AuthData"] as LoginModel;
    return View(loginModel?.Username);
}
Enter fullscreen mode Exit fullscreen mode

Let me know if you had any questions & have fun coding :)

Discussion (0)