Skip to content

Commit af3d6ff

Browse files
authored
Merge pull request #743 from DuendeSoftware/mb/replay
Improve clarity in refresh tokens documentation
2 parents f9c26e4 + 5f7cc1f commit af3d6ff

File tree

2 files changed

+31
-18
lines changed

2 files changed

+31
-18
lines changed

src/content/docs/bff/fundamentals/blazor/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ These rendering modes are very powerful, but also add additional complexity when
3838
For more information on this, see [rendering-modes](/bff/fundamentals/blazor/rendering-modes)
3939

4040
### Authentication State
41-
The **AuthenticationState ** contains information about the currently logged-in user. This is partly populated from information from the user, but is also enriched with several management claims, such as the Logout URL.
41+
The `AuthenticationState` contains information about the currently logged-in user. This is partly populated from information from the user, but is also enriched with several management claims, such as the Logout URL.
4242

4343
Blazor uses AuthenticationStateProviders to make authentication state available to components. On the server, the authentication state is already mostly managed by the authentication framework. However, the BFF will add the Logout url to the claims using the **AddServerManagementClaimsTransform**. On the client, there are some other claims that might be useful. The **BffClientAuthenticationStateProvider** will poll the server to update the client on the latest authentication state, such as the user's claims. This also notifies the front-end if the session is terminated on the server.
4444

src/content/docs/identityserver/tokens/refresh.md

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Refresh tokens are a high-value target for attackers, because they typically hav
7373
tokens.
7474

7575
However, refresh tokens for _confidential clients_ are bound to that client; they can only be used by the client they
76-
are issued to and the client is required to authenticate itself in order to do so. An attacker able to obtain a refresh
76+
are issued to and the client is required to authenticate itself to do so. An attacker able to obtain a refresh
7777
token issued to a confidential client cannot use it without the client's credentials.
7878

7979
Refresh tokens issued to public clients are not bound to the client in the same way, since the client cannot
@@ -132,15 +132,15 @@ avoids those writes.
132132

133133
To make one time use tokens more robust to network failures, you can customize the behavior of the `RefreshTokenService`
134134
such that consumed tokens can be used under certain circumstances, perhaps for a small length of time after they are
135-
consumed. To do so, create a subclass of the `DefaultRefreshTokenService` and override its *AcceptConsumedTokenAsync(
136-
RefreshToken refreshToken)* method. This method takes a consumed refresh token and returns a boolean flag that indicates
135+
consumed. To do so, create a subclass of the `DefaultRefreshTokenService` and override its `AcceptConsumedTokenAsync(
136+
RefreshToken refreshToken)` method. This method takes a consumed refresh token and returns a boolean flag that indicates
137137
if that token should be accepted, that is, allowed to be used to obtain an access token. The default implementation in
138138
the `DefaultRefreshTokenService` rejects all consumed tokens, but your customized implementation could create a time
139139
window where consumed tokens can be used.
140140

141141
New options added In 6.3 interact with this feature. The `PersistentGrantOptions.DeleteOneTimeOnlyRefreshTokensOnUse`
142142
flag will cause OneTime refresh tokens to be deleted on use, rather than marked as consumed. This flag will need to be
143-
disabled in order to allow a customized Refresh Token Service to use consumed tokens.
143+
disabled to allow a customized Refresh Token Service to use consumed tokens.
144144

145145
Consumed tokens can be cleaned up by a background process, enabled with the existing
146146
`OperationalStoreOptions.EnableTokenCleanup` and `OperationalStoreOptions.RemoveConsumedTokens` flags. Starting in 6.3,
@@ -157,22 +157,35 @@ builder.Services.TryAddTransient<IRefreshTokenService, YourCustomRefreshTokenSer
157157

158158
### Replay Detection
159159

160-
In addition to one-time only usage semantics, you might wish to add replay detection for refresh tokens. If a refresh
161-
token is configured for one-time only use but used multiple times, that means that either the client application is
162-
accidentally mis-using the token (a bug), a network failure is preventing the client application from rotating
163-
properly (see above), or an attacker is attempting a replay attack. Depending on your security requirements, you might
164-
decide to treat this situation as an attack, and take action. What you might do is, if a consumed refresh token is ever
165-
used, revoke all access for that client/user combination. This could include deleting refresh tokens, revoking access
166-
tokens (if they are introspection tokens), ending the user's server side session, and sending back-channel logout
167-
notifications to client applications. You might also consider alerting the user to suspicious activity on their account.
160+
In addition to one-time only usage semantics, you can add replay detection for refresh tokens.
161+
Multiple uses of a one-time-only refresh token may indicate:
162+
163+
* A client application bug
164+
* Network failure during token rotation
165+
* A potential replay attack
166+
167+
Depending on your security requirements, you can treat this situation as an attack, and take action.
168+
If a consumed refresh token is ever used, you could revoke all access for that client/user combination.
169+
This could include deleting refresh tokens, revoking access tokens (if they are introspection tokens),
170+
ending the user's server side session, and sending back-channel logout notifications to client applications.
171+
You can also consider alerting the user to suspicious activity on their account.
172+
173+
:::caution
168174
Keep in mind that these actions are disruptive and possibly alarming to the user, and there is a potential for false
169175
positives.
176+
:::
177+
178+
While replay and re-use detection can be useful, they can be tricky to implement. In load-balanced environments,
179+
some form of synchronization will be required to avoid race conditions.
180+
181+
Implementing replay detection can be done in a similar way to [accepting consumed tokens](#accepting-consumed-tokens). Extending the
182+
`AcceptConsumedTokenAsync` method of the `DefaultRefreshTokenService`, you can add the additional revocation or alerting
183+
behavior that you choose. Depending on your scenario, overriding the `CreateRefreshTokenAsync`,
184+
`ValidateRefreshTokenAsync` and `UpdateRefreshTokenAsync` methods may also be desired.
170185

171-
Implementing replay detection is similar to [accepting consumed tokens](#accepting-consumed-tokens). Extend the
172-
`AcceptConsumedTokenAsync` method of the `DefaultRefreshTokenService` and add the additional revocation or alerting
173-
behavior that you choose. In 6.3, the same new options that interact with accepting consumed tokens also interact with
174-
replay detection. The `PersistentGrantOptions.DeleteOneTimeOnlyRefreshTokensOnUse` flag needs to be disabled so that
175-
used tokens persist and can be used to detect replays. The cleanup job should also be configured to not delete consumed
186+
The options that interact with accepting consumed tokens also interact with replay detection.
187+
The `PersistentGrantOptions.DeleteOneTimeOnlyRefreshTokensOnUse` flag needs to be disabled so that used tokens persist
188+
and can be used to detect replays. The cleanup job should also be configured to not delete consumed
176189
tokens.
177190

178191
See also: The [IRefreshTokenService](/identityserver/reference/services/refresh-token-service.md) reference.

0 commit comments

Comments
 (0)