Auth Policy

In the Planes guide, we created a security policy to only allow requests with a given token URL parameter. This guide will expand upon this to show how access can be restriced for given Agents and Lanes.

Declaration and Instantiation

The recommended steps for implementing and adding a security policy to a Swim application:

(Note that the policy does not have to be set in the constructor of the Plane. We could set the policy against the PlaneContext in main which would allow us to downlink lanes within the authorization logic.)

Here we give the most basic example of how to declare and add a policy to an application:

// swim/basic/BasicPlane.java
package swim.basic;

import swim.api.auth.Identity;
import swim.api.plane.AbstractPlane;
import swim.api.policy.AbstractPolicy;
import swim.api.policy.PolicyDirective;
import swim.kernel.Kernel;
import swim.server.ServerLoader;
import swim.warp.Envelope;

public class BasicPlane extends AbstractPlane {

  // Inject policy. Swim internally calls the no-argument constructor, which retains
  // its implicit call to super() in Java
  public BasicPlane() {
    context.setPolicy(new BasicPolicy());
  }

  public static void main(String[] args) {
    final Kernel kernel = ServerLoader.loadServer();
    kernel.start();
    kernel.run();
  }


  // Define policy; doesn't have to be an inner class
  class BasicPolicy extends AbstractPolicy {
    @Override
    protected <T> PolicyDirective<T> authorize(Envelope envelope, Identity identity) {
      //Custom security logic here
    }
  }
}

Access Control for Lanes and Agents

The Envelope object contains the nodeUri and laneUri of each request and so from here it is simple to add access control to given Agents or Lanes. Here we extend our previous example to only allow requests with an ‘admin token’ to make requests to /control agents and adminInfo lanes.

// swim/basic/BasicPolicy.java
package swim.basic;

import swim.api.auth.Identity;
import swim.api.policy.AbstractPolicy;
import swim.api.policy.PolicyDirective;
import swim.warp.Envelope;

public class BasicPolicy extends AbstractPolicy {

  private static final String ADMIN_TOKEN = "abc123";
  private static final String USER_TOKEN = "abc";

  @Override
  protected <T> PolicyDirective<T> authorize(Envelope envelope, Identity identity) {
    if (identity != null) {
      final String token = identity.requestUri().query().get("token");

      //Always authorize admins
      if (ADMIN_TOKEN.equals(token)) {
        return allow();
      }

      //Admin tokens must be used for 'adminInfo' lanes or '/control' agents
      if ("adminInfo".equals(envelope.laneUri().toString()) ||
        envelope.nodeUri().toString().startsWith("/control")) {
        return forbid();
      }

      //Users can access any remaining lanes
      if (USER_TOKEN.equals(token)) {
        return allow();
      }
    }
    return forbid();
  }
}

Try It Yourself

A standalone project that combines all of these snippets and handles any remaining boilerplate is available here.