Tutorial: Using Cerbos with Okta :: Cerbos Authorization Management Platform // Documentation
Tutorial: Using Cerbos with Okta
| This documentation is for an as-yet unreleased version of Cerbos PDP. Choose 0.53.0 from the version picker at the top right or navigate to https://docs.cerbos.dev for the latest version. |
An example application of integrating Cerbos with an Express server using Okta for authentication.
Using Cerbos with Okta - YouTube
Tap to unmute
Cerbos420 subscribers
Dependencies
Node.js
An Okta account
For simplicity this demo is using the hosted Cerbos Demo PDP available in the Playground so running the Cerbos container locally isn’t required. For production use cases a deployed Cerbos PDP is required and the code updated to point to your instance. You can read more about the deployment options here.
Setup
Install Deps
- Clone the repo
git clone git@github.com:cerbos/express-okta-cerbos.git
Create an Okta Application
In your Okta instance you need to create a new application. For this example we will be making use of Okta’s ExpressOIDC package so the application’s sign-in method needs to be OIDC - OpenID Connect and the application type is Web Application.
Set Redirect URLs
The default redirect URLs for sign-in and sign-out are correct if you are running this demo app on the default 8080 port. If you have changed this in your .env file then you will need to update accordingly.
Enabling Groups in the Okta Token
By default the groups the user belongs to are not passed to the application in the Okta token - this needs enabling as these groups will be passed from Okta to Cerbos for use in authorization decisions.
To do this, go to Security > API in the sidebar, and edit the default Authorization Server.
On this page, go to the Claims tab and press Add Claim. Add a new claim called groups which includes the groups of the user in the ID token.
In production you will likely want to filter this down, but for this example we are enabling all groups to be added to the token.
Create an example admin group.
In a new Okta account the only group that exists is the Everyone group. For our demo application policies we expect users to be in admin or user group as this is what is checked.
Under Directory > Groups press Add Group and create the two groups and add your example users to them.
Setup Environment Variables
Make a copy of the .env.sample file and call it .env. You will then need to populate the fields that begin with OKTA_ with the information provided in the new application you created.
PORT=8080
CERBOS_HOSTNAME=https://demo-pdp.cerbos.cloud
CERBOS_PLAYGROUND=ygW612cc9c9xXOsOZjI40ovY2LZvXf43
OKTA_DOMAIN=
OKTA_CLIENTID=
OKTA_CLIENTSECRET=
OKTA_APP_BASE_URL=http://localhost:8080
This example is using the hosted Demo PDP of Cerbos and an example Playground instance. If you are running your own Cerbos PDP then update the
CERBOS_HOSTNAMEfield to your own instance and remove theCERBOS_PLAYGROUNDfield.
Test the app
Now that everything is wired up you should be able to go to http://localhost:8080 and press the login link to authenticate with your Okta account.
Policies
This example has a simple CRUD policy in place for a resource kind of contact - like a CRM system would have. Should you wish to experiment with this policy, you can try it in the Cerbos Playground.
The policy expects one of two roles to be set on the principal - admin and user. These roles are authorized as follows:
| Action | User | Admin |
|---|---|---|
| list | Y | Y |
| read | Y | Y |
| create | N | Y |
| update | N | Y |
| delete | N | Y |
Request Flow
User access the application and clicks Login
User is directed to the Okta UI and authenticates
A token is returned back in the redirect URL to the application
That token is then exchanged for the user profile information
The user profile from Okta being stored (user Id, roles etc).
Any requests to the /contacts endpoints fetch the data required about the resource being accessed from the data store
Call the Cerbos PDP with the principal, resource and action to check the authorization and then return an error if the user is not authorized. The Cerbos package is used for this.
const allowed = await cerbos.check({
principal: { //pass in the Okta user ID and groups
id: req.userContext.userinfo.sub,
roles: req.userContext.userinfo.groups,
},
resource: {
kind: "contact",
instances: {
//a map of the resource(s) being accessed
[contact.id]: {
attr: contact,
},
},
},
actions: ["read"], //the list of actions being performed
});
if (!allowed.isAuthorized(contact.id, "read")) { return res.status(403).json({ error: "Unauthorized" }); }
Implementation at this stage will be dependant on your business requirements.