ForgeRock SDKs

Intercept and modify REST calls

The ForgeRock SDKs support modification of REST calls before they are sent.

For example, you can customize:

  • Request parameters

  • Headers

  • Request URLs

  • Request methods

  • The request body and post data

Request interceptors

The SDKs provide "request interceptor" interfaces you can use to customize requests.

Android RequestInterceptor interface

public interface FRRequestInterceptor<Action> {
    @NonNull Request intercept(Request request, Action action);
}

public class Action {
    private String type;
    private JSONObject payload;
}

iOS RequestInterceptor protocol

public protocol RequestInterceptor {
    func intercept(request: Request, action: Action) -> Request
}

public struct Action {
    public let type: String
    public let payload: [String: Any]?
}

JavaScript Middleware interface

type RequestMiddleware = (req: RequestObj, action: Action, next: () => RequestObj) => void;

interface RequestObj {
  url: URL;
  init: RequestInit;
}

interface Action {
  type: string;
  payload?: any; // optional data
}

Interceptor inputs

Request interceptors have two inputs:

  • The Request object

  • The Action object

The Request object

Represents the original request, and contains information about the body, method type, parameters and more.

ForgeRock Android SDK

public class Request {
    public URL url();
    public Iterator<Pair<String, String>> headers();
    public String header(String name);
    public List<String> headers(String name);
    public String method();
    public Object tag();
    public Body body();
    public Builder newBuilder();
}

// Use Build to build upon on existing Request
public class Builder {
   public Builder url(URL url);
   public Builder url(String url);
   public Builder header(String name, String value);
   public Builder addHeader(String name, String value)
   public Builder removeHeader(String name)
   public Builder get()
   public Builder put(Body body)
   public Builder post(Body body)
   public Builder delete(Body body)
   public Builder delete()
   public Builder patch(Body body)
   public Request build()

}

ForgeRock iOS SDK

public struct Request {
    // Properties
    public let url: String
    public let method: HTTPMethod
    private(set) public var headers: [String: String]
    public let bodyParams: [String: Any]
    public let urlParams: [String: String]
    public let responseType: ContentType
    public let requestType: ContentType
    public let timeoutInterval: Double

    public enum ContentType: String {
        case plainText = "text/plain"
        case json = "application/json"
        case urlEncoded = "application/x-www-form-urlencoded"
    }

    public enum HTTPMethod: String {
        case GET = "GET"
        case PUT = "PUT"
        case POST = "POST"
        case DELETE = "DELETE"
    }

    public func build() -> URLRequest?
}

ForgeRock JavaScript SDK

See Request in the MDN Web Docs.

The Action object

Represents the type of operation the request performs:

Action Description

START_AUTHENTICATE

Initial call to an authentication tree

AUTHENTICATE

Proceed through an authentication tree flow

AUTHORIZE

Obtain authorization token from AM

EXCHANGE_TOKEN

Exchange authorization code for an access token

REFRESH_TOKEN

Refresh an access token

REVOKE_TOKEN

Revoke a refresh or access token

LOGOUT

Log out a session

USER_INFO

Obtain information from the userinfo endpoint

PUSH_REGISTER

Register a push device with AM; for example, a call to /json/push/sns/message?_action=register

PUSH_AUTHENTICATE

Authenticate using push; for example, a call to /json/push/sns/message?_action=authenticate

The AUTHENTICATE and START_AUTHENTICATE actions have a payload that contains:

tree

The name of the authentication tree being called.

type

Whether the call is to a service, or is in response to composite_advice.

The outcome of applying a request interceptor is the entire modified request object, ready to either be sent to AM, or to have additional request interceptors applied.

Intercept and modify REST calls

This section covers how to develop request interceptors, referred to as "middleware" in the ForgeRock JavaScript SDK, and apply them to outbound requests from your applications.

ForgeRock Android SDK

The following code demonstrates an implementation of the FRRequestInterceptor interface, which sets the ForceAuth query parameter to true on all outgoing requests of the START_AUTHENTICATE type:

public class ForceAuthRequestInterceptor implements FRRequestInterceptor<Action> {

    @NonNull
    @Override
    public Request intercept(@NonNull Request request, Action tag) {
        if (tag.getType().equals(START_AUTHENTICATE)) {
            return request.newBuilder()
                    .url(Uri.parse(request.url().toString())
                            .buildUpon()
                            .appendQueryParameter("ForceAuth", "true").toString())
                    .build();
        }
        return request;
    }
}

In this example, we use the RequestInterceptorRegistry.getInstance().register() method to register the request interceptor:

RequestInterceptorRegistry.getInstance().register(new ForceAuthRequestInterceptor())

Any calls the application makes to initiate authentication will now have the query parameter ForceAuth=true appended.

You can register multiple request interceptors as follows:

RequestInterceptorRegistry.getInstance().register(
                new ForceAuthRequestInterceptor(),
                new NoSessionRequestInterceptor(),
                new InjectHeaderAuthRequestInterceptor());

ForgeRock iOS SDK

The following code demonstrates an implementation of the RequestInterceptor interface, which sets the ForceAuth query parameter to true on all outgoing requests of the AUTHENTICATE or START_AUTHENTICATE type, but only for a specific authentication tree (<NAME_OF_AUTH_TREE>):

class ForceAuthInterceptor: RequestInterceptor {
    func intercept(request: Request, action: Action) -> Request {
        if (action.type == "START_AUTHENTICATE" || action.type == "AUTHENTICATE"),
            let payload = action.payload,
            let treeName = payload["tree"] as? String,
            treeName == "<NAME_OF_AUTH_TREE>"
        {
            var urlParams = request.urlParams
            urlParams["ForceAuth"] = "true"
            let newRequest = Request(url: request.url, method: request.method, headers: request.headers, bodyParams: request.bodyParams, urlParams: urlParams, requestType: request.requestType, responseType: request.responseType, timeoutInterval: request.timeoutInterval)
            return newRequest
        }
        else {
            return request
        }
    }
}

This example uses the registerInterceptors() method to register the request interceptor:

FRRequestInterceptorRegistry.shared.registerInterceptors(interceptors: [ForceAuthInterceptor()])

Any calls the application makes to initiate authentication will now have the query parameter ForceAuth=true appended.

You can register multiple request interceptors as follows:

FRRequestInterceptorRegistry.shared.registerInterceptor(interceptors: [OAuthTokenInterceptor(), LogoutInterceptor(), AuthTreeInterceptor()])

ForgeRock JavaScript SDK

The following code demonstrates an implementation of the Middleware interface, which sets the ForceAuth query parameter to true on all outgoing requests of the START_AUTHENTICATE type:

const forceAuthMiddleware = (req: Req, action: Action, next: () => RequestObj): void => {
  switch (action.type) {
    case 'START_AUTHENTICATE':
      req.url.searchParams.set('ForceAuth', 'true');
      break;
  }
  next();
}

In this example, we register the request interceptor above in the middleware property, when setting configuration:

Config.set({
  clientId: 'WebOAuthClient',
  middleware: [forceAuthMiddleware],
  redirectUri: 'https://sdkapp.example.com:8443/callback',
  realmPath: 'root',
  scope: 'openid profile me.read',
  serverConfig: { baseUrl: 'https://openam.example.com:8443/openam/', timeout: 30000 },
  tree: 'UsernamePassword',
});

Any calls the application makes to initiate authentication will now have the query parameter ForceAuth=true appended.

Copyright © 2010-2022 ForgeRock, all rights reserved.