Cross-site Request Forgery
Cross-site Request Forgery happens when an attacker tricks a user into clicking on a malicious link, where the link goes to a site where the user is currently authenticated. Any commands embedded in that malicious link might be run automatically because the user is already authenticated on the site, so the user does not see a login screen or any other evidence of malicious activity. In the case of Login with Amazon, Cross-site Request Forgery could be used to mimic a client or an authentication server.
Login with Amazon recommends using the
state parameter to prevent Cross-site Request Forgery. The client should set the value of the
state parameter when it initiates an authorization request, and save it to the user’s secure session. Unlike the
client_secret values, in order for the
state parameter to be useful in preventing attacks it should be unique, and non-guessable, for each and every authorization request. The authorization server returns the same
state when communicating with the client to deliver authorization codes and access tokens
. To protect users from attacks, the client must ignore communication if the returned
state parameter doesn't match the value from the initial call.
Calculating the State Parameter
Clients can calculate the
state parameter value in any way they choose, however, the value should be secure from forgery. Login with Amazon recommends using a securely-generated random string with at least 256 bits of entropy. To calculate a
state value using this method, use a random number generator suitable for cryptographic operations.
Here is an example in Python:
random = os.urandom(256)
state = base64.b64encode(random)
After generating the
state parameter value, save it to the user’s session information, ensuring the information is communicated securely and saved to a secure session. When the
state is returned by an authorization response, verify the legitimacy of the user by comparing it with the
state value saved to their session. If the values do not match, you should ignore the authorization response.
If you’re also using the
state parameter value to dynamically redirect users after authentication, consider concatenating the securely-generated random string with the dynamic URL, separated by a space (e.g.
state = state + " " + dynamicURL). When the authorization server returns the state, parse it and split it into two values based on the space. The second value will contain the dynamic URL needed to direct the user to the appropriate page after authentication.