Reputation: 17562
I have the following architecture.
Where:
I am using Implicit Flow to access a JWT access token from Azure AD.
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=id_token+token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
&response_mode=fragment
&state=12345
&nonce=678910
This JWT token is then later passed to the resource server as a Bearer authorization. The same token could be reused multiple times before it expires.
As part of the Authorize request I pass state and a nonce value.
Presently I validate the state on my client in JavaScript using a simple if
:
function isValid() {
if (token.state !== expectedState) {
return false;
}
...
}
If I understand correctly the nonce is to prevent replay attacks - which I assume meant against my resource server, but perhaps also against the client.
I am unsure where (or if) I should validate the nonce.
On the server doesnt seem right, the token as a whole is being validated, and the token is meant to be reusable (within its expiry).
On the client, seems to be a better location, but is that any different to validating the state?
Upvotes: 7
Views: 11109
Reputation: 9401
I am unsure where (or if) I should validate the nonce.
Of course, you should validate the nonce. Because the nonce
is required and it will be returned and contained as a claim in the id_token
. When you validate the id_token
, you would just validate the nonce claim. Using nonce is to mitigate token replay attacks (someone who want to use token replay attack won't know the nonce, so each token has different nonce to identify the origin of the request).
There is a clear explanation for nonce for AAD v2 endpoint:
#nonce
(required)
A value included in the request, generated by the app, that will be included in the resulting
id_token
as a claim. The app can then verify this value to mitigate token replay attacks. The value is typically a randomized, unique string that can be used to identify the origin of the request.
So, you can just validate the id_token to validate the nonce.
but is that any different to validating the state?
Yes, the effect of nonce is different from state. First, nonce will be returned in the id_token
and you can validate it when you decode and validate the id_token
. But state
is returned in the response, not in the token. Also, state
has different meaning and effect from nonce.
#state
(recommended)
A value included in the request that will also be returned in the token response. It can be a string of any content that you wish. A randomly generated unique value is typically used for preventing cross-site request forgery attacks. The state is also used to encode information about the user's state in the app before the authentication request occurred, such as the page or view they were on.
Additional, replay attack is different from cross-site request forgery attacks. You can refer for more details about these two attacks. Then, you will understand why nonce
is in the token and state
is in the response.
Whether validate the nonce (token) at client
For id_token
, yes, it just should be validate from the client.
For SPA with implicit flow, we can use ADAL.js to validate nonce
, the id_token
which contains the nonce
claim to mitigate token replay attacks.
Hope this helps!
Upvotes: 6
Reputation: 29218
As a general point I'd recommend using the excellent oidc-client certified library to do this for you
It is tricky with Azure AD but I have a documented sample that works and that we used at my last company: http://authguidance.com/2017/11/30/azure-active-directory-setup/
Happy to answer any questions if it helps ..
Upvotes: 1