class TokenRequest extends BaseRequest<TokenResponse, AuthorizationException> {

    @Override
    public TokenResponse executeRequest(OktaHttpClient client) throws AuthorizationException {
        HttpResponse response = null;
        TokenResponse tokenResponse;
        try {
            response = openConnection(client);
            JSONObject json = response.asJson();
            if (json.has(AuthorizationException.PARAM_ERROR)) {
                try {
                    final String error = json.getString(AuthorizationException.PARAM_ERROR);
                    throw AuthorizationException.fromOAuthTemplate(
                            AuthorizationException.TokenRequestErrors.byString(error),
                            error,
                            json.optString(AuthorizationException.PARAM_ERROR_DESCRIPTION,
                                    null),
                            UriUtil.parseUriIfAvailable(
                                    json.optString(AuthorizationException.PARAM_ERROR_URI)));
                } catch (JSONException jsonEx) {
                    throw AuthorizationException.fromTemplate(
                            AuthorizationException.GeneralErrors.JSON_DESERIALIZATION_ERROR,
                            jsonEx);
                }
            }
            tokenResponse = new Gson().fromJson(json.toString(), TokenResponse.class);
            tokenResponse.setCreationTime(System.currentTimeMillis());
            if (tokenResponse.getIdToken() != null) {
                OktaIdToken idToken;
                try {
                    idToken = OktaIdToken.parseIdToken(tokenResponse.getIdToken());
                } catch (IllegalArgumentException | JsonIOException ex) {
                    Log.e(TAG, "", ex);
                    throw AuthorizationException.fromTemplate(
                            AuthorizationException.GeneralErrors.ID_TOKEN_PARSING_ERROR,
                            ex);
                }
                idToken.validate(this, System::currentTimeMillis);
            }
            return tokenResponse;
        } catch (IOException ex) {
            throw new AuthorizationException(ex.getMessage(), ex);
        } catch (JSONException ex) {
            throw AuthorizationException.fromTemplate(
                    AuthorizationException.GeneralErrors.JSON_DESERIALIZATION_ERROR, ex);
        } catch (AuthorizationException ae) {
            throw ae;
        } catch (Exception e) {
            throw AuthorizationException.fromTemplate(AuthorizationException
                    .GeneralErrors.NETWORK_ERROR, e);
        } finally {
            if (response != null) {
                response.disconnect();
            }
        }
    }

      TokenRequest();
      TokenRequest(HttpRequestBuilder.TokenExchange b);

}