Client API. The Codename One framework your app is built on: this runs on the device, not in a backend.

public final class OidcRequestAuthorizer

  1. Object
  2. OidcRequestAuthorizer

ImplementsRequestAuthorizer, RequestAuthorizer.Proactive

Sends an OidcClient’s access token with the application’s requests, and renews it with the refresh token when the service refuses it.

OidcRequestAuthorizer authorizer = new OidcRequestAuthorizer(client);
authorizer.install("https://api.example.com");
authorizer.load();          // a session saved by an earlier run, if there is one

From then on every request under that base URL carries Authorization: Bearer ..., generated @RestClient clients included. The authorizer follows its client: tokens obtained by OidcClient.authorize(), OidcClient.refresh(String) or the device grant are picked up as they arrive, and OidcClient.clearStoredTokens() drops them.

When the service answers 401

The request is held and the refresh token is exchanged for a new set – once, however many requests were refused together; they all wait for the same exchange. Each is then sent again with the new access token. See RequestAuthorizer for what the caller of a request sees.

When the authorization server returns a permanent refresh error, the session is over: the tokens are dropped from memory and from the TokenStore, the held requests deliver their 401, and every SignInRequiredListener is told so the application can show its sign-in screen. Transport failures, malformed responses, and the provider’s server_error or temporarily_unavailable errors keep the tokens: nothing has said they are bad.

Before the token expires

A refusal is the fallback, not the way a token is normally renewed. When a request is queued and the access token is within setRefreshLeeway(int) of its expiry – sixty seconds unless set – the refresh token is exchanged first and the request is kept out of the queue until the exchange is done. It is then sent once, with the new token. Requests queued in the meantime wait for the same exchange.

Nothing blocks for this: the request has simply not been handed to a network thread yet. Code that waits for it – addToQueueAndWait, the blocking methods of RequestBuilder – returns the one final answer.

If that exchange is refused the session ends as described above, and the request goes out with no token for the service to answer 401. If it fails without an answer the request is sent with the token it has, which may still be good, and no exchange is tried ahead of time for the next few seconds.

A token whose response carried no expires_in has no known expiry, and is renewed only when the service refuses it.

Threads

Everything an authorizer holds – the tokens, the exchange in progress, the listeners – belongs to the event dispatch thread and is read and changed nowhere else. Nothing here is locked. A network thread never calls an authorizer: it sends the header the EDT put on the request when the request was queued. Tokens that arrive on a network thread, and a 401 seen there, are passed to the EDT before the authorizer hears of them.

Call this class on the EDT. The methods that read or change its state can also be called from another thread, and then wait for the EDT to do the work – so not from a thread the EDT is itself waiting for.

Nested types

interface OidcRequestAuthorizer.SignInRequiredListenerTold when the user has to sign in again.

Constructors

public OidcRequestAuthorizer(OidcClient client)An authorizer for the tokens of client.

Methods

public OidcRequestAuthorizer install(String baseUrl)Registers this authorizer for every request under a base URL.
public AsyncResource<OidcTokens> load()Reads the tokens an earlier run saved into memory.
public OidcTokens getTokens()The tokens in use.
public void setTokens(OidcTokens tokens)Replaces the tokens in use.
public boolean isSignedIn()Whether there is an access token to send.
public AsyncResource<Boolean> signOut()Drops the tokens from memory and from the client’s TokenStore.
public void addSignInRequiredListener(OidcRequestAuthorizer.SignInRequiredListener listener)Adds a listener told when the session can’t be renewed.
public void removeSignInRequiredListener(OidcRequestAuthorizer.SignInRequiredListener listener)Removes a listener.
public OidcRequestAuthorizer setRefreshLeeway(int seconds)How close to its expiry an access token is renewed before a request is sent with it.
public int getRefreshLeeway()The leeway set with setRefreshLeeway(int).
public String getAuthorization(ConnectionRequest request)Called on the event dispatch thread as a request is queued; the request carries the answer to the network thread.
public AsyncResource<Boolean> prepareAuthorization(ConnectionRequest request)Called on the event dispatch thread as a request is queued.
public AsyncResource<Boolean> refreshAuthorization(ConnectionRequest request, String rejectedAuthorization)Called after the service answered 401 to a request that carried this authorizer’s header.

