Interface RequestAuthorizer
- All Known Subinterfaces:
RequestAuthorizer.Proactive
- All Known Implementing Classes:
OidcRequestAuthorizer
Supplies the Authorization header of the requests an application sends to its own
service, and renews it when the service refuses it.
An authorizer is given to one request with ConnectionRequest.setAuthorizer(RequestAuthorizer)
or RequestBuilder.authorizer(RequestAuthorizer), or to every request
under a base URL with NetworkManager.setAuthorizer(String, RequestAuthorizer):
NetworkManager.getInstance().setAuthorizer("https://api.example.com", authorizer);
OidcRequestAuthorizer is the implementation for a service that
accepts OAuth 2.0 access tokens.
What happens to a request
- As the request is queued,
getAuthorization(ConnectionRequest)is asked for a header value, which travels with the request. A request that already carries anAuthorizationheader keeps its own: one the caller set always wins, and so does a default header ofNetworkManager. - If the service answers
401, nothing is delivered yet. The request is held andrefreshAuthorization(ConnectionRequest, String)is asked for a new credential. - If that succeeds the request is sent once more with the new header, and its answer --
whatever it is, another
401included -- is delivered as usual. There is one renewal per request, so a service that keeps refusing cannot make this loop. - If it fails, the request is sent again as it first was, and the service's
401goes through the request's ordinary error handling exactly as it would have without an authorizer.
Code that waits for the request -- NetworkManager.addToQueueAndWait(ConnectionRequest), the
blocking methods of RequestBuilder, NetworkManager.addToQueueAsync(ConnectionRequest) --
keeps waiting through all of it and sees only the final answer.
An authorizer that knows when its credential expires can skip the refused request
altogether: see RequestAuthorizer.Proactive.
Threads
Every method of an authorizer is called on the event dispatch thread and on no other, so
an implementation keeps its credential in plain fields and needs no lock. A network
thread never calls one: it sends the header value that was put on the request, on the
EDT, when the request was queued or released after a renewal. A request queued from
another thread is passed to the EDT first, and so is a 401, which a network thread is
the one to see.
The header is therefore the one current when the request was queued. If the credential is renewed while the request waits in the queue, the service refuses the old one and the request is sent again with the new one, as step 2 describes.
getAuthorization(ConnectionRequest) must answer from memory. It must not wait for
another request: the EDT would wait on the queue it is filling. Renewing is therefore a
separate step, which the authorizer starts and answers later.
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic interfaceAn authorizer that can tell, before a request is sent, that its credential is about to stop working, and renew it first. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final RequestAuthorizerAn authorizer that never adds a header. -
Method Summary
Modifier and TypeMethodDescriptiongetAuthorization(ConnectionRequest request) The value of theAuthorizationheader for a request that is about to be sent, for example"Bearer eyJ...".refreshAuthorization(ConnectionRequest request, String rejectedAuthorization) Called after the service answered401to a request that carried this authorizer's header.
-
Field Details
-
NONE
An authorizer that never adds a header. Set on a request, it keeps the default ofNetworkManager.setAuthorizer(String, RequestAuthorizer)away from that one request -- the request that fetches the token itself is the usual case.
-
-
Method Details
-
getAuthorization
The value of the
Authorizationheader for a request that is about to be sent, for example"Bearer eyJ...".Called on the event dispatch thread: when the request is queued, and again when it is sent a second time with a renewed credential. Answer from memory and do not block. The value is copied to the request; a redirect is sent the same one for as long as it stays under the base URL the authorizer was registered for.
Parameters
request: the request being queued
Returns
the header value, or null to send the request without one
-
refreshAuthorization
AsyncResource<Boolean> refreshAuthorization(ConnectionRequest request, String rejectedAuthorization) Called after the service answered
401to a request that carried this authorizer's header. Called on the event dispatch thread, at most once per request.Several requests can be refused at the same moment. An implementation should renew its credential once and give every one of them the same answer, and should recognize a
rejectedAuthorizationthat is no longer the current one: that request was sent before an earlier renewal finished, and only needs sending again.Parameters
-
request: the request that was refused -
rejectedAuthorization: the header value the service refused
Returns
a resource that completes with
trueonce a different credential is ready, and withfalseor an error when there is none to be had. Null means the same asfalse -
-