@@ -311,13 +311,9 @@ protected static boolean isTlsChannel(Channel channel) {
311
311
return channel .pipeline ().get (ServiceChannelInitializer .TLS_HANDLER ) != null ;
312
312
}
313
313
314
- private synchronized void completeConnect (AuthData clientData ) throws PulsarClientException {
314
+ private synchronized void completeConnect () throws PulsarClientException {
315
315
Supplier <ClientCnx > clientCnxSupplier ;
316
316
if (service .getConfiguration ().isAuthenticationEnabled ()) {
317
- if (service .getConfiguration ().isForwardAuthorizationCredentials ()) {
318
- this .clientAuthData = clientData ;
319
- this .clientAuthMethod = authMethod ;
320
- }
321
317
clientCnxSupplier = () -> new ProxyClientCnx (clientConf , service .getWorkerGroup (), clientAuthRole ,
322
318
clientAuthData , clientAuthMethod , protocolVersionToAdvertise ,
323
319
service .getConfiguration ().isForwardAuthorizationCredentials (), this );
@@ -423,29 +419,51 @@ public void brokerConnected(DirectProxyHandler directProxyHandler, CommandConnec
423
419
// According to auth result, send newConnected or newAuthChallenge command.
424
420
private void doAuthentication (AuthData clientData )
425
421
throws Exception {
426
- AuthData brokerData = authState .authenticate (clientData );
427
- // authentication has completed, will send newConnected command.
428
- if (authState .isComplete ()) {
429
- clientAuthRole = authState .getAuthRole ();
430
- if (LOG .isDebugEnabled ()) {
431
- LOG .debug ("[{}] Client successfully authenticated with {} role {}" ,
432
- remoteAddress , authMethod , clientAuthRole );
433
- }
422
+ authState
423
+ .authenticateAsync (clientData )
424
+ .whenCompleteAsync ((authChallenge , throwable ) -> {
425
+ if (throwable == null ) {
426
+ authChallengeSuccessCallback (authChallenge );
427
+ } else {
428
+ authenticationFailedCallback (throwable );
429
+ }
430
+ }, ctx .executor ());
431
+ }
432
+
433
+ protected void authenticationFailedCallback (Throwable t ) {
434
+ LOG .warn ("[{}] Unable to authenticate: " , remoteAddress , t );
435
+ final ByteBuf msg = Commands .newError (-1 , ServerError .AuthenticationError , "Failed to authenticate" );
436
+ writeAndFlushAndClose (msg );
437
+ }
434
438
435
- // First connection
436
- if (this .connectionPool == null || state == State .Connecting ) {
437
- // authentication has completed, will send newConnected command.
438
- completeConnect (clientData );
439
+ // Always run in this class's event loop.
440
+ protected void authChallengeSuccessCallback (AuthData authChallenge ) {
441
+ try {
442
+ // authentication has completed, will send newConnected command.
443
+ if (authChallenge == null ) {
444
+ clientAuthRole = authState .getAuthRole ();
445
+ if (LOG .isDebugEnabled ()) {
446
+ LOG .debug ("[{}] Client successfully authenticated with {} role {}" ,
447
+ remoteAddress , authMethod , clientAuthRole );
448
+ }
449
+
450
+ // First connection
451
+ if (this .connectionPool == null || state == State .Connecting ) {
452
+ // authentication has completed, will send newConnected command.
453
+ completeConnect ();
454
+ }
455
+ return ;
439
456
}
440
- return ;
441
- }
442
457
443
- // auth not complete, continue auth with client side.
444
- final ByteBuf msg = Commands .newAuthChallenge (authMethod , brokerData , protocolVersionToAdvertise );
445
- writeAndFlush (msg );
446
- if (LOG .isDebugEnabled ()) {
447
- LOG .debug ("[{}] Authentication in progress client by method {}." ,
448
- remoteAddress , authMethod );
458
+ // auth not complete, continue auth with client side.
459
+ final ByteBuf msg = Commands .newAuthChallenge (authMethod , authChallenge , protocolVersionToAdvertise );
460
+ writeAndFlush (msg );
461
+ if (LOG .isDebugEnabled ()) {
462
+ LOG .debug ("[{}] Authentication in progress client by method {}." ,
463
+ remoteAddress , authMethod );
464
+ }
465
+ } catch (Exception e ) {
466
+ authenticationFailedCallback (e );
449
467
}
450
468
}
451
469
@@ -479,7 +497,7 @@ remoteAddress, protocolVersionToAdvertise, getRemoteEndpointProtocolVersion(),
479
497
480
498
// authn not enabled, complete
481
499
if (!service .getConfiguration ().isAuthenticationEnabled ()) {
482
- completeConnect (null );
500
+ completeConnect ();
483
501
return ;
484
502
}
485
503
@@ -493,6 +511,14 @@ remoteAddress, protocolVersionToAdvertise, getRemoteEndpointProtocolVersion(),
493
511
authMethod = "none" ;
494
512
}
495
513
514
+ if (service .getConfiguration ().isForwardAuthorizationCredentials ()) {
515
+ // We store the first clientData here. Before this commit, we stored the last clientData.
516
+ // Since this only works when forwarding single staged authentication, first == last is true.
517
+ // Here is an issue to fix the protocol: https://github.com/apache/pulsar/issues/19291.
518
+ this .clientAuthData = clientData ;
519
+ this .clientAuthMethod = authMethod ;
520
+ }
521
+
496
522
authenticationProvider = service
497
523
.getAuthenticationService ()
498
524
.getAuthenticationProvider (authMethod );
@@ -504,7 +530,7 @@ remoteAddress, protocolVersionToAdvertise, getRemoteEndpointProtocolVersion(),
504
530
.orElseThrow (() ->
505
531
new AuthenticationException ("No anonymous role, and no authentication provider configured" ));
506
532
507
- completeConnect (clientData );
533
+ completeConnect ();
508
534
return ;
509
535
}
510
536
@@ -518,9 +544,7 @@ remoteAddress, protocolVersionToAdvertise, getRemoteEndpointProtocolVersion(),
518
544
authState = authenticationProvider .newAuthState (clientData , remoteAddress , sslSession );
519
545
doAuthentication (clientData );
520
546
} catch (Exception e ) {
521
- LOG .warn ("[{}] Unable to authenticate: " , remoteAddress , e );
522
- final ByteBuf msg = Commands .newError (-1 , ServerError .AuthenticationError , "Failed to authenticate" );
523
- writeAndFlushAndClose (msg );
547
+ authenticationFailedCallback (e );
524
548
}
525
549
}
526
550
0 commit comments