Authorization and Security

Setup

Maven

<dependency>
    <groupId>de.whitefrog</groupId>
    <artifactId>frogr-auth</artifactId>
    <version>0.1.0</version>
</dependency>

User Model

The User model has to extend BaseUser and defines our user, which can be passed in Service methods using the @Auth annotation.

class User : BaseUser()

User Repository

Next, we’ll have to define a repository for our users, extending BaseUserRepository:

public class UserRepository extends BaseUserRepository<User> {
  public String init() {
    String token;
    PersonRepository persons = service().repository(Person.class);
    if(search().count() == 0) {
      Person rick = new Person("Rick Sanchez");
      Person beth = new Person("Beth Smith");
      Person jerry = new Person("Jerry Smith");
      Person morty = new Person("Morty Smith");
      Person summer = new Person("Summer Smith");
      // we need to save the people first, before we can create relationships
      persons.save(rick, beth, jerry, morty, summer);

      rick.setChildren(Arrays.asList(beth));
      beth.setChildren(Arrays.asList(morty, summer));
      beth.setMarriedWith(jerry);
      jerry.setChildren(Arrays.asList(morty, summer));
      jerry.setMarriedWith(beth);
      persons.save(rick, beth, jerry, morty, summer);

      User user = new User();
      user.setLogin("justin_roiland");
      user.setPassword("rickandmorty");
      user.setRole(Role.Admin);
      save(user);
      
      // login to create and print an access token - for test purposes only
      user = login("justin_roiland", "rickandmorty");
      token = "Access Token: " + user.getAccessToken();
      System.out.println("User created. Authorization: Bearer " + user.getAccessToken());
    } else {
      User user = login("justin_roiland", "rickandmorty");
      token = "Access Token: " + user.getAccessToken();
      System.out.println("Authorization: Bearer " + user.getAccessToken());
    }
    return token;
  }
}

Application

In our applications run method, we need to set up some authentication configurations:

public class MyApplication extends Application<Configuration> {
  public MyApplication() {
    // register the rest classes
    register("de.whitefrog.frogr.auth.example");
    // register repositories and models
    serviceInjector().service().register("de.whitefrog.frogr.auth.example");
    
  }

  @Override
  @SuppressWarnings("unchecked")
  public void run(Configuration configuration, Environment environment) throws Exception {
    super.run(configuration, environment);

    Authorizer authorizer = new Authorizer(service().repository(User.class));
    AuthFilter oauthFilter = new OAuthCredentialAuthFilter.Builder<User>()
      .setAuthenticator(new Authenticator(service().repository(User.class)))
      .setAuthorizer(authorizer)
      .setPrefix("Bearer")
      .buildAuthFilter();

    environment.jersey().register(RolesAllowedDynamicFeature.class);
    environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
    environment.jersey().register(new AuthDynamicFeature(oauthFilter));
  }

  @Override
  public String getName() {
    return "frogr-auth-example-rest";
  }

  public static void main(String[] args) throws Exception {
    new MyApplication().run("server", "config/example.yml");
  }
}

Services

Here’s a simple service, that can only be called when the user is authenticated. The user will be passed as argument to the method:

@Path("person")
public class Persons extends AuthCRUDService<PersonRepository, Person, User> {
  @GET
  @Path("find-morty")
  @RolesAllowed(Role.User)
  public Person findMorty(@Auth User user) {
    try(Transaction tx = service().beginTx()) {
      return repository().findMorty();
    }
  }
}