Performing resource calls

Introduction

Starting from version 6.04.00 the Onegini SDK exposes instances of OkHttp 3 clients that are prepared for making secure resource calls to your backend. The instances are already pre configured and secured by the SDK, so that you do not need to worry about encrypting/decrypting the payload or certificate pinning. The client can be later on used with libraries like Retrofit 1.X and 2.X.

  • DeviceClient#getOkHttpClient() returns an instance of the OkHttpClient with security features like certificate pinning, but no user/device authentication.
  • DeviceClient#getAnonymousResourceOkHttpClient() returns an instance of secured client that also uses device credentials for authentication.
  • UserClient#getResourceOkHttpClient() returns an instance of secured client that also uses user's credentials for authentication.

In older versions of the SDK instances of retrofit.client.OkClient from Retrofit 1.9 are exposed using methods like UserClient#getResourceRetrofitClient, DeviceClient#getAnonymousResourceRetrofitClient. Starting from 6.04.00 those methods are marked as deprecated and are scheduled to be removed in next major release, so please use the new OkHttp 3 clients instead.

Get resource flow

Secured resource access

  1. APP → SDK: Build REST adapter based secured client provided by the SDK.
  2. SDK → Resource Gateway: Request a resource at the resource gateway.
  3. Resource Gateway → Token Server: Validate the provided token.
  4. Token Server → Resource Gateway: Details regarding the access token like scope and user, which will be verified by the resource gateway.
  5. Resource Gateway → Resource Server: Get the resource.
  6. Resource Server → Resource Gateway: Return the resource.
  7. Resource Gateway → App: Return the resource.

Using OkHttp 3 client with Retrofit 1.X and 2.X

