Class OidcClient

java.lang.Object
com.codename1.io.oidc.OidcClient

public final class OidcClient extends Object

Modern OpenID Connect / OAuth 2.0 client. Built around the authorization-code flow with PKCE (RFC 7636) and the system browser. Use it as the foundation for all new sign-in integrations:

OidcClient.discover("https://accounts.google.com").ready(new SuccessCallback<OidcClient>() {
    public void onSucess(OidcClient client) {
        client.setClientId("YOUR_CLIENT_ID")
              .setRedirectUri("com.example.app:/oauth2redirect")
              .setScopes("openid", "email", "profile");
        client.authorize().ready(new SuccessCallback<OidcTokens>() {
            public void onSucess(OidcTokens tokens) {
                // use tokens.getAccessToken() / tokens.getIdToken()
            }
        });
    }
});

What this gives you that Oauth2 does not

  • Discovery via .well-known/openid-configuration so you only configure the issuer URL, not five separate endpoints
  • PKCE S256 on every flow (mandatory; many providers now require it)
  • System-browser sign-in via SystemBrowser (the previous class used an in-app WebView that modern IdPs reject)
  • Refresh-token flow surfaced as a first-class method
  • ID-token claim decoding via OidcTokens.getClaim(String)
  • Pluggable TokenStore persistence
  • Nonce + state verification on every authorization round-trip

What is checked before tokens are handed over

  • The authorization response: its state, and the issuer it names. A response that names another issuer than this client's is refused, and so is one that names none when the provider's discovery document says it always does (RFC 9207). That is what stops a response from one provider being taken for another's.
  • The ID token's claims: iss is the provider, aud is this client, exp has not passed, nonce is the one the request carried, and at_hash, when the token has one, is the hash of the access token it came with.
  • The ID token's signature, against the provider's keys. The keys are fetched from the configuration's jwks_uri once and kept, and fetched again when a token names a key that is not among them. RS256, RS384, RS512, ES256 and ES384 are accepted; an unsigned token, or one signed with the client secret, is not.

A token that fails any of this is not stored and not returned: the resource fails with OidcException.INVALID_ID_TOKEN, OidcException.NONCE_MISMATCH or OidcException.ISSUER_MISMATCH. That includes a signature this platform has no way to check. Nothing is skipped quietly -- see setVerifyIdTokenSignature(boolean) for the one switch there is, and what turning it off gives up.

Things this class deliberately does NOT do

  • Implicit and hybrid flows. Use the lower-level ConnectionRequest APIs if you need those.

A device without a browser or a keyboard

requestDeviceAuthorization() and pollDeviceToken(OidcDeviceAuthorization) run the device authorization grant (RFC 8628): the device shows a short code, the user approves it on a phone or a computer, and the device receives its tokens.

Using the tokens

