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_id
and 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:
def generate_state_parameter():
random = os.urandom(256)
state = base64.b64encode(random)
return (state)
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.