angularjsasp.net-coremobileasp.net-core-webapiasp.net-core-security

How to secure ASP.NET Core Web API from stolen JWT token for Impersonation


I have a ASP.NET core REST API deployed in a Server behind IIS. REST API is consumed by Angular JS Web application and Mobile(Android/IOS) application. For Authorization I'm using JWT token(). Recently went through Security Audit and they found that JWT stored in Local storage can be stolen and used by other attacker from the same organization for impersonation(For eg, Employee utilizing Manager's features).

I want to tag the person or that machine to that JWT so that when the JWT is stolen the attacker cannot misuse it or will not be any use with that stolen Token. I tried tagging the IP with JWT token and stored those lookup in Server(In memory Cache). Below is the code i tried , which didn't work.

private readonly IHttpContextAccessor _httpContextAccessor;
public TestController(IHttpContextAccessor httpContextAccessor)
{
    _httpContextAccessor = httpContextAccessor;
}
var ipAddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();

I expected output to be different every time i request from different machines. But the actual output is same IP every time like this 15.11.101.25 (though i tried from different machines). Please share with me some better solution if there is any. Excuse my English.


Solution

  • If you really need that kind of security, you can combine the JWT token with a secure (=cookies only allowed to be sent via https) http-only cookie, and store a kind of request token inside it that sent on each request.

    You can have a read on Where to Store your JWTs – Cookies vs HTML5 Web Storage which kind of covers the topic and explain the up- and down-sides of local storage vs cookies for JWT.

    Http-only cookies can't be read via JavaScripts (and hence not stolen) and are hence secure against XSS attacks. And CSRF based attacks can't get the JWT token (since its sent via headers).

    So XSS based attacks won't have the cookie based token and CSRF based request won't have the JWT token required to authenticate the user. The cookie token could be generated on sign in, so its tied to the user who logs on that machine.

    You can of course also turn it around and have the JWT in a secured cooke and the anti request token as header.

    Of course you could still steal the anti-forgery cookie with physical access to the machine, but that's neither XSS nor CSRF and can't be protected by the application alone, the machines themselves need to be secured against physical type of attacks.

    Alternatively, don't store JWT tokens in the local storage. When you use the OpenID flow, your application will, on the first load, see that its not authorized, will redirect you to the OpenID provider, let the user enter his credentials and redirect them back with the token (or code for the auth code flow).

    When the user closes the browser and opens the site again, there's no token anymore, the user will be redirected to the OpenID provider. Since the user is still logged in, no credentials will be asked and he will be redirected back to the page he came from, including a new set of tokens. You just need the store the tokens in memory (and refresh when it expires) for the current application session.