Quickstart for Java
This guide will walk you through your first change to an Oso policy file. There are three steps:
- Download a minimal Java starter project that’s already integrated with Oso.
- Run the server and visit the app in your browser.
- Make a small change to the policy to allow a new type of access.
The Oso Library works best in monolithic applications. If you’re building authorization for more than one service or want to share a policy across multiple applications, read how to get started with Oso Cloud.
1. Clone the repo and install dependencies
First, clone the Java quickstart repo, and install the dependencies:
git clone https://github.com/osohq/oso-java-quickstart.git
cd oso-java-quickstart
mvn install # requires maven to be installed!
2. Run the server
With the dependencies installed, you should be ready to start the server:
mvn clean package exec:java -Dexec.mainClass="quickstart.Server"
If all is well, the server should be listening on port 5000.
Visit
http://localhost:5000/repo/gmail
in your browser. You should see a successful response, indicating that you have
access to the gmail
repo.
To see an unsuccessful response, visit
http://localhost:5000/repo/react. You’ll see an error: Repo named react was not found
. There actually is a repo named react
, but you don’t have access
to it. Let’s fix that now.
3. Update the policy
In main.polar
, add the following two lines to define a new “rule.” This
rule will allow any “actor” (or user) to perform the "read"
action on a
repository if that repository is marked as isPublic
.
actor User {}
resource Repository {
permissions = ["read", "push", "delete"];
roles = ["contributor", "maintainer", "admin"];
"read" if "contributor";
"push" if "maintainer";
"delete" if "admin";
"maintainer" if "admin";
"contributor" if "maintainer";
}
# This rule tells Oso how to fetch roles for a repository
has_role(actor: User, role_name: String, repository: Repository) if
role in actor.roles and
role_name = role.name and
repository = role.repository;
has_permission(_actor: User, "read", repository: Repository) if
repository.isPublic;
allow(actor, action, resource) if
has_permission(actor, action, resource);
Restart the server, and again visit http://localhost:5000/repo/react. Now, you’ll see a successful response:
What just happened?
The quickstart server uses an Oso policy to make sure users are allowed to
view repos. The call to oso.authorize()
in Server.java
performs this check in the /repo/{name}
route.
If the user does not have access to a repository, an error response is returned
to them.
In this case, the repo with the name react
is public because of its definition
in the Models.java
file, so it should be accessible
to everyone. By making the change to main.polar
, you
told Oso to allow users to "read"
repositories that have the isPublic
field set to true.
That way, when you visited the react
repo in your browser, Oso determined that
the action was permitted!
Check out the full code for the example below:
package quickstart;
import java.io.IOException;
import io.javalin.Javalin;
import com.osohq.oso.Oso;
import com.osohq.oso.Exceptions.NotFoundException;
import quickstart.Models.Repository;
import quickstart.Models.User;
public class Server {
public static void main(String[] args) throws IOException {
Javalin app = Javalin.create();
Oso oso = new Oso();
oso.registerClass(User.class, "User");
oso.registerClass(Repository.class, "Repository");
oso.loadFile("src/main/java/quickstart/main.polar");
app.get("/repo/{name}", ctx -> {
ctx.contentType("text/html");
String name = ctx.pathParam("name");
Repository repo = Repository.byName(name);
User user = User.getCurrentUser();
try {
oso.authorize(user, "read", repo);
ctx.result(String.format("<h1>A Repo</h1><p>Welcome to repo %s</p>", repo.name));
} catch (NotFoundException e) {
ctx.status(404);
ctx.result(String.format("<h1>Whoops!</h1><p>Repo named %s was not found</p>", name));
}
});
app.start(5000);
}
}
package quickstart;
import java.util.HashMap;
import java.util.Map;
public class Models {
public static class Repository {
public String name;
public boolean isPublic;
public Repository(String name, boolean isPublic) {
this.name = name;
this.isPublic = isPublic;
}
public static Repository byName(String name) {
return Models.reposDb.get(name);
}
}
public static class Role {
public String name;
public Repository repository;
public Role(String name, Repository repository) {
this.name = name;
this.repository = repository;
}
}
public static class User {
public Role[] roles;
public User(Role[] roles) {
this.roles = roles;
}
public static User getCurrentUser() {
return Models.usersDb.get("larry");
}
}
static Map<String, Repository> reposDb = Map.of(
"gmail", new Repository("gmail", false),
"react", new Repository("react", true), // react is public
"oso", new Repository("oso", false)
);
static Map<String, User> usersDb = Map.of(
"larry", new User(new Role[] {new Role("admin", reposDb.get("gmail"))}),
"anne", new User(new Role[] {new Role("maintainer", reposDb.get("react"))}),
"graham", new User(new Role[] {new Role("contributor", reposDb.get("oso"))})
);
}
Connect with us on Slack
If you have any questions, or just want to talk something through, jump into Slack. An Oso engineer or one of the thousands of developers in the growing community will be happy to help.