Is it safe to expose refreshtoken API - c#

I have an application developed using React in the front-end and ASP.Net Web API in the backend. I am using JWT for authorization. The process is
When a user logs in and is authenticated, 2 tokens are sent to the front-end, access token and refresh token. An access token is the JWT and a refreshes token is a random string and a refresh token is stored in a database.
For every subsequent call to APIs access token is attached in the header, I have an authentication filter that validates the access token.
Once the access token is expired, a 401 status is thrown with the error message TokenExpired.
Once the front-end receives 401, it calls the refresh token API to get the refresh token
The question I have is that I cannot have an authentication filter to validate the access token of refresh tokens API as it will throw 401 due to the expired access token, so I need to make the refresh token API to be anonymous so it does not hit authentication filter. If I make anonymous I am making a call to the database to get the refresh token stored for the user and compare it with the one I received from the front-end. So is it safe to make the refresh token API anonymous, if not what's the best way?

At Auth0, Created a set of features that mitigate the risks associated with using refresh tokens by imposing safeguards and controls on their lifecycle. Our identity platform offers refresh token rotation, which also comes with automatic reuse detection.
Please read the following topic.
Refresh Token Rotation
Refresh Token Automatic Reuse Detection

The JWT is signed using preshared secret key. Since it’s REST API in the backend and stateless, jwt is used for authorization and construct principal object
As you say, the access token represent authorisation in your application, if the refresh token is exposed then the refresh token can be presented by a bad actor to obtain an access token they can use for the same authorisation.
Using a 'preshared secret' indicates the JWT is a HMAC only variant of JWT, i.e. there is no encryption as that would indicate private and public key pair opposed to a 'preshared secret'. So the JWT is essentially a signature for the puposes of security characteristics we are ensuring integrity that the claims of the JWT are well-formed and have not been changed since signed. It also means same secret is used for signing on one end as was used to verify on the other end, the same secret has to be used because verifying a signature requires that both ends generate the signature and both of the signature match. So no data is being encrypted, so not data in the JWT is sensitive and needs to be protected.
Given this context, both the refresh and access token are a simple JWT that can only be generated by the holder of the secret - if they are exposed they can be used to make malicious requests as long as they remain valid (nbf claim).
Essentially this type of JWT can be misused if exposed to impersonate the identity the secret that signed the JWT represents, without actually knowing the secret itself, until the nbf claim expires the token - and a refresh token is the mechanism to extend the nbf claim without having the secret (which would result in a new signature, because the nbf claim would change when used).
There is one protection from access token reuse, it is the nonce claim. If you do not currently use a nonce claim you can read about how OIDC have implemented and do he same in your app. But as you say, your app is stateless but hopefully the backend has a form of state to ensure no nonce reuse and prevent JWT signature reuse. For every nonce the JWT signature changes, therefore the access token changes and can be used only 1-time. So if stolen it is a race condition who uses the token first, which greatly minimises the risk but not a perfect solution.

Related

How i can expire the access-token manually or forcefully generated by my own web API

I Create a Web API in the asp.net web API its Generate the access-token and store in the browser storage cache or session storage what if someone stole the access-token from the browser he can expose the API Data by using fiddler or Post Man so how can we prevent that issue how can we expire the token manually or forcefully
I dont think you can expire an access token generated in that way. Access tokens are good for the extent of their lifetime. This is why access tokens short lived tokens, normally an hour.
Even having the user revoke their consent is not going to expire an access token.
That being said the OAuth 2.0 Token Revocation RFC 7009 specification supplements the core specification with a mechanism to revoke both types of tokens. A token is a string representing an authorization grant issued by the resource owner to the client. A revocation request will invalidate the actual token and, if applicable, other tokens based on the same authorization grant and the authorization grant itself.
POST /revoke HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
token=45ghiukldjahdnhzdauz&token_type_hint=access_token
But this will probably only work if you are using an Authentication server to get your Access token and if the Authentication server supports this endpoint. IIR Googles for example only supports revoke of the refresh token not the access token. This is not a default thing. I have never implemented it myself it would probably entail storing the access token on the auth server and then testing that somehow rather than having it be a standard JWT.
The usual mechanism is to introduce refresh tokens. Let the access tokens have a short lifespan, say one day, and have a long lived refresh token request new access tokens every day. The server can then be asked to revoke access for a specific account by disabling the access for a refresh token.

IdentityServer4 External Authentication Tokens

I have an IdentityServer4 set up to authenticate using google, and thats working great, including storing the tokens in AspNetUserTokens.
Additionally I have a separate service that needs to be able to use the access and refresh tokens to call google's API on behalf of the user later, when they are not logged in.
I'm not understanding how to request the tokens from identityserver, and keep them up to date(swap out the access token and expiration date). I can do this directly by adding an endpoint to identityserver to request the tokens, but then the external access token in IdentityServer would never be updated.
Your best bet was to use Hybrid Flow where the refresh token is stored in your service DB directly. IDS is just a proxy here and is not responsible for storing refresh token not issued by itself.

Is it safe to implement JWT auth with cookies, token versioning, and no refresh tokens?

