Hey team — I recently started using <Permit.io> in...
# permit-saas
s
Hey team — I recently started using Permit.io in our project as a web API access controller and have some feedback on the URL-mapping feature: 1. Localhost URLs aren’t accepted Addresses like
<http://localhost:8787>
aren’t allowed as URL inputs, which makes local testing difficult. 2. One (URL, method) → only one (resource, action) Each (url - method) can be mapped to only a single (resource-action). Some endpoints return information across multiple resources, so we need to map to multiple resource/action pairs. 3. Multi-tenancy support The provided example flow doesn’t seem to support a multi-tenant setup (no clear way to include tenantId).
Copy code
fetch('<https://proxy.api.permit.io/proxy/xxxxxxxxxxxxxxxxxxxxxxxx?url=><PROXIED_URL>', {
  method: '<HTTP_METHOD>',
  headers: {
    'Authorization': 'Bearer <USER_JWT>'
  }
});
If I’m missing a configuration or workaround for any of the above, I’d appreciate pointers. Thanks!
a
Hi @Seiichi Arai, I'm an AI assistant for Permit.io. I'll analyze available sources and get back to you shortly.
Thanks for the feedback! I see you're working with FoAz (Frontend-only Authorization) . Let me address your points: ​*Important Note*​: FoAz is deprecated and no longer supported, but it is still available at app.permit.io/foaz-proxy (1) (2) (3) . For URL-Based permission, Permit.io is introducing app.permit.io/url-mapping (1) . Regarding your specific concerns: ​*1. Localhost URLs*​: The documentation doesn't explicitly address localhost URL restrictions. This limitation appears to be by design in the FoAz proxy implementation. ​*2. One-to-one mapping limitation*​: You're correct that each URL-method combination maps to a single resource-action pair (3) . The mapping rules are structured into four components: the API endpoint URL, HTTP method, Permit resource, and action . ​*3. Multi-tenancy support*​: For multi-tenant scenarios, you can include the tenant in the permission check. When checking permissions using URL Mapping via the PDP's
/allowed_url
endpoint, you can specify the tenant (1) (2) :
Copy code
{
  "user": {
    "key": "<mailto:raz@permit.io|raz@permit.io>"
  },
  "url": "<https://example.com/endpoint?param=value>",
  "http_method": "POST",
  "tenant": "default"
}
(1) The fetch request you showed is for the FoAz proxy. For proper multi-tenant support, consider using the PDP directly with the
/allowed_url
endpoint instead of the proxy approach (1) (2) . Given FoAz's deprecated status, I'd recommend migrating to the newer URL Mapping feature or using the PDP directly for better flexibility and ongoing support.
To learn more, see the sources I considered: [[1] Simple URL Mapping Check](https://docs.permit.io/foaz/url-mapping-check) [[2] Regex URL Mapping Check](https://docs.permit.io/foaz/regex-url-mapping-check) [[3] Working with the UI](https://docs.permit.io/foaz/visual-guide)
o
Hi @Seiichi Arai - welcome and thanks for reaching out. 1. Is a legacy side-effect of the (now deprecated) FoAz feature, which URL mapping was part of a. I’ll check with the team on how quickly we can fix this (@Raz Co, @Alon Boshi, @Ze'ev Manilovich) 2. In the end you’d need to map each incoming
URL + verb
(additional potential meta data like body content) to a specific policy object for enforcement - are you maybe missing the ability to describe parts of your incoming calls? 3. See AI answer - @Alon Boshi - let’s improve this in the docs
s
Thanks for the reply! I’m understand the current situation on #1 and #3. For #2, I’ll share before/after screenshots of the mapping step. Expectation (one URL + verb mapped to multiple policy targets): https://example.com/members + GET ⇔ Member:read https://example.com/members + GET ⇔ Group:read Actual: https://example.com/members + GET ⇔ Group:read (I can’t add Group:read as an additional mapping.)
Screenshot from 2025-11-05 10-47-37.png,Screenshot from 2025-11-05 10-48-33.png
a
Hey @Seiichi Arai, Looping in the team, will circle back to you soon
For #2 @Seiichi Arai, The (URL, method) pair is like a translation key between the API request and the internal logic. Each pair must be unique, otherwise the backend wouldn’t know which internal resource or action to trigger.
@Seiichi Arai For #1, I was able to test this in my env and I have a working example via the API. The UI currently has filed validation that won't let you save a non-https or regex based url. Take a look at this guide/tutorial to see how to configure all these: https://deploy-preview-539--permitio-docs.netlify.app/foaz/regex-url-mapping-check/
Copy code
curl --location '<https://api.permit.io/v2/facts/support/urlmapping/proxy_configs>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer permit_key_yourKey' \
--data '{
  "secret": "notUsed",
  "key": "test_http",
  "name": "test_http",
  "auth_mechanism": "Bearer",
  "mapping_rules": [
    {
        "url": "^<http://localhost/users/(?P><user_id>[0-9]+)/profile$",
        "http_method": "post",
        "resource": "customers",
        "action": "create",
        "url_type": "regex",
        "priority": "1"
    }
  ]
}'
Note that
user_id
can be used in resource.attribute based ABAC rules (similar to your
tenant
need). Note that the values are mapped to resource.attributes, and so it will show up as
resource.tenant
and not
tenant.id
.
Proof it works: AllowedURL call:
Copy code
curl --location '<http://localhost:7766/allowed_url>' \
--header 'x-permit-sdk-language: <string>' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer permit_key_yourKey' \
--data '{
  "user": {
    "key": "bob"
  },
  "http_method": "post",
  "url": "<http://localhost/users/123/profile>",
  "tenant": "default"
}'
Response:
Copy code
{
  "allow": true,
  "query": {},
  "debug": {
    "rbac": {
      "allow": true,
      "allowing_roles": [
        "admin"
      ],
      "code": "allow",
      "reason": "user 'bob' has the role 'admin' in tenant 'default', role 'admin' has the 'create' permission on resources of type 'customers'"
    },
    "request": {
      "action": "create",
      "resource": {
        "attributes": {
          "type": "customers",
          "user_id": "123"
        },
        "type": "customers"
      },
      "tenant": "default",
      "user": {
        "attributes": {
          "key": "bob",
          "roles": [
            "admin"
          ],
          "tenants": [
            "default"
          ]
        },
        "key": "bob",
        "synced": true
      }
    }
  },
  "result": true
}
See screenshots for policy setup.
s
Thanks for the solid answers to #1 and #3. I’ll try them out later!
The (URL, method) pair is like a translation key between the API request and the internal logic.
Each pair must be unique; otherwise, the backend wouldn’t know which internal resource or action to trigger.
Regarding #2, I understand the current concept of URL mapping, but I think it’s a bit inflexible. There are situations where a user may want to assign one URL–method to multiple resource-action pairs, for example: •
GET <https://example.com/organizations/1/groups/1/members>
⇔
Member:read
Returns the list of members associated with organization 1 and group 1. •
GET <https://example.com/organizations/1/members>
⇔
Member:read
•
GET <https://example.com/organizations/1/members>
⇔
Group:read
Returns the member list with group info in organization 1. I know the principle of RESTful APIs recommends returning a single resource, but in practice it’s sometimes unavoidable to expose endpoints that return data across multiple resources.
p
Hey, thanks for reaching out ! It seems our team is a little busy right now, a human will be with you within the next hour or so. In the meantime, can I help you ?
t
@Seiichi Arai I believe you can achieve some level what you're trying to do with ReBAC derivations combined with url_mapping feature.
but probably not all of it... the
/allowed_url
does a single mapping between one resource and it's action. You can create a priority list of urls that match, and the top one will be the one that is evaluated, but really the goal is to provide a translation of
url + http_verb
to
resource + action
so that we can forward the request to OPA.
👀 1
s
From what I’ve researched, my understanding is that OPA itself allows saving the same URL-mapping pair with priority. However, looking at how
allowed_url
api is processed, it seems only the highest-priority entry is taken into account. I assume that’s the current behavior of the PDP. https://github.com/permitio/PDP/blob/main/horizon/enforcer/utils/mapping_rules_utils.py#L162 As for the UI showing two registrations were treated as a single entry, I suspect that’s to keep it consistent with this behavior.
t
I assume that’s the current behavior of the PDP.
correct.
As for the UI showing two registrations were treated as a single entry, I suspect that’s to keep it consistent with this behavior.
no, foaz isn't technically the same as the regex url mapping. I would ignore what foaz UI shows you.
👍 1