Skip to main content

Modeling Public Access

In this guide you will learn how to grant public access to an object, such as a certain document, using type bound public access.

When to use

Public access allows your application to grant every user in the system access to an object. You would add a relationship tuple with type-bound public access when:

  • sharing a document publicly to indicate that everyone can view it
  • a public poll is created to indicate that anyone can vote on it
  • a blog post is published and anyone should be able to read it
  • a video is made public for anyone to watch

Before You Start

In order to understand this guide correctly you must be familiar with some Okta FGA Concepts and know how to develop the things that we will list below.

Assume that you have the following authorization model.
You have a type called document that can have a view relation.

model
schema 1.1

type user

type document
relations
define view: [user, user:*]

In addition, you will need to know the following:

Direct Access

You need to know how to create an authorization model and create a relationship tuple to grant a user access to an object. Learn more →

Okta FGA Concepts

  • A Type: a class of objects that have similar characteristics
  • A User: an entity in the system that can be related to an object
  • A Relation: is a string defined in the type definition of an authorization model that defines the possibility of a relationship between an object of the same type as the type definition and a user in the system
  • An Object: represents an entity in the system. Users' relationships to it can be define through relationship tuples and the authorization model
  • A Relationship Tuple: a grouping consisting of a user, a relation and an object stored in Okta FGA
  • A Type Bound Public Access: is a special Okta FGA concept (represented by <type>:*) can be used in relationship tuples to represent every object of that type
caution

Make sure to use unique ids for each object and user within your application domain when creating relationship tuples for Okta Fine Grained Authorization (FGA). We are using first names and simple ids to just illustrate an easy-to-follow example.

The Playground

Try this guide out on the Okta FGA Playground

Step By Step

In previous guides, we have shown how to indicate that objects are related to users or objects. In some cases, you might want to indicate that everyone is related to an object (for example when sharing a document publicly).

01. Create A Relationship Tuple

To do this we need to create a relationship tuple using the type bound public access. The type bound public access syntax is used to indicate that all users of a particular type have a relation to a specific object.

Let us create a relationship tuple that states: any user can view document:company-psa.doc

Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
const { CredentialsMethod, OpenFgaClient } = require('@openfga/sdk'); // OR import { CredentialsMethod, OpenFgaClient } from '@openfga/sdk';

// Ensure the environment variables are set
// FGA_API_URL = 'https://api.us1.fga.dev' // 'https://api.eu1.fga.dev' for EU and 'https://api.au1.fga.dev' for AU
// FGA_STORE_ID = 'YOUR_STORE_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page
// FGA_MODEL_ID = 'YOUR_MODEL_ID' - optional, can be overridden per request, helps reduce latency
// FGA_API_TOKEN_ISSUER = 'fga.us.auth0.com'
// FGA_API_AUDIENCE = 'https://api.us1.fga.dev/' // 'https://api.eu1.fga.dev/' for EU and 'https://api.au1.fga.dev/' for AU
// FGA_CLIENT_ID = 'YOUR_CLIENT_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page
// FGA_CLIENT_SECRET = 'YOUR_CLIENT_SECRET' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page

const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL,
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID,
credentials: { // Credentials are not needed if connecting to the Playground API
method: CredentialsMethod.ClientCredentials,
config: {
apiTokenIssuer: process.env.FGA_API_TOKEN_ISSUER,
apiAudience: process.env.FGA_API_AUDIENCE,
clientId: process.env.FGA_CLIENT_ID,
clientSecret: process.env.FGA_CLIENT_SECRET,
},
},
});

await fgaClient.write({
writes: [
// user:* denotes every object of type user
{"_description":"user:* denotes every object of type user","user":"user:*","relation":"view","object":"document:company-psa.doc"}
],
}, {
authorization_model_id: "1uHxCSuTP0VKPYSnkq1pbb1jeZw"
});
Wildcard syntax usage

Please note that type-bound public access is not a wildcard or a regex expression.

You cannot use the <type>:* syntax in the tuple's object field.

The following syntax is invalid:

[// It is invalid to use this syntax in the object field. The below relationship tuple is invalid and does not mean that Bob can view all documents.
{
"_description": "It is invalid to use this syntax in the object field. The below relationship tuple is invalid and does not mean that Bob can view all documents.",
"user": "user:bob",
"relation": "view",
"object": "document:*"
}]
Wildcard syntax usage

You cannot use <type>:* as part of a userset in the tuple's user field.

The following syntax is invalid:

[// It is invalid to use this syntax as part of a userset. The below relationship tuple is invalid and does not mean that members of any org can view the company-psa document.
{
"_description": "It is invalid to use this syntax as part of a userset. The below relationship tuple is invalid and does not mean that members of any org can view the company-psa document.",
"user": "org:*#member",
"relation": "view",
"object": "document:company-psa.doc"
}]

02. Check That The Relationship Exists

Once the above relationship tuple is added, we can check if bob cab view document:company-psa.doc. Okta FGA will return { "allowed": true } even though no relationship tuple linking bob to the document was added. That is because the relationship tuple with user:* as the user made it so every object of type user (such as user:bob) can view the document, making it public.

Initialize the SDK
// Checkout the "How to Setup the SDK Client" page for more details.
const { CredentialsMethod, OpenFgaClient } = require('@openfga/sdk'); // OR import { CredentialsMethod, OpenFgaClient } from '@openfga/sdk';

// Ensure the environment variables are set
// FGA_API_URL = 'https://api.us1.fga.dev' // 'https://api.eu1.fga.dev' for EU and 'https://api.au1.fga.dev' for AU
// FGA_STORE_ID = 'YOUR_STORE_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page
// FGA_MODEL_ID = 'YOUR_MODEL_ID' - optional, can be overridden per request, helps reduce latency
// FGA_API_TOKEN_ISSUER = 'fga.us.auth0.com'
// FGA_API_AUDIENCE = 'https://api.us1.fga.dev/' // 'https://api.eu1.fga.dev/' for EU and 'https://api.au1.fga.dev/' for AU
// FGA_CLIENT_ID = 'YOUR_CLIENT_ID' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page
// FGA_CLIENT_SECRET = 'YOUR_CLIENT_SECRET' - Get this from your store settings in the dashboard, refer to the "How to get your API Keys" page

const fgaClient = new OpenFgaClient({
apiUrl: process.env.FGA_API_URL,
storeId: process.env.FGA_STORE_ID,
authorizationModelId: process.env.FGA_MODEL_ID,
credentials: { // Credentials are not needed if connecting to the Playground API
method: CredentialsMethod.ClientCredentials,
config: {
apiTokenIssuer: process.env.FGA_API_TOKEN_ISSUER,
apiAudience: process.env.FGA_API_AUDIENCE,
clientId: process.env.FGA_CLIENT_ID,
clientSecret: process.env.FGA_CLIENT_SECRET,
},
},
});

// Run a check
const { allowed } = await fgaClient.check({
user: 'user:bob',
relation: 'view',
object: 'document:company-psa.doc',
}, {
authorization_model_id: '1uHxCSuTP0VKPYSnkq1pbb1jeZw',
});

// allowed = true
Modeling: Getting Started

Learn about how to get started with modeling.

Configuration Language

Learn about Okta FGA Configuration Language.

Modeling Blocklists

Learn about model block lists.

Have Feedback?

You can use any of our support channels for any questions or suggestions you may have.