Quickstart
Welcome to Oso! Let's get you started on the journey to supercharge authorization in your application.
Before we get started
You'll need a couple of things for this tutorial:
- An Oso Cloud account. You can get one at https://ui.osohq.com (opens in a new tab).
- A sample application that you can modify and launch locally. We have clients
for
Node
,Python
,Go
,Ruby
, and.NET
.
Building your first policy
The first thing you need on this journey is a policy. A policy contains the
authorization logic that Oso Cloud will use to determine access. A minimal
policy comprises an Actor
, the subject of an authorization query, and a
Resource
, the object of an authorization query, with at least one
permission.
For example, you may want to control "read" access for users to organizations in your multi-tenant application.
actor User {}
resource Organization {
permissions = ["read"];
}
Once you have constructed a policy, upload it using the Policy (opens in a new tab) page. That's it! In practice, your policy will have some more bells and whistles; we'll add those in due time, but this is enough to get things rolling.
Optional reading:
Adding Oso Cloud to your application
You're ready to add Oso Cloud to your application, so load up the application code in your favorite IDE.
- Generate a new read-write token from the Settings (opens in a new tab) page and initialize your environment.
- Follow the steps on the Install (opens in a new tab) page to
integrate Oso Cloud into your application. The sample code uses hardcoded
values for the
Actor
andResource
IDs. In practice, you'll retrieve these from contexts available to your application; the hardcoded values are good enough for now, and we'll use them in our examples.
Launch your application and attempt to access the endpoint now protected by Oso
Cloud. You'll get an exception. That's because you still need to grant the
permission to the Actor
!
Granting permissions
You grant permissions by adding facts. Facts are the authorization-relevant data that Oso Cloud will use to determine access.
Following our example, if we want to allow User:123
to "read"
Organization:456
, we need to add the following fact:
has_permission User:123 "read" Organization:456
You can do this using the Facts (opens in a new tab) page.
Now, try reaccessing the endpoint. No exceptions!
Congratulations, you've successfully added enforcement to your application.
Optional reading:
From example, to practice
Updating the authorization logic
Most use cases do not have individual permissions assigned to each Actor
on
each Resource
; that would be too many to manage! Instead, it's common to assign
a "role" that has the desired permission(s); this is referred to as Role-Based
Access Control (RBAC). Follow the Roles
example to update your policy to support roles. Note: you do not need to
update your application code after you've made the changes!
Example Solution
actor User {}
resource Organization {
roles = ["member"];
permissions = ["read"];
"read" if "member";
}
has_role User:123 "member" Organization:456
Using real Actors
and Resources
Until now, we have used hardcoded values for the Actor
and Resource
IDs. Update
your application to read the IDs from the appropriate contexts. Additionally,
add a few more facts to grant the permission to the real Actors
on the actual
Resources
.
Example Solution
const express = require("express");
require("dotenv").config();
const { Oso } = require("oso-cloud");
const apiKey = process.env.OSO_AUTH;
const oso = new Oso("https://cloud.osohq.com", apiKey);
async function start() {
const app = express();
app.get("/:org_id", async (req, res) => {
const authorization = req.headers.authorization;
if (!authorization) {
res.set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`);
res.status(401).send("Not Authorized");
return;
}
const [username, _] = new Buffer.from(authorization.split(" ")[1], "base64")
.toString()
.split(":");
const orgId = req.params.org_id;
const actor = { type: "User", id: username };
const resource = { type: "Organization", id: orgId };
if ((await oso.authorize(actor, "read", resource)) === false) {
// Handle authorization failure
res.status(404).send("Not Found");
return;
}
res.status(200).send(`Hello, you can "read" Organization:${orgId}`);
});
app.listen(8000);
}
start();
From your browser or using cURL
, navigate to http://{username}:@localhost:8000/{orgId}
(e.g., http://123:@localhost:8000/456
).
Continuing the journey
- Learn the steps for building authorization with Oso Cloud
- Review successful and failed authorization checks (opens in a new tab)
- Explore additional models
Talk to an Oso Engineer
If you'd like to learn more about using Oso Cloud in your app or have any questions about this guide, connect with us on Slack. We're happy to help.