21
21
import static java .nio .charset .StandardCharsets .UTF_8 ;
22
22
import static org .apache .pulsar .broker .web .AuthenticationFilter .AuthenticatedDataAttributeName ;
23
23
import static org .apache .pulsar .broker .web .AuthenticationFilter .AuthenticatedRoleAttributeName ;
24
+ import static org .assertj .core .api .Assertions .assertThat ;
25
+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
24
26
import static org .mockito .ArgumentMatchers .eq ;
25
27
import static org .mockito .ArgumentMatchers .isA ;
26
28
import static org .mockito .Mockito .mock ;
36
38
import java .security .KeyPair ;
37
39
import java .security .PrivateKey ;
38
40
import java .util .Date ;
41
+ import java .util .List ;
39
42
import java .util .Optional ;
40
43
import java .util .Properties ;
44
+ import java .util .concurrent .CompletableFuture ;
41
45
import java .util .concurrent .TimeUnit ;
46
+ import javax .naming .AuthenticationException ;
42
47
import javax .servlet .http .HttpServletRequest ;
43
48
import org .apache .pulsar .broker .ServiceConfiguration ;
44
49
import org .apache .pulsar .broker .authentication .utils .AuthTokenUtils ;
45
50
import org .apache .pulsar .common .api .AuthData ;
51
+ import org .apache .pulsar .common .util .FutureUtil ;
46
52
import org .assertj .core .util .Lists ;
47
53
import org .testng .annotations .AfterMethod ;
48
54
import org .testng .annotations .BeforeMethod ;
@@ -261,4 +267,125 @@ public void testAuthenticateHttpRequest() throws Exception {
261
267
verify (requestBB ).setAttribute (eq (AuthenticatedDataAttributeName ), isA (AuthenticationDataSource .class ));
262
268
}
263
269
264
- }
270
+ @ Test
271
+ public void testAuthenticateWithMultipleProviders () throws Exception {
272
+ HttpServletRequest httpRequest = mock (HttpServletRequest .class );
273
+ AuthenticationDataSource authenticationDataSource = mock (AuthenticationDataSource .class );
274
+
275
+ AuthenticationProvider failingProvider = mock (AuthenticationProvider .class );
276
+ List <AuthenticationProvider > providers = Lists .newArrayList (
277
+ failingProvider
278
+ );
279
+ try (AuthenticationProvider provider = new AuthenticationProviderList (providers )) {
280
+ provider .initialize (new ServiceConfiguration ());
281
+ RuntimeException authenticateException = new RuntimeException ("authenticateException" );
282
+
283
+ when (failingProvider .authenticateAsync (authenticationDataSource ))
284
+ .thenReturn (FutureUtil .failedFuture (authenticateException ));
285
+ when (failingProvider .authenticate (authenticationDataSource ))
286
+ .thenThrow (authenticateException );
287
+ assertThat (provider .authenticateAsync (authenticationDataSource ))
288
+ .failsWithin (3 , TimeUnit .SECONDS )
289
+ .withThrowableThat ().withCause (authenticateException );
290
+ assertThatThrownBy (() -> provider .authenticate (authenticationDataSource ))
291
+ .isInstanceOf (AuthenticationException .class )
292
+ .hasCause (authenticateException );
293
+
294
+ RuntimeException authenticateHttpRequestException = new RuntimeException ("authenticateHttpRequestAsync" );
295
+ when (failingProvider .authenticateHttpRequestAsync (httpRequest , null ))
296
+ .thenReturn (FutureUtil .failedFuture (authenticateHttpRequestException ));
297
+ when (failingProvider .authenticateHttpRequest (httpRequest , null ))
298
+ .thenThrow (authenticateHttpRequestException );
299
+ assertThat (provider .authenticateHttpRequestAsync (httpRequest , null ))
300
+ .failsWithin (3 , TimeUnit .SECONDS )
301
+ .withThrowableThat ()
302
+ .havingCause ()
303
+ .withCause (authenticateHttpRequestException );
304
+ assertThatThrownBy (() -> provider .authenticateHttpRequest (httpRequest , null ))
305
+ .isInstanceOf (AuthenticationException .class )
306
+ .hasCause (authenticateHttpRequestException );
307
+
308
+ RuntimeException newAuthStateException = new RuntimeException ("newAuthState" );
309
+ when (failingProvider .newAuthState (null , null , null ))
310
+ .thenThrow (newAuthStateException );
311
+ assertThatThrownBy (() -> provider .newAuthState (null , null , null ))
312
+ .isInstanceOf (AuthenticationException .class )
313
+ .hasCause (newAuthStateException );
314
+
315
+ RuntimeException newHttpAuthStateException = new RuntimeException ("newHttpAuthState" );
316
+ when (failingProvider .newHttpAuthState (httpRequest ))
317
+ .thenThrow (newHttpAuthStateException );
318
+ assertThatThrownBy (() -> provider .newHttpAuthState (httpRequest ))
319
+ .isInstanceOf (AuthenticationException .class )
320
+ .hasCause (newHttpAuthStateException );
321
+ }
322
+
323
+ AuthenticationProvider successfulProvider = mock (AuthenticationProvider .class );
324
+ providers .add (successfulProvider );
325
+ String subject = "test-role" ;
326
+
327
+ try (AuthenticationProvider provider = new AuthenticationProviderList (providers )) {
328
+ provider .initialize (new ServiceConfiguration ());
329
+
330
+ when (successfulProvider .authenticateAsync (authenticationDataSource ))
331
+ .thenReturn (CompletableFuture .completedFuture (subject ));
332
+ when (successfulProvider .authenticate (authenticationDataSource ))
333
+ .thenReturn (subject );
334
+ assertThat (provider .authenticateAsync (authenticationDataSource ))
335
+ .succeedsWithin (3 , TimeUnit .SECONDS )
336
+ .matches (subject ::equals );
337
+ assertThat (provider .authenticate (authenticationDataSource ))
338
+ .isEqualTo (subject );
339
+
340
+ when (successfulProvider .authenticateHttpRequestAsync (httpRequest , null ))
341
+ .thenReturn (CompletableFuture .completedFuture (true ));
342
+ when (successfulProvider .authenticateHttpRequest (httpRequest , null ))
343
+ .thenReturn (true );
344
+ assertThat (provider .authenticateHttpRequestAsync (httpRequest , null ))
345
+ .succeedsWithin (3 , TimeUnit .SECONDS )
346
+ .isEqualTo (true );
347
+ assertThat (provider .authenticateHttpRequest (httpRequest , null ))
348
+ .isEqualTo (true );
349
+
350
+ AuthenticationState authenticationState = new AuthenticationState () {
351
+ @ Override
352
+ public String getAuthRole () {
353
+ return subject ;
354
+ }
355
+
356
+ @ Override
357
+ public AuthData authenticate (AuthData authData ) {
358
+ return null ;
359
+ }
360
+
361
+ @ Override
362
+ public AuthenticationDataSource getAuthDataSource () {
363
+ return null ;
364
+ }
365
+
366
+ @ Override
367
+ public boolean isComplete () {
368
+ return false ;
369
+ }
370
+ };
371
+ when (successfulProvider .newAuthState (null , null , null ))
372
+ .thenReturn (authenticationState );
373
+ when (successfulProvider .newHttpAuthState (httpRequest )).thenReturn (authenticationState );
374
+ verifyAuthenticationStateSuccess (provider .newAuthState (null , null , null ), true , subject );
375
+ verifyAuthenticationStateSuccess (provider .newAuthState (null , null , null ), false , subject );
376
+ verifyAuthenticationStateSuccess (provider .newHttpAuthState (httpRequest ), true , subject );
377
+ verifyAuthenticationStateSuccess (provider .newHttpAuthState (httpRequest ), false , subject );
378
+ }
379
+ }
380
+
381
+ private void verifyAuthenticationStateSuccess (AuthenticationState authState , boolean isAsync , String expectedRole )
382
+ throws Exception {
383
+ assertThat (authState ).isNotNull ();
384
+ if (isAsync ) {
385
+ assertThat (authState .authenticateAsync (null )).succeedsWithin (3 , TimeUnit .SECONDS );
386
+ } else {
387
+ assertThat (authState .authenticate (null )).isNull ();
388
+ }
389
+ assertThat (authState .getAuthRole ()).isEqualTo (expectedRole );
390
+ }
391
+ }
0 commit comments