I have some questions about my implementation of bearer token security (JWT to be specific) in an asp.net core 2.0 project that I'm working on. The bearer token is used when the frontend web app talks to a separate Api (and needless to say all of this is over Https, of course).
First, let me summarize what I implemented and my reasoning:
Access Tokens are stored via a secure http-only cookie
I believe this limits the attack surface to just XSRF (correct me if I'm wrong). To prevent against XSRF I have implemented antiforgery/XSRF tokens.
Access Tokens have a version number
My Users table has a column for Token Version, and this number is included when issuing an access token for the user.
If the token versions don't match during authentication/authorization, the request is denied and a challenge is issued
There is logic that automatically updates the token version when applicable (i.e. An admin locks an account, the user changes their email or logs out, etc) - It can also be manually changed if needed, for example if it becomes known that a specific account was compromised or any other valid reason for revoking access
Side note: I've implemented a way to avoid constant database hits when active users require the version number check and can elaborate if needed but I don't think it directly applies to my security concerns in this question
No Refresh Tokens and long expiration for Access Tokens
I don't use refresh tokens at all, and my access tokens are set to expire after 7 days (unless "remember me" is unchecked, in which case the expiration is set to Session). Here is my justification:
The token version functionality solves the issue of needing to revoke an access token while its expiration is still valid
Even with very short access token expiration, a compromised account/session could simply use the longer lived refresh token to acquire a new valid access token, so I'm just cutting out the middle man (correct me if I'm wrong or naive)
So, here are my specific questions (and to clarify, I'm not asking for opinions on best practices and such but for objective answers about whether or not the implementation satisfies a reasonable level of security):
Does using a http-only cookie limit the attack surface to just XSRF attacks? And can XSRF be "completely" prevented via Antiforgery/XSRF tokens?
Is a token versioning system a valid way to ensure proper access revocation?
Is it reasonable to forego refresh tokens and allow for longer access token expiration times when a token versioning system is in use (and tokens are protected via the http-only cookie and antiforgery tactics)?

Generate a Refresh Token

I have a work flow that works like this:
User on mobile device uses a login with Google work flow and gets a token back.
User passes id_token to my WebAPI endpoint.
WebAPI validates the token via google endpoint, saves user data to a database, and generates refresh and access tokens.
When user needs to use my api, they provide access token via bearer authentication header.
If access token has expired or is going to expired, app provides refresh token and receives a new access token.
This is a pretty standard workflow I believe. Where I am currently stuck is how to generate a secure refresh token. I'm using ASP.NET MVC 5 and would love a little direction in how to generate this refresh token. I'm actually having a hard time even finding the refresh token format as well. I can generate an access token fairly easily using the JwtSecurityToken, JwtSecurityTokenHandler and SecurityTokenDescriptor classes.
Could this be as simple as using a symmetrical encryption algorithm on a json string and sending it over the wire?

how can signing/encryption of token based authentication work for a stateless server (REST)

I have clients which are all browsers.
All clients render just a single page application getting data from a Web API.
The design of the API follows REST principles.
This is my authentication flow:
I use basic authentication over SSL for my login view.
If the user`s sent username and password are valid I put a token string into the response
This token is stored in the local storage on client side
Each further request to a ressource endpoint of the server API includes the token.
Before I do further investigation with the token like checking its expiration date:
I need to know wether the authenticity of the token is still valid or someone has modified it. This assumes that the token was signed with a key before.
OR
I need to decrypt the encrypted token.
Question 1) Do steps 6 and 7 make sense using SSL ?
Question 2) Lets assume steps 6 and 7 make sense then I would have done the following:
When the for example json web token (JWT) after successful login is created I sign it with a key. This key is somewhere on the server stored maybe in an xml file or in a singleton class.
Wherever I store this sign key when I create the token I have to use the same key to validate the token. The same is valid for the encryption of the token. How is it possible to use different sign keys for a token maybe on a user basis. That means each authenticated login gets a token with an individual sign key.
The next time the user is requesting a resource endpoint I want to know whether the token has still the authenticity. But I can check this only with the same sign key the token was created with.
Question 3) Where should this sign key be stored ?
If you use JWT you have different possibilities of security:
Sign the token (see JWS). In this case a man-in-the-middle can still read the contents of this token but cannot modify it because he doesn't have the key to sign it and when the server checks the authenticity of the token it will detect that it has been tampered with
Encrypt the token (see JWE). In this case a man-in-the middle cannot read the contents of the token, nor he can modify its contents.
Using SSL in your case would ensure that the token cannot be stolen by man-in-the-middles. So unless you have some super secret information stored inside this token, signing it should be sufficient. Obviously the signing key should be stored on the server only and not shared with the rest of the world.
As far as your question about signing the token with different keys depending on the user is concerned, I don't think this is necessary.
Personally I would use a JWT token which contains only a minimum information like the exp and jti claims and sign it with a secret key. Then I would use the value of this token as key in a key/value store on the server (could be some cache implementation like memcached or NoSQL DB) and would associate the username and any other necessary information to this token. The value will be cached for the duration of validity of the token. When the client sends the JWT token to the server, the server would validate the signature of the token to ensure that its value hasn't been tampered with and then look it the cache for the associated user information.
SSL prevents tampering by men in the middle but what about the end users themselves? I don't trust anybody including end users. Any evil end user can hijack the token from a common machine or some one else's and simply send the token back to the server. If that is okay to you in terms of the security requirements you have, SSL is good enough.
However, people use the term token to indicate any kind of blob. But a software security token is supposed to be the container of claims. If you do indeed use your token to store claims, it is very important to check the integrity by validating the signature. Even a legit user can add bogus claims and push the token over to the server through HTTPS.
You can have a key per user. You can store it where ever you want it. But you need to ensure the security of the keys.

Categories