@@ -254,7 +254,7 @@ public TokenService(Settings settings, Clock clock, Client client, XPackLicenseS
254
254
* {@link #VERSION_TOKENS_INDEX_INTRODUCED} and to a specific security tokens index for later versions.
255
255
*/
256
256
public void createOAuth2Tokens (Authentication authentication , Authentication originatingClientAuth , Map <String , Object > metadata ,
257
- boolean includeRefreshToken , ActionListener <Tuple < String , String > > listener ) {
257
+ boolean includeRefreshToken , ActionListener <CreateTokenResult > listener ) {
258
258
// the created token is compatible with the oldest node version in the cluster
259
259
final Version tokenVersion = getTokenVersionCompatibility ();
260
260
// tokens moved to a separate index in newer versions
@@ -273,7 +273,7 @@ public void createOAuth2Tokens(Authentication authentication, Authentication ori
273
273
//public for testing
274
274
public void createOAuth2Tokens (String accessToken , String refreshToken , Authentication authentication ,
275
275
Authentication originatingClientAuth ,
276
- Map <String , Object > metadata , ActionListener <Tuple < String , String > > listener ) {
276
+ Map <String , Object > metadata , ActionListener <CreateTokenResult > listener ) {
277
277
// the created token is compatible with the oldest node version in the cluster
278
278
final Version tokenVersion = getTokenVersionCompatibility ();
279
279
// tokens moved to a separate index in newer versions
@@ -306,12 +306,13 @@ public void createOAuth2Tokens(String accessToken, String refreshToken, Authenti
306
306
* @param authentication The authentication object representing the user for which the tokens are created
307
307
* @param originatingClientAuth The authentication object representing the client that called the related API
308
308
* @param metadata A map with metadata to be stored in the token document
309
- * @param listener The listener to call upon completion with a {@link Tuple} containing the
310
- * serialized access token and serialized refresh token as these will be returned to the client
309
+ * @param listener The listener to call upon completion with a {@link CreateTokenResult} containing the
310
+ * serialized access token, serialized refresh token and authentication for which the token is created
311
+ * as these will be returned to the client
311
312
*/
312
313
private void createOAuth2Tokens (String accessToken , String refreshToken , Version tokenVersion , SecurityIndexManager tokensIndex ,
313
314
Authentication authentication , Authentication originatingClientAuth , Map <String , Object > metadata ,
314
- ActionListener <Tuple < String , String > > listener ) {
315
+ ActionListener <CreateTokenResult > listener ) {
315
316
assert accessToken .length () == TOKEN_LENGTH : "We assume token ids have a fixed length for nodes of a certain version."
316
317
+ " When changing the token length, be careful that the inferences about its length still hold." ;
317
318
ensureEnabled ();
@@ -351,12 +352,13 @@ private void createOAuth2Tokens(String accessToken, String refreshToken, Version
351
352
final String versionedRefreshToken = refreshToken != null
352
353
? prependVersionAndEncodeRefreshToken (tokenVersion , refreshToken )
353
354
: null ;
354
- listener .onResponse (new Tuple <>(versionedAccessToken , versionedRefreshToken ));
355
+ listener .onResponse (new CreateTokenResult (versionedAccessToken , versionedRefreshToken ,
356
+ authentication ));
355
357
} else {
356
358
// prior versions of the refresh token are not version-prepended, as nodes on those
357
359
// versions don't expect it.
358
360
// Such nodes might exist in a mixed cluster during a rolling upgrade.
359
- listener .onResponse (new Tuple <> (versionedAccessToken , refreshToken ));
361
+ listener .onResponse (new CreateTokenResult (versionedAccessToken , refreshToken , authentication ));
360
362
}
361
363
} else {
362
364
listener .onFailure (traceLog ("create token" ,
@@ -859,10 +861,11 @@ private void indexInvalidation(Collection<String> tokenIds, SecurityIndexManager
859
861
* Called by the transport action in order to start the process of refreshing a token.
860
862
*
861
863
* @param refreshToken The refresh token as provided by the client
862
- * @param listener The listener to call upon completion with a {@link Tuple} containing the
863
- * serialized access token and serialized refresh token as these will be returned to the client
864
+ * @param listener The listener to call upon completion with a {@link CreateTokenResult} containing the
865
+ * serialized access token, serialized refresh token and authentication for which the token is created
866
+ * as these will be returned to the client
864
867
*/
865
- public void refreshToken (String refreshToken , ActionListener <Tuple < String , String > > listener ) {
868
+ public void refreshToken (String refreshToken , ActionListener <CreateTokenResult > listener ) {
866
869
ensureEnabled ();
867
870
final Instant refreshRequested = clock .instant ();
868
871
final Iterator <TimeValue > backoff = DEFAULT_BACKOFF .iterator ();
@@ -995,7 +998,7 @@ private void findTokenFromRefreshToken(String refreshToken, SecurityIndexManager
995
998
*/
996
999
private void innerRefresh (String refreshToken , String tokenDocId , Map <String , Object > source , long seqNo , long primaryTerm ,
997
1000
Authentication clientAuth , Iterator <TimeValue > backoff , Instant refreshRequested ,
998
- ActionListener <Tuple < String , String > > listener ) {
1001
+ ActionListener <CreateTokenResult > listener ) {
999
1002
logger .debug ("Attempting to refresh token stored in token document [{}]" , tokenDocId );
1000
1003
final Consumer <Exception > onFailure = ex -> listener .onFailure (traceLog ("refresh token" , tokenDocId , ex ));
1001
1004
final Tuple <RefreshTokenStatus , Optional <ElasticsearchSecurityException >> checkRefreshResult ;
@@ -1014,7 +1017,9 @@ private void innerRefresh(String refreshToken, String tokenDocId, Map<String, Ob
1014
1017
if (refreshTokenStatus .isRefreshed ()) {
1015
1018
logger .debug ("Token document [{}] was recently refreshed, when a new token document was generated. Reusing that result." ,
1016
1019
tokenDocId );
1017
- decryptAndReturnSupersedingTokens (refreshToken , refreshTokenStatus , refreshedTokenIndex , listener );
1020
+ final Tuple <UserToken , String > parsedTokens = parseTokensFromDocument (source , null );
1021
+ Authentication authentication = parsedTokens .v1 ().getAuthentication ();
1022
+ decryptAndReturnSupersedingTokens (refreshToken , refreshTokenStatus , refreshedTokenIndex , authentication , listener );
1018
1023
} else {
1019
1024
final String newAccessTokenString = UUIDs .randomBase64UUID ();
1020
1025
final String newRefreshTokenString = UUIDs .randomBase64UUID ();
@@ -1126,11 +1131,13 @@ public void onFailure(Exception e) {
1126
1131
* @param refreshTokenStatus The {@link RefreshTokenStatus} containing information about the superseding tokens as retrieved from the
1127
1132
* index
1128
1133
* @param tokensIndex the manager for the index where the tokens are stored
1129
- * @param listener The listener to call upon completion with a {@link Tuple} containing the
1130
- * serialized access token and serialized refresh token as these will be returned to the client
1134
+ * @param authentication The authentication object representing the user for which the tokens are created
1135
+ * @param listener The listener to call upon completion with a {@link CreateTokenResult} containing the
1136
+ * serialized access token, serialized refresh token and authentication for which the token is created
1137
+ * as these will be returned to the client
1131
1138
*/
1132
1139
void decryptAndReturnSupersedingTokens (String refreshToken , RefreshTokenStatus refreshTokenStatus , SecurityIndexManager tokensIndex ,
1133
- ActionListener < Tuple < String , String > > listener ) {
1140
+ Authentication authentication , ActionListener < CreateTokenResult > listener ) {
1134
1141
1135
1142
final byte [] iv = Base64 .getDecoder ().decode (refreshTokenStatus .getIv ());
1136
1143
final byte [] salt = Base64 .getDecoder ().decode (refreshTokenStatus .getSalt ());
@@ -1166,8 +1173,10 @@ public void onResponse(GetResponse response) {
1166
1173
if (response .isExists ()) {
1167
1174
try {
1168
1175
listener .onResponse (
1169
- new Tuple <>(prependVersionAndEncodeAccessToken (refreshTokenStatus .getVersion (), decryptedTokens [0 ]),
1170
- prependVersionAndEncodeRefreshToken (refreshTokenStatus .getVersion (), decryptedTokens [1 ])));
1176
+ new CreateTokenResult (prependVersionAndEncodeAccessToken (refreshTokenStatus .getVersion (),
1177
+ decryptedTokens [0 ]),
1178
+ prependVersionAndEncodeRefreshToken (refreshTokenStatus .getVersion (), decryptedTokens [1 ]),
1179
+ authentication ));
1171
1180
} catch (GeneralSecurityException | IOException e ) {
1172
1181
logger .warn ("Could not format stored superseding token values" , e );
1173
1182
onFailure .accept (invalidGrantException ("could not refresh the requested token" ));
@@ -1910,6 +1919,30 @@ boolean isExpirationInProgress() {
1910
1919
return expiredTokenRemover .isExpirationInProgress ();
1911
1920
}
1912
1921
1922
+ public static final class CreateTokenResult {
1923
+ private final String accessToken ;
1924
+ private final String refreshToken ;
1925
+ private final Authentication authentication ;
1926
+
1927
+ public CreateTokenResult (String accessToken , String refreshToken , Authentication authentication ) {
1928
+ this .accessToken = accessToken ;
1929
+ this .refreshToken = refreshToken ;
1930
+ this .authentication = authentication ;
1931
+ }
1932
+
1933
+ public String getAccessToken () {
1934
+ return accessToken ;
1935
+ }
1936
+
1937
+ public String getRefreshToken () {
1938
+ return refreshToken ;
1939
+ }
1940
+
1941
+ public Authentication getAuthentication () {
1942
+ return authentication ;
1943
+ }
1944
+ }
1945
+
1913
1946
private class KeyComputingRunnable extends AbstractRunnable {
1914
1947
1915
1948
private final BytesKey decodedSalt ;
0 commit comments