Skip navigation links

Package com.devexperts.qd.qtp.auth

QTP authentication and authorization, modeled after HTTP Basic Auth (RFC 7617).

See: Description

Package com.devexperts.qd.qtp.auth Description

QTP authentication and authorization, modeled after HTTP Basic Auth (RFC 7617).

Wire protocol

Two ProtocolDescriptor properties carry auth state:

Property value semantics

PropertyValueMeaning
authentication"LOGIN <realm>" Server challenges client (like HTTP WWW-Authenticate)
authenticationnon-empty error string Server reports auth failure
authentication"" (empty) Server confirms success (like HTTP 200 OK)
authenticationabsent No change; receiver retains last value
authorizationtoken string Client sends credentials (like HTTP Authorization)

Properties accumulate across DESCRIBE_PROTOCOL messages within a connection. A property not present in a new message survives from the previous descriptor. The only way to clear a property on the remote side is to send an explicit replacement value.

Protocol exchange

Happy path

 Server                                        Client
   |                                             |
   |--- authentication="LOGIN MyRealm" --------->|   (challenge)
   |                                             |
   |      [QDLoginHandler.login() -> Promise]    |
   |                                             |
   |<-- authorization="Basic dXNlcjpwYXNz" ------|   (credentials)
   |                                             |
   |    [QDAuthRealm.authenticate() -> Promise]  |
   |                                             |
   |--- authentication="" ---------------------->|   (success + data flow begins)
   |                                             |
 

Authentication failure

Server's authenticate() promise rejects: AuthManager moves to AUTH_FAILED, the failure message is sent as a non-empty authentication value. The client treats any non-empty authentication value as a fresh login prompt and re-runs login(reason) with the error text.
 Server                                        Client
   |<-- authorization="Basic dXNlcjpwYXNz" ------|
   |    [QDAuthRealm.authenticate() rejects]     |
   |--- authentication="bad credentials" ------->|   (failure, NOT empty)
   |                                             |
   |      [QDLoginHandler.login("bad ...")]      |
   |<-- authorization="Basic dXNlcjpwYXNzMg==" --|   (retry with new token)
   |                                             |
 

Idempotent re-challenge / re-send

The receiver accumulates properties across DESCRIBE_PROTOCOL messages, so a peer that re-emits a property the other side has already processed must not re-invoke the QDAuthRealm / QDLoginHandler implementation. On the server side MessageAdapter guards by lastProcessedAuthToken: an authorization with the same token as the previous call is dropped before reaching authManager.authenticate(). On the client side LoginManager guards by lastSendAccessToken and ignores a repeated "LOGIN ..." challenge while already in LOGIN / WAITING_OTHER_SIDE / COMPLETED.

Post-login DESCRIBE_PROTOCOL re-send

After authentication completes, either side may re-emit DESCRIBE_PROTOCOL carrying an unrelated delta (e.g. client-side setRequestedAggregationPeriod). The auth properties are NOT re-attached: LoginManager skips writing authorization while in WAITING_OTHER_SIDE / COMPLETED, and MessageAdapter writes authentication="" on every outgoing descriptor only because the receiver already processed it once and discards the redundant repeat.
 Server                                        Client
   |--- authentication="" ---------------------->|   (auth complete)
   |<-- requestedAggregationPeriod="1s" ---------|   (delta only, NO authorization re-sent)
   |                                             |
 

Server side

Implement QDAuthRealm and register via QDAuthRealmFactory (SPI). The realm's authenticate method receives the client's token and returns a Promise that resolves to an AuthSession on success or an exception on failure.

Internally, AuthManager (package-private, in com.devexperts.qd.qtp) drives the server-side state machine. The on-wire authentication value is split across two write sites: AuthManager.prepareAuthenticate writes the challenge ("LOGIN <realm>") and the failure string from its reason field, while MessageAdapter.prepareProtocolDescriptor writes the empty success value directly based on AuthManager.isAuthComplete(). Both writes are a pure function of AuthManager's current state and are never consumed by the act of sending — the value changes only via state transitions.

Client side

Implement QDLoginHandler and register via QDLoginHandlerFactory (SPI). The handler's login method receives the server's challenge or error and returns a Promise that resolves to an AuthToken.

Internally, LoginManager (package-private, in com.devexperts.qd.qtp) drives the client-side state machine. The authorization value is written by LoginManager.prepareProtocolDescriptor and, symmetric to the server side, is a pure function of LoginManager's current state — once the token has been emitted, the manager moves to WAITING_OTHER_SIDE / COMPLETED and stops re-attaching the token to subsequent descriptors.

See Also:
QDAuthRealm, QDLoginHandler, ProtocolDescriptor
Skip navigation links

Copyright © 2002–2026 Devexperts LLC. All rights reserved.