I have a REST API backend which has HTTPS (and blocked HTTP) and use JWT as the authentication mechanism. The client side is iOS/Android app. I want to add a layer of safeguard on critical API by using client nonce to prevent (mostly) resubmission (unintentionally calling the same API twice due to bad network/UI) and (maybe) replay attack. The current details are as follows.
(All REST calls are through HTTPS)
- The client makes an API call using username and password to exchange for a JWT from server side.
- The client uses the JWT obtained (HTTP header) and makes subsequent API call to the server.
- The backend server checks the JWT and executes the request.
The current issue is, anyone who can intercept the HTTP package can replay the API call. Moreover, in the situation with a bad network, the client may press the submit/confirm button twice and resubmit the request.
What I propose is the following:
- The client makes an API call using username and password to exchange for a JWT from server side.
- The client uses the JWT obtained + a client-generated nonce and makes subsequent API call to the backend server.
- The backend server checks the JWT first and then the nonce. Let's assume we have a k-v store with TTL like Redis.
- If the nonce exists in Redis, we reject the request. If not, we accept the request and set the nonce in Redis with some predefined TTL (say 1hr?) so that a replay will be rejected.
I have to admit I have very little knowledge on security. I want to know if this proposal is legit? Or I miss something important? If my idea is ok, what is the best algorithm to generate the nonce? Does the server side need to somehow "decode" the nonce to see if it fits the protocol before comparing it against Redis?