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