# Contextual Based Relationships Suggestion

**URL:** <https://community.auth0.com/t/contextual-based-relationships-suggestion/184177>\
**Category:** Auth0 Fine-Grained Authorization\
**Created:** [March 20, 2025, 6:08am UTC](https://community.auth0.com/t/contextual-based-relationships-suggestion/184177 "2025-03-20T06:08:01Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![justin.cui](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/justin.cui/32/71157_2.png) [@justin.cui](https://community.auth0.com/u/justin.cui)\
**Post date:** [March 20, 2025, 6:08am UTC](https://community.auth0.com/t/contextual-based-relationships-suggestion/184177/1 "2025-03-20T06:08:01Z")

</div>

Hi guys,

I’ve been reading up on how to do contextual based relationships

```auto
https://docs.fga.dev/modeling/basics/organization-context-authorization

```

and i’ve mocked something up that is sort of akin to what i would like to represent our objects and relationships as:

```auto
model
  schema 1.1

type user

type organization
  relations
    define base_org_viewer: [user] or org_viewer
    define base_org_writer: [user] or org_writer
    define has_view_access: base_org_viewer and user_in_context
    define has_write_access: base_org_writer and user_in_context
    define member: [user]
    define org_viewer: [user] and user_in_context
    define org_writer: [user] and user_in_context
    define user_in_context: [user]

type subscription
  relations
    define can_view: viewer
    define can_write: writer
    define subscriber: [organization]
    define viewer: has_view_access from subscriber
    define writer: has_write_access from subscriber

type application
  relations
    define can_view: can_view from subscription
    define can_write: can_write from subscription
    define subscription: [subscription]

```

so in this case, if a user is part of an organization that has view access and the organization has a relationship with a subscription that also has a relationship with the application that the user is trying to view, then the it should return allow.

i ran this snippet of code while passing the context into the contextTuple and i am getting the expected response of true

```auto
const fgaClient = new OpenFgaClient({
    apiUrl: FGA_API_URL,
    storeId: FGA_STORE_ID,
    authorizationModelId: FGA_MODEL_ID,
    credentials: {
      method: CredentialsMethod.ClientCredentials,
      config: {
        apiTokenIssuer: FGA_API_TOKEN_ISSUER,
        apiAudience: FGA_API_AUDIENCE,
        clientId: FGA_CLIENT_ID,
        clientSecret: FGA_CLIENT_SECRET,
      },
    }
});

const check = async () => {
    const { allowed } = await fgaClient.check({
        user: 'user:anne',
        relation: 'can_view',
        object: 'application:app1',
        contextualTuples: [
          {"_description":"Anne is authorizing from the context of organization:A","user":"user:anne","relation":"user_in_context","object":"organization:org1"}
        ],
      }, {
      authorization_model_id: FGA_MODEL_ID,
    });

    console.log(allowed);

}

check()

// logs out true

```

the tuples i used are :

```auto
 await fgaClient.write({
    writes: [
        // Anne has a `base_org_viewer` role in org1
        {"_description":"Anne has a `base_org_viewer` role at org1","user":"user:anne","relation":"base_org_viewer","object":"organization:org1"},
        // org1 has a subscription to subscription1
        {"_description":"org1 has a subscription to subscription1","user":"organization:org1","relation":"subscriber","object":"subscription:subscription1"},
        // subscription1 has a relation to app 1
        {"_description":"subscription1 has a relation to app 1","user":"subscription:subscription1","relation":"subscription","object":"application:app1"},
    ],
  }, {
    authorization_model_id: FGA_MODEL_ID
  });

```

My question was whether or not there was a way to simplify my schema as this seems a bit confusing to me when reading it as there feels like a lot of duplications in organization, subscription and application model

Thanks

---

<div class="post-metadata">

**Author:** ![andres.aguiar](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/andres.aguiar/32/7718_2.png) [@andres.aguiar](https://community.auth0.com/u/andres.aguiar)\
**Post date:** [March 20, 2025, 12:50pm UTC](https://community.auth0.com/t/contextual-based-relationships-suggestion/184177/2 "2025-03-20T12:50:32Z")

</div>

Hi!

It seems you can simplify the `organization` type. Unless I’m missing something this would be equivalent:

```auto

  type organization
    relations
      define org_viewer: [user] and user_in_context
      define org_writer: [user] and user_in_context
      define user_in_context: [user]
      
      define has_view_access: org_viewer 
      define has_write_access: org_writer 

```

You can also simplify the subscription type:

```auto
type subscription
    relations
      define subscriber: [organization]
      define can_view: has_view_access from subscriber
      define can_write: has_write_access from subscriber

```

Let me know if it helps, thanks!

---

<div class="post-metadata">

**Author:** ![justin.cui](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/justin.cui/32/71157_2.png) [@justin.cui](https://community.auth0.com/u/justin.cui)\
**Post date:** [March 21, 2025, 3:54am UTC](https://community.auth0.com/t/contextual-based-relationships-suggestion/184177/3 "2025-03-21T03:54:15Z")

</div>

Hey Andres! it worked like a charm! thank you very much 😃

I was wondering if i could ask for your input in regards to extending my schema with two new models.

I am trying to see if i can introduce the concept of api keys as a model and additional definition in subscription whereby in subscription, i am able to check if an api key is valid based on if the key is active or not. I’ve created a seperate model called active\_keys but i am not sure if this is the best approach.

```auto
model
  schema 1.1

type user

type organization
  relations
    define has_view_access: org_viewer
    define has_write_access: org_writer
    define org_viewer: [user] and user_in_context
    define org_writer: [user] and user_in_context
    define user_in_context: [user]

type active_key
  relations
    define active_key: [api_key]
    define key_in_context: [api_key]
    define key_is_active: active_key and key_in_context

type api_key
  relations
    define owner: [user]

type subscription
  relations
    define active_key: [active_key]
    define can_view: has_view_access from subscriber
    define can_write: has_write_access from subscriber
    define is_valid_api_key: key_is_active from active_key
    define subscriber: [organization]

type application
  relations
    define can_view: can_view from subscription
    define can_write: can_write from subscription
    define subscription: [subscription]

type api_bundle
  relations
    define has_access: can_view from subscription or is_valid_api_key from subscription
    define subscription: [subscription]

type api_resource
  relations
    define api_bundle: [api_bundle]
    define has_access: has_access from api_bundle

```

The problem here it seems is that i had to pass additional contexual tuples into the check call and i was wondering if this could somehow be avoided? and if there was just a way to do so without having to know the schema of the fga models? If there were a simpler way of doing this it would be greatly appreciated if you could guide me on the ways 😃

```auto
const check = async () => {
    const response = await fgaClient.check({
        user: 'api_key:api_key_1',
        relation: 'has_access',
        object: 'api_resource:api_resource_1',
        contextualTuples: [
          {"_description":"api_key_1 authorized via context of active key to subscription","user":"api_key:api_key_1","relation":"key_in_context","object":"active_key:active_key_1"},
          {"_description":"api_key_1 authorized via context of active key -> subscription -> api_bundle -> api_resources","user":"subscription:subscription_1","relation":"subscription","object":"api_bundle:api_bundle_1"}
        ],
      }, {
      authorization_model_id: FGA_MODEL_ID,
    });

    console.log(response);

}

```

This is my seed for the tuples

```auto

const seed = async () => {
  await fgaClient.write({
    writes: [
      // Anne has a `base_org_viewer` role in org1
      {"_description":"Anne has a `org_viewer` role at org1","user":"user:anne","relation":"org_viewer","object":"organization:org1"},
      // org1 has a subscription to subscription1
      {"_description":"org1 has a subscription to subscription1","user":"organization:org1","relation":"subscriber","object":"subscription:subscription1"},
      // subscription1 has a relation to app 1
      {"_description":"subscription1 has a relation to app 1","user":"subscription:subscription1","relation":"subscription","object":"application:app1"},
      {"_description":"subscription1 has a relation to api_bundle_1","user":"subscription:subscription1","relation":"subscription","object":"api_bundle:api_bundle_1"},
      {"_description":"api_bundle_1 has a relation to api_resource_1","user":"api_bundle:api_bundle_1","relation":"api_bundle","object":"api_resource:api_resource_1"},
      //----
      {"_description":"Anne has a `org_viewer` role at org2","user":"user:anne","relation":"org_viewer","object":"organization:org2"},
      {"_description":"org2 has a subscription to subscription2","user":"organization:org2","relation":"subscriber","object":"subscription:subscription2"},
      {"_description":"subscription2 has a relation to api_bundle_2","user":"subscription:subscription2","relation":"subscription","object":"api_bundle:api_bundle_2"},
      {"_description":"api_bundle_2 has a relation to api_resource_2","user":"api_bundle:api_bundle_2","relation":"api_bundle","object":"api_resource:api_resource_2"},
      //-----
      {"_description":"api_key_1 has a relation to active_key","user":"api_key:api_key_1","relation":"active_key","object":"active_key:active_key_1"},
      {"_description":"api_key_1 has a relation to subscription_1","user":"active_key:active_key_1","relation":"active_key","object":"subscription:subscription_1"},
    ],
  }, {
    authorization_model_id: FGA_MODEL_ID
  });
}

```

---

<div class="post-metadata">

**Author:** ![andres.aguiar](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/andres.aguiar/32/7718_2.png) [@andres.aguiar](https://community.auth0.com/u/andres.aguiar)\
**Post date:** [March 21, 2025, 7:54pm UTC](https://community.auth0.com/t/contextual-based-relationships-suggestion/184177/4 "2025-03-21T19:54:55Z")

</div>

A few comments/questions:

- You can considering deleting inactive keys to simplify the model.
- Why do you need ‘key\_in\_context’?
- Can you elaborate on what api\_bundle/api\_resources are?
- Shouldn’t { “user”:“subscription:subscription\_1”,“relation”:“subscription”,“object”:“api\_bundle:api\_bundle\_1”} be a tuple that’s written to FGA?

---

<div class="post-metadata">

**Author:** ![justin.cui](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/justin.cui/32/71157_2.png) [@justin.cui](https://community.auth0.com/u/justin.cui)\
**Post date:** [March 23, 2025, 11:26pm UTC](https://community.auth0.com/t/contextual-based-relationships-suggestion/184177/5 "2025-03-23T23:26:41Z")

</div>

Hey Andres!

Thanks for taking your time to assist and sorry about that, let me add more context!

So i was hoping to be able to establish a relationship between a user and an app / api\_resource in which i would be able to perform the following check and ideally without having to pass in any contextual tuples (if possible)

```auto
const check = async () => {

// does api_key_1 have access to api_resource_1

    const response = await fgaClient.check({
        user: 'api_key:api_key_1',
        relation: 'has_access',
        object: 'api_resource:api_resource_1',
        contextualTuples: [
        ],
      }, {
      authorization_model_id: FGA_MODEL_ID,
    });

    console.log(response);
}

-----

const check = async () => {

// does user have access to api_resource_1

    const response = await fgaClient.check({
        user: 'user:user_1',
        relation: 'has_access',
        object: 'api_resource:api_resource_1',
        contextualTuples: [
        ],
      }, {
      authorization_model_id: FGA_MODEL_ID,
    });

    console.log(response);
}

----
const check = async () => {

// does user have access to app_1

    const response = await fgaClient.check({
        user: 'user:user_1',
        relation: 'has_access',
        object: 'application:application_1',
        contextualTuples: [
        ],
      }, {
      authorization_model_id: FGA_MODEL_ID,
    });

    console.log(response);
}

```

However, i was hoping to be able to perform this check via an indirect relationship through a few other models of which have the following relationship:

- Users are members of organizations
- An organization can have subscriptions
- Subscriptions can have application relations as well as api\_bundle relations
- Api\_bundles are a group of api\_resources
- Api Keys are owned by users and belong to a subscription from an organization

For api\_bundles and api\_resources; an api resource is an endpoint which a user can call and an api\_bundle are just groupings of api\_resources.

As such :  
A user: user\_1 will have access to application: application\_1 if they are part of an organization: organization\_1 that has a subscription: subscription\_1 which has a relationship to application: application\_1

A user: user\_1 will have access to api\_resource: api\_resource\_1 if they are part of an organization: organization\_1 that has a subscription: subscription\_9 which has a relationship with api\_bundle: api\_bundle\_1 which includes api\_resource: api\_resource\_1

An api\_key: api\_key\_1 will have access to api\_resource\_1 if they have a relation to a subscription: subscription\_9 that has a relationship with api\_bundle: api\_bundle\_1 which includes api\_resource: api\_resource\_1

I hope that clarifies things and thanks again for helping 😃