OidcRequestAuthorizer attaches the access token to the application's requests and renews it with the refresh token when the service refuses it.

  • Method Details

    • create

      public static OidcClient create(OidcConfiguration configuration)
      Constructs a client from an already-known OidcConfiguration. Use discover(String) when you'd rather pull the endpoints from the provider's .well-known/openid-configuration document.
    • discover

      public static AsyncResource<OidcClient> discover(String issuer)

      Fetches <issuer>/.well-known/openid-configuration and resolves with an OidcClient pre-populated with the discovered endpoints. The returned client still needs clientId, redirectUri and scopes before authorize() will work.

      Trailing slashes are removed when building the discovery request URL. The metadata's issuer must still exactly match the supplied issuer, including its trailing slashes, before any discovered endpoints are accepted.

    • getConfiguration

      public OidcConfiguration getConfiguration()
    • setClientId

      public OidcClient setClientId(String clientId)
    • setClientSecret

      public OidcClient setClientSecret(String clientSecret)
    • setRedirectUri

      public OidcClient setRedirectUri(String redirectUri)
    • setScopes

      public OidcClient setScopes(String... scopes)
    • setScopes

      public OidcClient setScopes(List<String> scopes)
    • setAuthorizationParameters

      public OidcClient setAuthorizationParameters(String... kv)
      Extra name=value parameters appended to the authorization-endpoint URL. Use for provider-specific options like Google's prompt=consent or Apple's response_mode=form_post. Values are URL-encoded.
    • setTokenParameters

      public OidcClient setTokenParameters(String... kv)
      Extra name=value parameters sent as form data on every token-endpoint POST.
    • setTokenStore

      public OidcClient setTokenStore(TokenStore store)
      Swaps the token persistence strategy. Defaults to TokenStore.DefaultStorageTokenStore.
    • setStoreKey

      public OidcClient setStoreKey(String key)
      Override the key under which tokens are stored. Defaults to the issuer + client-id pair so that multiple clients can coexist.
    • setEnforceNonce

      public OidcClient setEnforceNonce(boolean enforce)
      false skips the nonce claim check on the returned ID token. Only disable when you have a very good reason (e.g. provider known not to echo the nonce); the default is to enforce.
    • setVerifyIdTokenSignature

      public OidcClient setVerifyIdTokenSignature(boolean verify)

      Whether an ID token's signature is verified against the provider's keys before the token is accepted. True unless set.

      With it on, a token whose signature cannot be checked is refused -- because it does not verify, because the configuration names no jwks_uri, or because the platform the app is running on cannot verify a signature of that algorithm. The last one is the reason this switch exists: turn it off for a provider whose ID tokens cannot be verified on a platform you ship to, and for no other reason.

      With it off, the claims are still checked, but they are only as good as the TLS connection to the token endpoint. Do not make a decision on your server from an ID token the app forwards: verify it there.

    • setIdTokenClockSkew

      public OidcClient setIdTokenClockSkew(int seconds)
      How far the device's clock may be from the provider's when an ID token's exp is checked. Five minutes unless set: phones are set by hand more often than servers.
    • setResponseMode

      public OidcClient setResponseMode(String mode)
      Sets the response_mode parameter sent on the authorization URL (e.g. "form_post" for Apple Sign-In with the web fallback).
    • authorize

      public AsyncResource<OidcTokens> authorize()
      Launches an authorization-code flow with PKCE. The user is sent to the system browser to sign in; the returned AsyncResource completes with the token set or errors with OidcException (e.g. USER_CANCELLED, STATE_MISMATCH).
    • refresh

      public AsyncResource<OidcTokens> refresh(String refreshToken)

      Exchanges a stored refresh token for a fresh access token. Pass the value returned from OidcTokens.getRefreshToken() on a previous flow. The stored session supplies the original subject for any refreshed ID token. A refresh response cannot change that subject. The new tokens are persisted via the current TokenStore.

      Cancelling the returned resource before it completes drops the answer: nothing is stored and no OidcRequestAuthorizer is given the new tokens.

    • loadStoredTokens

      public AsyncResource<OidcTokens> loadStoredTokens()
      Returns previously-saved tokens for this client (or null). Combine with refreshIfExpired(int) to silently bring the session back to life on app launch.
    • refreshIfExpired

      public AsyncResource<OidcTokens> refreshIfExpired(int leewaySeconds)
      Loads stored tokens; if they are within leewaySeconds of expiring, runs a refresh and saves the new tokens. Completes with null when nothing is stored or when the stored token has no refresh token and has already expired.
    • revoke

      public AsyncResource<Boolean> revoke(String token)
      Sends a token-revocation request to the issuer (RFC 7009). Silently no-ops when the issuer does not advertise a revocation_endpoint. A refused request reports the OAuth error, or a transport error when the non-success HTTP response contains no OAuth error.
    • clearStoredTokens

      public AsyncResource<Boolean> clearStoredTokens()
      Clears any stored tokens for this client. Does not call the issuer's revocation endpoint -- combine with revoke(String) if you want a proper sign-out. The returned resource completes after earlier saves and this clear finish, so a delayed save cannot restore the cleared session.
    • requestDeviceAuthorization

      public AsyncResource<OidcDeviceAuthorization> requestDeviceAuthorization()

      Starts the device authorization grant (RFC 8628), for a device with no browser or no practical way to type: a television, a watch, a kiosk, a command line.

      The answer holds a short code. Show it with the verification address; the user opens that address on another device, signs in and types the code. Meanwhile pass the answer to pollDeviceToken(OidcDeviceAuthorization), which completes once they have.

      Needs a client id, the scopes, and a provider whose configuration names a device_authorization_endpoint. No redirect URI is involved.

      Returns

      a resource that completes with the codes, or fails with an OidcException carrying the server's error code

      Throws
      • IllegalStateException: when the client id is missing, or the provider does not offer the grant
    • pollDeviceToken

      public AsyncResource<OidcTokens> pollDeviceToken(OidcDeviceAuthorization authorization)

      Waits for the user to approve a device, by asking the token endpoint at the pace the server set.

      The wait is a timer, not a thread: each request is queued when the previous answer's interval has passed. The interval starts at OidcDeviceAuthorization.getInterval() and grows by five seconds every time the server answers slow_down, and doubles after a request that failed to reach the server at all.

      The resource completes with the tokens, which are saved to the TokenStore the way authorize() saves them. It fails with an OidcException whose code is OidcException.ACCESS_DENIED when the user refused, OidcException.EXPIRED_TOKEN when the codes ran out -- by the server's word or by the clock -- or whatever other code the server sent. Cancelling the resource stops the polling.

      Parameters
      Returns

      a resource that completes with the tokens