The OkHttp 3 clients that are returned by the SDK (DeviceClient#getOkHttpClient(), DeviceClient#getAnonymousResourceOkHttpClient(), UserClient#getResourceOkHttpClient(), UserClient#getImplicitResourceOkHttpClient()) can be used with both Retrofit 1.X and 2.X. Because of that we strongly advise to use those methods rather than retrofit.client.OkClient returned by deprecated SDK methods.

In Retrofit 2.X the Retrofit.Builder() expects that an instance of the OkHttpClient will be provided with the client method:

private static <T> T prepareSecuredRetrofit2Client(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
  final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
  final Retrofit retrofit = new Retrofit.Builder()
    .client(okHttpClient)
    // ...
    .build();

  return retrofit.create(clazz);
}

In Retrofit 1.X you need to use additional dependency called retrofit1-okhttp3-client. Then the client can be set with:

private static <T> T prepareSecuredRetrofitClient(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
  final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
  final RestAdapter restAdapter = new RestAdapter.Builder()
    .setClient(new Ok3Client(okHttpClient))
    // ...
    .build();
  return restAdapter.create(clazz);
}

Fetching resource anonymously

A device can use it's OAuth credentials in order to obtain an Access Token object, which in turn can be used for proofing its authenticity. An anonymous resource call can be typically used in cases where a user does not need to login or register in order to use certain functionality, or access some resource.

Authenticate the device

The SDK gives you the flexibility of being in control over building the requests and handling the responses. Therefore, it is your responsibility to perform device authentication with DeviceClient#authenticateDevice whenever the Resource Gateway responds with the 401 unauthorized status code. Once the device has been authenticated using DeviceClient#authenticateDevice method, it is possible to start fetching resources.

Example code for authenticating the device

private void authenticateDevice() {
  authenticatedUserProfile = OneginiSDK.getOneginiClient(this).getUserClient().getAuthenticatedUserProfile();
  OneginiSDK.getOneginiClient(this).getDeviceClient()
      .authenticateDevice(new String[]{ "application-details" }, new OneginiDeviceAuthenticationHandler() {
            @Override
            public void onSuccess() {
              callAnonymousResourceCallToFetchApplicationDetails();
            }

            @Override
            public void onError(final OneginiDeviceAuthenticationError error) {
              final @OneginiDeviceAuthenticationError.DeviceAuthenticationErrorType int errorType = error.getErrorType();
              if (errorType == OneginiDeviceAuthenticationError.DEVICE_DEREGISTERED) {
                onDeviceDeregistered();
              } else if (errorType == OneginiDeviceAuthenticationError.USER_DEREGISTERED) {
                onUserDeregistered(authenticatedUserProfile);
              } else {
                displayError(error);
              }
            }
          }
      );
}

Defining the REST interface

The first step we need to take in order to fetch resources anonymously is to define a REST interface. Please note that the path application-details is relative to the endpoint which we need to configure on the HTTP client before making a call. Also the endpoint URL definition looks slightly different when comparing Retrofit 1.X and 2.X. Please follow one of many Retrofit tutorials for details.

Client definition for Retrofit 1.9

import com.onegini.mobile.exampleapp.model.ApplicationDetails;
import retrofit.http.GET;
import rx.Observable;

public interface AnonymousClient {

  @GET("/application-details")
  Observable<ApplicationDetails> getApplicationDetails();
}

Client definition for Retrofit 2.X

import com.onegini.mobile.exampleapp.model.ApplicationDetails;
import retrofit2.http.GET;
import rx.Observable;

public interface AnonymousClient2 {

  @GET("application-details")
  Observable<ApplicationDetails> getApplicationDetails();
}

Defining the REST Adapter

Next, we need to setup the Retrofit instance by providing the anonymousClient (DeviceClient#getAnonymousResourceOkHttpClient() or deprecated DeviceClient#getAnonymousResourceRetrofitClient()), Resource Gateway url and also REST interface which we have defined in the previous step.

Example code

import android.content.Context;
import com.onegini.mobile.exampleapp.model.ApplicationDetails;
import com.onegini.mobile.exampleapp.network.client.AnonymousClient;
import com.onegini.mobile.exampleapp.network.client.SecureResourceClient;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;

public class AnonymousService {

  private static AnonymousService instance;

  public static AnonymousService getInstance(final Context context) {
    if (instance == null) {
      instance = new AnonymousService(context);
    }
    return instance;
  }

  // the client using Retrofit 1.9
  private final AnonymousClient applicationDetailsRetrofitClient;
  // the client using Retrofit 2.X
  private final AnonymousClient2 applicationDetailsRetrofit2Client;

  private AnonymousService(final Context context) {
    applicationDetailsRetrofitClient = SecureResourceClient.prepareSecuredAnonymousRetrofitClient(AnonymousClient.class, context);
    applicationDetailsRetrofit2Client = SecureResourceClient.prepareSecuredAnonymousRetrofit2Client(AnonymousClient2.class, context);
  }

  public Observable<ApplicationDetails> getApplicationDetails(final boolean useRetrofit2) {
    return getObservable(useRetrofit2)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .unsubscribeOn(Schedulers.io());
  }

  private Observable<ApplicationDetails> getObservable(final boolean useRetrofit2) {
    if (useRetrofit2) {
      return applicationDetailsRetrofit2Client.getApplicationDetails();
    } else {
      return applicationDetailsRetrofitClient.getApplicationDetails();
    }
  }
}
import android.content.Context;
import com.google.gson.GsonBuilder;
import com.onegini.mobile.sdk.android.client.OneginiClient;
import com.onegini.mobile.exampleapp.OneginiSDK;
import retrofit.RestAdapter;
import retrofit.converter.GsonConverter;

public class SecureResourceClient {

  private static final GsonConverter gsonConverter = new GsonConverter(new GsonBuilder().disableHtmlEscaping().create());

  // preparing the client using Retrofit 1.9
  public static <T> T prepareSecuredAnonymousRetrofitClient(final Class<T> clazz, final Context context) {
    final OkHttpClient okHttpClient = OneginiSDK.getOneginiClient(context).getDeviceClient().getAnonymousResourceOkHttpClient();
    return prepareSecuredRetrofitClient(clazz, context, okHttpClient);
  }

  // preparing the client using Retrofit 2.X
  public static <T> T prepareSecuredAnonymousRetrofit2Client(final Class<T> clazz, final Context context) {
    final OkHttpClient okHttpClient = OneginiSDK.getOneginiClient(context).getDeviceClient().getAnonymousResourceOkHttpClient();
    return prepareSecuredRetrofit2Client(clazz, context, okHttpClient);
  }

  // preparing the client using Retrofit 2.X
  private static <T> T prepareSecuredRetrofit2Client(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
    final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
    final Retrofit retrofit = new Retrofit.Builder()
        .client(okHttpClient)
        .baseUrl(oneginiClient.getConfigModel().getResourceBaseUrl() + "/") // In Retrofit 2.X the base URL should end with '/'
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

    return retrofit.create(clazz);
  }

  // preparing the client using Retrofit 1.9
  private static <T> T prepareSecuredRetrofitClient(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
    final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
    final RestAdapter restAdapter = new RestAdapter.Builder()
        .setClient(new Ok3Client(okHttpClient))
        .setEndpoint(oneginiClient.getConfigModel().getResourceBaseUrl())
        .setConverter(gsonConverter)
        .build();
    return restAdapter.create(clazz);
  }
}

As you can see in the snippets above, the Resource Gateway url (endpoint) is set explicitly on Retrofit.Builder or RestAdapter.Builder. Depending on your needs you may set additional options, for example add a Gson converter or a RxJavaCallAdapterFactory like in the example above. Please notice that the client passed to the builder has to come from DeviceClient#getAnonymousResourceRetrofitClient() as we want to make anonymous resource call.

Performing the anonymous resource call

When we have the Retrofit client defined and instantiated we can proceed and perform the resource call itself. The SDK will not process the response, which means that you need to handle it on our own. This also means that you need to make sure that the device has a valid access token by performing device authentication before making the actual anonymous resource call.

  private void authenticateDevice() {
    OneginiSDK.getOneginiClient(this).getDeviceClient()
        .authenticateDevice(new String[]{ "application-details" }, new OneginiDeviceAuthenticationHandler() {
              @Override
              public void onSuccess() {
                callAnonymousResourceCallToFetchApplicationDetails();
              }

              @Override
              public void onError(final OneginiDeviceAuthenticationError error) {
                final @OneginiDeviceAuthenticationError.DeviceAuthenticationErrorType int errorType = error.getErrorType();
                if (errorType == OneginiDeviceAuthenticationError.DEVICE_DEREGISTERED) {
                  onDeviceDeregistered();
                } else if (errorType == OneginiDeviceAuthenticationError.USER_DEREGISTERED) {
                  onUserDeregistered(authenticatedUserProfile);
                } else {
                  displayError(error);
                }
              }
        );
  }

  private void callAnonymousResourceCallToFetchApplicationDetails() {
    subscription = AnonymousService.getInstance(this)
      .getApplicationDetails()
      .subscribe(this::onApplicationDetailsFetched, throwable -> onApplicationDetailsFetchFailed());
  }

  private void onApplicationDetailsFetched(final ApplicationDetails applicationDetails) {
    applicationDetailsTextView.setText(applicationDetails.getApplicationDetailsCombined());
  }

  private void onApplicationDetailsFetchFailed() {
    applicationDetailsTextView.setText("Application details fetch failed");
  }

  @Override
  public void onDestroy() {
    if (subscription != null) {
      subscription.unsubscribe();
    }
    super.onDestroy();
  }

Fetching a resource on behalf of a user

In order to request a resource for a specific user, the client needs to be registered and also the user's access token needs to be present within the application memory. So it is required to have the authentication flow UserClient#authenticateUser finished successfully before a resource call on behalf of user can be made. A resource request can be typically used in cases where usage of certain functionality or accessing resources requires user authentication.

Defining REST interface

The first step we need to take in order to fetch a resource is to define a REST interface. Please note that the path devices is relative to the endpoint which we need to configure on the HTTP client before making a call. Also the endpoint URL definition looks slightly different when comparing Retrofit 1.X and 2.X. Please follow one of many Retrofit tutorials for details.

Client definition for Retrofit 1.9

import com.onegini.mobile.exampleapp.network.response.DevicesResponse;
import retrofit.http.GET;
import rx.Observable;

public interface UserClient {

  @GET("/devices")
  Observable<DevicesResponse> getDevices();
}

Client definition for Retrofit 2.X

import com.onegini.mobile.exampleapp.network.response.DevicesResponse;
import retrofit2.http.GET;
import rx.Observable;

public interface UserClient2 {

  @GET("devices")
  Observable<DevicesResponse> getDevices();
}

Defining the REST Adapter

Next, we need to setup the retrofit instance by providing the resource client (UserClient#getResourceRetrofitClient() or deprecated UserClient#getResourceRetrofitClient()), Resource Gateway url and also REST interface which we have defined in previous step.

Example code

package com.onegini.mobile.exampleapp.network;

import android.content.Context;
import com.onegini.mobile.exampleapp.network.client.UserClient;
import com.onegini.mobile.exampleapp.network.client.SecureResourceClient;
import com.onegini.mobile.exampleapp.network.response.DevicesResponse;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;

public class UserService {

  private static UserService instance;

  public static UserService getInstance(final Context context) {
    if (instance == null) {
      instance = new UserService(context);
    }
    return instance;
  }

  // the client using Retrofit 1.9
  private final UserClient userRetrofitClient;
  // the client using Retrofit 2.X
  private final UserClient2 userRetrofit2Client;

  private UserService(final Context context) {
    userRetrofitClient = SecureResourceClient.prepareSecuredUserRetrofitClient(UserClient.class, context);
    userRetrofit2Client = SecureResourceClient.prepareSecuredUserRetrofit2Client(UserClient2.class, context);
  }

  public Observable<DevicesResponse> getDevices(final boolean useRetrofit2) {
    return getObservable(useRetrofit2)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .unsubscribeOn(Schedulers.io());
  }

  private Observable<DevicesResponse> getObservable(final boolean useRetrofit2) {
    if (useRetrofit2) {
      return userRetrofit2Client.getDevices();
    } else {
      return userRetrofitClient.getDevices();
    }
  }
}
package com.onegini.mobile.exampleapp.network.client;

import android.content.Context;
import com.google.gson.GsonBuilder;
import com.onegini.mobile.sdk.android.client.OneginiClient;
import com.onegini.mobile.exampleapp.OneginiSDK;
import retrofit.RestAdapter;
import retrofit.converter.GsonConverter;

public class SecureResourceClient {

  private static final GsonConverter gsonConverter = new GsonConverter(new GsonBuilder().disableHtmlEscaping().create());

  // preparing the client using Retrofit 1.9
  public static <T> T prepareSecuredUserRetrofitClient(final Class<T> clazz, final Context context) {
    final OkHttpClient okHttpClient = OneginiSDK.getOneginiClient(context).getUserClient().getResourceOkHttpClient();
    return prepareSecuredRetrofitClient(clazz, context, okHttpClient);
  }

  // preparing the client using Retrofit 2.X
  public static <T> T prepareSecuredUserRetrofit2Client(final Class<T> clazz, final Context context) {
    final OkHttpClient okHttpClient = OneginiSDK.getOneginiClient(context).getUserClient().getResourceOkHttpClient();
    return prepareSecuredRetrofit2Client(clazz, context, okHttpClient);
  }

  // preparing the client using Retrofit 2.X
  private static <T> T prepareSecuredRetrofit2Client(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
    final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
    final Retrofit retrofit = new Retrofit.Builder()
      .client(okHttpClient)
      .baseUrl(oneginiClient.getConfigModel().getResourceBaseUrl() + "/") // In Retrofit 2.X the base URL should end with '/'
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
      .build();

    return retrofit.create(clazz);
  }

  // preparing the client using Retrofit 1.9
  private static <T> T prepareSecuredRetrofitClient(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
    final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
    final RestAdapter restAdapter = new RestAdapter.Builder()
      .setClient(new Ok3Client(okHttpClient))
      .setEndpoint(oneginiClient.getConfigModel().getResourceBaseUrl())
      .setConverter(gsonConverter)
      .build();
    return restAdapter.create(clazz);
  }
}

As you can see in the snippets above, the Resource Gateway url (endpoint) is set explicitly on Retrofit.Builder or RestAdapter.Builder. Depending on your needs you may set additional options, for example add a Gson converter or a RxJavaCallAdapterFactory like in the example above. Please notice that the client passed to the builder has to come from UserClient#getResourceOkHttpClient() as we want to make anonymous resource call.

Performing the resource call

When we have the Retrofit defined and instantiated we can proceed and perform the resource call itself. The SDK will not process the response, which means that you need to handle it on your own. This also means that you need to make sure that the user has a valid access token by triggering user authentication. You don't have to bother about payload encryption because the SDK will take care of that for you. Let's try to send the request and log the answer.

  private void fetchUserDevices() {
    subscription = UserService.getInstance(this)
        .getDevices()
        .subscribe(this::onDevicesFetched, throwable -> onDevicesFetchFailed(), this::onFetchComplete);
  }

  private void onDevicesFetched(final DevicesResponse devicesResponse) {
    displayFetchedDevices(devicesResponse.getDevices());
  }

  private void onDevicesFetchFailed() {
    showToast("onDevicesFetchFailed");
  }

  private void onFetchComplete() {
    progressBar.setVisibility(View.INVISIBLE);
  }

  private void displayFetchedDevices(final List<Device> devices) {
    final DevicesAdapter adapter = new DevicesAdapter(devices);
    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
  }

  private void showToast(final String message) {
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
  }

  @Override
  public void onDestroy() {
    if (subscription != null) {
      subscription.unsubscribe();
    }
    super.onDestroy();
  }

The operation will succeed only in case the user's access token is available. Otherwise, the Resource Gateway will respond with 401 unauthorized, meaning that the provided access token was not valid.

Fetching a resource on behalf of implicitly authenticated user

In order to request a resource for a specific implicitly authenticated user, the client needs to be registered and also the user's implicit access token needs to be present within application memory. So it is required to have the implicit authentication flow UserClient#authenticateUserImplicitly finished successfully before a resource call on behalf of an implicitly authenticated user can be made. A resource request can be typically used in cases where usage of certain functionality or accessing resources does not require user to explicitly authenticate himself. The implicit authentication can be used for accessing less sensitive resources.

Defining REST interface

The first step we need to take in order to fetch a resource is to define a REST interface. Please note that the path user-id-decorated is relative to the endpoint which we need to configure on the HTTP client before making a call. Also the endpoint URL definition looks slightly different when comparing Retrofit 1.X and 2.X. Please follow one of many Retrofit tutorials for details.

Client definition for Retrofit 1.9

import com.onegini.mobile.exampleapp.model.ImplicitUserDetails;
import retrofit.http.GET;
import rx.Observable;

public interface ImplicitUserClient {

  @GET("/user-id-decorated")
  Observable<ImplicitUserDetails> getImplicitUserDetails();
}

Client definition for Retrofit 2.X

import com.onegini.mobile.exampleapp.model.ImplicitUserDetails;
import retrofit2.http.GET;
import rx.Observable;

public interface ImplicitUserClient2 {

  @GET("user-id-decorated")
  Observable<ImplicitUserDetails> getImplicitUserDetails();
}

Defining the REST Adapter

Next, we need to setup the retrofit instance by providing the resource client (UserClient#getImplicitResourceOkHttpClient(), Resource Gateway url and also REST interface which we have defined in previous step.

Example code

import com.google.gson.annotations.SerializedName;

public class ImplicitUserDetails {

  @SerializedName("decorated_user_id")
  private String decoratedUserId;

  @Override
  public String toString() {
    return decoratedUserId;
  }
}
import android.content.Context;
import com.onegini.mobile.exampleapp.model.ImplicitUserDetails;
import com.onegini.mobile.exampleapp.network.client.ImplicitUserClient;
import com.onegini.mobile.exampleapp.network.client.ImplicitUserClient2;
import com.onegini.mobile.exampleapp.network.client.SecureResourceClient;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class ImplicitUserService {

  private static ImplicitUserService INSTANCE;

  public static ImplicitUserService getInstance(final Context context) {
    if (INSTANCE == null) {
      INSTANCE = new ImplicitUserService(context);
    }
    return INSTANCE;
  }

  // the client using Retrofit 1.9
  private final ImplicitUserClient applicationDetailsRetrofitClient;
  // the client using Retrofit 2.X
  private final ImplicitUserClient2 applicationDetailsRetrofit2Client;

  private ImplicitUserService(final Context context) {
    applicationDetailsRetrofitClient = SecureResourceClient.prepareSecuredImplicitUserRetrofitClient(ImplicitUserClient.class, context);
    applicationDetailsRetrofit2Client = SecureResourceClient.prepareSecuredImplicitUserRetrofit2Client(ImplicitUserClient2.class, context);
  }

  public Observable<ImplicitUserDetails> getImplicitUserDetails(final boolean useRetrofit2) {
    return getObservable(useRetrofit2)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
  }

  private Observable<ImplicitUserDetails> getObservable(final boolean useRetrofit2) {
    if (useRetrofit2) {
      return applicationDetailsRetrofit2Client.getImplicitUserDetails();
    } else {
      return applicationDetailsRetrofitClient.getImplicitUserDetails();
    }
  }
}
package com.onegini.mobile.exampleapp.network.client;

import android.content.Context;
import com.google.gson.GsonBuilder;
import com.onegini.mobile.sdk.android.client.OneginiClient;
import com.onegini.mobile.exampleapp.OneginiSDK;
import retrofit.RestAdapter;
import retrofit.converter.GsonConverter;

public class SecureResourceClient {

  private static final GsonConverter gsonConverter = new GsonConverter(new GsonBuilder().disableHtmlEscaping().create());

  // preparing the client using Retrofit 1.9
  public static <T> T prepareSecuredImplicitUserRetrofitClient(final Class<T> clazz, final Context context) {
    final OkHttpClient okHttpClient = OneginiSDK.getOneginiClient(context).getUserClient().getImplicitResourceOkHttpClient();
    return prepareSecuredRetrofitClient(clazz, context, okHttpClient);
  }

  // preparing the client using Retrofit 2.X
  public static <T> T prepareSecuredImplicitUserRetrofit2Client(final Class<T> clazz, final Context context) {
    final OkHttpClient okHttpClient = OneginiSDK.getOneginiClient(context).getUserClient().getImplicitResourceOkHttpClient();
    return prepareSecuredRetrofit2Client(clazz, context, okHttpClient);
  }

  // preparing the client using Retrofit 2.X
  private static <T> T prepareSecuredRetrofit2Client(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
    final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
    final Retrofit retrofit = new Retrofit.Builder()
        .client(okHttpClient)
        .baseUrl(oneginiClient.getConfigModel().getResourceBaseUrl() + "/") // In Retrofit 2.X the base URL should end with '/'
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .build();

    return retrofit.create(clazz);
  }

  // preparing the client using Retrofit 1.9
  private static <T> T prepareSecuredRetrofitClient(final Class<T> clazz, final Context context, final OkHttpClient okHttpClient) {
    final OneginiClient oneginiClient = OneginiSDK.getOneginiClient(context);
    final RestAdapter restAdapter = new RestAdapter.Builder()
        .setClient(new Ok3Client(okHttpClient))
        .setEndpoint(oneginiClient.getConfigModel().getResourceBaseUrl())
        .setConverter(gsonConverter)
        .build();
    return restAdapter.create(clazz);
  }

As you can see in the snippets above, the Resource Gateway url (endpoint) is set explicitly on Retrofit.Builder or RestAdapter.Builder. Depending on your needs you may set additional options, for example add a Gson converter or a RxJavaCallAdapterFactory like in the example above. Please notice that the client passed to the builder has to come from UserClient#getImplicitResourceOkHttpClient() as we want to make resource call for implicitly authenticated user.

Performing the resource call for implicitly authenticated user

When we have the Retrofit defined and instantiated we can proceed and perform the resource call itself. The SDK will not process the response, which means that you need to handle it on your own. This also means that you need to make sure that the user has a valid access token by triggering implicit user authentication. You don't have to bother about payload encryption because the SDK will take care of that for you. Let's try to send the request and log the answer.

private void callImplicitResourceCallToFetchImplicitUserDetails() {
    final boolean useRetrofit2 = deviceSettingsStorage.shouldUseRetrofit2();
    subscription = ImplicitUserService.getInstance(this)
        .getImplicitUserDetails(useRetrofit2)
        .subscribe(this::onImplicitUserDetailsFetched, this::onImplicitDetailsFetchFailed);
  }

  private void onImplicitUserDetailsFetched(final ImplicitUserDetails implicitUserDetails) {
    implicitUserDetailsTextView.setText(implicitUserDetails.toString());
  }

  private void onImplicitDetailsFetchFailed(final Throwable throwable) {
    implicitUserDetailsTextView.setText(R.string.implicit_user_details_fetch_failed_label);
    throwable.printStackTrace();
  }

The operation will succeed only in case the user's implicit access token is available. Otherwise, the Resource Gateway will respond with 401 unauthorized, meaning that the provided access token was not valid.

Performing modified REST requests

In some cases you may want to add custom headers to all requests made by your RestAdapter. To do so, please create a requestInterceptor instance and set it in the RestAdapter.Builder when you are constructing your RestAdapter.

RequestInterceptor requestInterceptor = new RequestInterceptor() {  
    @Override
    public void intercept(RequestFacade request) {
        request.addHeader("X-custom-header", "header value");
        request.addHeader("Content-type", "application/json");
    }
};

RestAdapter restAdapter = new RestAdapter.Builder()
    .setRequestInterceptor(requestInterceptor)
    .build();

For more information on adding headers or parameters to requests see the following Retrofit tutorial.

Also please note that for Retrofit 2.X you should add OkHttp Interceptor instead.