Inherited nested types

Inherited fields

Inherited methods

Constructor details

OidcRequestAuthorizer

public OidcRequestAuthorizer(OidcClient client)

An authorizer for the tokens of client.

A client has one authorizer: creating a second one for the same client takes its place.

Parameters

client OidcClient
a configured client

Method details

install

public OidcRequestAuthorizer install(String baseUrl)
Registers this authorizer for every request under a base URL. Shorthand for NetworkManager.setAuthorizer(String, RequestAuthorizer), whose matching rules apply.

Parameters

baseUrl String
the base URL of the application’s service

Returns

this authorizer

load

public AsyncResource<OidcTokens> load()
Reads the tokens an earlier run saved into memory. Call it when the application starts; with a SecureStorageTokenStore that requires biometrics, this is the one moment the user is prompted.

Returns

a resource that completes with the tokens, or with null when nothing was stored

getTokens

public OidcTokens getTokens()
The tokens in use.

Returns

the tokens, or null when nobody is signed in

setTokens

public void setTokens(OidcTokens tokens)
Replaces the tokens in use. Tokens the client obtains arrive here by themselves; this is for a set that came from somewhere else.

Parameters

tokens OidcTokens
the tokens, or null for none

isSignedIn

public boolean isSignedIn()
Whether there is an access token to send.

signOut

public AsyncResource<Boolean> signOut()

Drops the tokens from memory and from the client’s TokenStore. Requests go out without a header from then on. This doesn’t tell the server; call OidcClient.revoke(String) with the refresh token first for that.

A renewal in progress is abandoned: whatever it comes back with is dropped, and the requests waiting for it go out with no token.

Returns

the result of clearing the store

addSignInRequiredListener

public void addSignInRequiredListener(OidcRequestAuthorizer.SignInRequiredListener listener)
Adds a listener told when the session can’t be renewed.

removeSignInRequiredListener

public void removeSignInRequiredListener(OidcRequestAuthorizer.SignInRequiredListener listener)
Removes a listener.

setRefreshLeeway

public OidcRequestAuthorizer setRefreshLeeway(int seconds)
How close to its expiry an access token is renewed before a request is sent with it. Sixty seconds unless set: long enough for the request to reach a service whose clock runs a little ahead. Zero renews a token only once it has expired, and a negative value turns renewing ahead of time off, leaving the 401 as the only trigger.

Parameters

seconds int
the leeway in seconds

Returns

this authorizer

getRefreshLeeway

public int getRefreshLeeway()
The leeway set with setRefreshLeeway(int).

getAuthorization

public String getAuthorization(ConnectionRequest request)
Called on the event dispatch thread as a request is queued; the request carries the answer to the network thread.

Parameters

request ConnectionRequest
the request being queued

Returns

the header value, or null to send the request without one

prepareAuthorization

public AsyncResource<Boolean> prepareAuthorization(ConnectionRequest request)
Called on the event dispatch thread as a request is queued.

Parameters

request ConnectionRequest
the request being queued

Returns

null when the request can be sent as it is; otherwise a resource that completes when it can – with any value, or with an error: the request is sent either way, with whatever RequestAuthorizer.getAuthorization(ConnectionRequest) answers then

refreshAuthorization

public AsyncResource<Boolean> refreshAuthorization(ConnectionRequest request, String rejectedAuthorization)

Called after the service answered 401 to 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 rejectedAuthorization that is no longer the current one: that request was sent before an earlier renewal finished, and only needs sending again.

Parameters

request ConnectionRequest
the request that was refused
rejectedAuthorization String
the header value the service refused

Returns

a resource that completes with true once a different credential is ready, and with false or an error when there is none to be had. Null means the same as false