PHPackages                             amtgard/ork-iam - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. amtgard/ork-iam

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

amtgard/ork-iam
===============

Amtgard ORK IAM

v2.1.1(3w ago)0361MITPHPPHP ^8.3

Since Sep 23Pushed 3w agoCompare

[ Source](https://github.com/amtgard/ork-iam)[ Packagist](https://packagist.org/packages/amtgard/ork-iam)[ Docs](https://github.com/amtgard/ork-iam)[ RSS](/packages/amtgard-ork-iam/feed)WikiDiscussions main Synced today

READMEChangelog (10)Dependencies (16)Versions (26)Used By (1)

ork-iam
=======

[](#ork-iam)

IAM implementation for ORNs — the policy engine for parsing ORNs, evaluating claims against requirements, and authorizing policies.

Design
------

[](#design)

Installation
------------

[](#installation)

Requirements:

- PHP ^8.3
- ext-json

**Policy engine only** (bring your own ORN definitions):

```
composer require amtgard/ork-iam
```

**With standard Amtgard ORN definitions** (Attendance, ORK):

```
composer require amtgard/ork-iam amtgard/ork-iam-orn-definitions
```

`ork-iam` provides the IAM engine. It does not ship ORN definition classes itself. Use the companion package [amtgard/ork-iam-orn-definitions](https://github.com/amtgard/ork-iam-orn-definitions) for the standard set, or register your own (see below).

For local development:

```
composer install
```

### Version lines

[](#version-lines)

LineBranchComposer constraintLatest tag1.x (maintenance)`1.x``"amtgard/ork-iam": "^1.4"``v1.4.0`2.x (current)`main``"amtgard/ork-iam": "^2.1"``v2.1.0`Pin `^1.4` for IDP and existing integrators on the 1.x API. Use `^2.1` for the current ontology API (`ServiceCatalog`, `ornSegmentSchema()`, …).

### Branching

[](#branching)

- **1.x fixes and minors** — branch from `1.x`, name `feature/1.x/`, open PRs against `1.x`. Tag releases `v1.4.0`, `v1.5.0`, … on `1.x`.
- **2.x features** — branch from `main`, name `feature/`, open PRs against `main`. Tag releases `v2.1.0`, `v2.2.0`, … on `main`.

Do not use `1.x/feature/...` — it conflicts with the `1.x` branch ref.

Introduction
------------

[](#introduction)

ORK IAM is a policy document system that allows for testing `claims` against `requirements`. `claims` may be bundled into `policies`. If any claim in a policy is accepted by the requirement on a given object, then the policy is accepted by the requirement; otherwise, it is rejected.

A claim and a policy are not self-enforcing, in the sense that any validly constructed claim can be compared to a requirement; it is up to the system making the comparison to validate that the given claim originated from a trusted source.

A typical method of doing this would be a cryptographic signature of the policy from the trusted source, or a cryptographic signature of an envelope containing the policy, such as embedding the policy in a JWT.

ORN definitions
---------------

[](#orn-definitions)

`ClaimFactory` and `RequirementFactory` resolve ORN strings to concrete classes via `OrnClassMap`. **Services must be registered before use** — otherwise factories throw `InvalidArgumentException`.

### Standard definitions (optional)

[](#standard-definitions-optional)

Install [amtgard/ork-iam-orn-definitions](https://github.com/amtgard/ork-iam-orn-definitions). That package registers Attendance and ORK claim/requirement classes with `OrnClassMap` automatically on Composer autoload.

Currently defined there:

ServiceClaim classRequirement classAttendance`Amtgard\IAM\Definitions\ORN\AttendanceClaim``Amtgard\IAM\Definitions\ORN\AttendanceRequirement`ORK`Amtgard\IAM\Definitions\ORN\OrkClaim``Amtgard\IAM\Definitions\ORN\OrkRequirement`### Custom definitions

[](#custom-definitions)

Define your own ORN classes by extending the framework types:

- `Amtgard\IAM\ORNFormat` — proviso layout and valid resources for a service
- `Amtgard\IAM\Allowance\Claim` — claim ORN for a service
- `Amtgard\IAM\Requirement\Requirement` — requirement ORN for a service

Register them with `OrnClassMap` before calling the factories:

```
use Amtgard\IAM\ORN\OrnClassMap;
use Amtgard\IAM\OrkServices;
use MyApp\IAM\AttendanceClaim;
use MyApp\IAM\AttendanceRequirement;

OrnClassMap::registerClaim(OrkServices::Attendance, AttendanceClaim::class);
OrnClassMap::registerRequirement(OrkServices::Attendance, AttendanceRequirement::class);
```

A typical approach is a bootstrap file loaded via Composer autoload `files`, the same pattern used by `ork-iam-orn-definitions`.

### ORN ontology

[](#orn-ontology)

ORK IAM uses a consistent vocabulary for ORN structure. See [docs/ORN-ONTOLOGY.md](docs/ORN-ONTOLOGY.md) for the full glossary and the planned 2.0.0 rename.

Term1.x APIMeaning**Prefix**`ServiceIdentifier`, `getPrefix()`Leading segment — who owns the ORN**Schema**`ornSegmentSchema()`Ordered segment labels for a claim/requirement type**Label**`Orn\OrnSegmentLabel`Name of one middle segment in the schema**Offset**`segmentOffset()`, `OrnSegmentLabel::offsetIn()`Zero-based index of a label in the schema**Value**`getSegmentValue()`Parsed ID in one segment (`int`, `*`, or empty)**Binding**`Proviso` (`Grant` / `Condition`)Label + value on a parsed claim or requirement**Catalog**`OrkServices`Built-in registry of known prefix and label namesLegacy names (`serviceFormat()`, `getProviso()`, `ProvisoSlot`, …) remain available and are deprecated for removal in 2.0.0.

### Custom service identifiers

[](#custom-service-identifiers)

An ORN has two distinct naming layers at the prefix and schema level:

1. **Prefix** — the leading segment (`Attendance` in `Attendance:1:2:…`, or any custom name like `YourService` in `YourService:1:Widget/Read`). This identifies which integrator or product owns the ORN.
2. **Schema labels** — the ordered middle segments returned by `ornSegmentSchema()` (`Configuration`, `Game`, `Kingdom`, …). Each label names one ORN value segment, not the value itself.

Built-in prefixes (`Attendance`, `ORK`, …) normalize to `OrkServices` cases. Integrators may also register **custom prefixes** that are not enum members, as long as they match `/^[A-Z][A-Za-z0-9]*$/`. Each prefix maps to its own claim/requirement classes and `serviceFormat()` layout.

```
use Amtgard\IAM\ClaimFactory;
use Amtgard\IAM\ORN\OrnClassMap;
use MyApp\IAM\YourServiceClaim;
use MyApp\IAM\YourServiceRequirement;

OrnClassMap::registerClaim('YourService', YourServiceClaim::class);
OrnClassMap::registerRequirement('YourService', YourServiceRequirement::class);

$claim = ClaimFactory::createOrn('YourService:1:Widget/Read');
```

Built-in `OrkServices` names cannot be registered via a custom string key — use the enum overload (`OrnClassMap::registerClaim(OrkServices::Attendance, …)`). `OrnClassMap::validateCustomServiceName()` checks that a proposed custom name does not collide with a built-in identifier.

Use `getServiceIdentifier()` on claims and requirements for the prefix string. `getService()` remains available when the prefix maps to a built-in `OrkServices` case.

#### Custom segment labels

[](#custom-segment-labels)

`ornSegmentSchema()` (or legacy `serviceFormat()`) may return `OrkServices` cases, arbitrary strings, or `OrnSegmentLabel` instances. Unlike prefixes, custom label names are not restricted — integrators can use any non-empty string (`tenant-id`, `org unit`, and so on). Strings that exactly match a built-in catalog entry normalize to that `OrkServices` case.

```
protected function serviceFormat(): array
{
    return [OrkServices::Configuration, 'tenant-id', 'org unit'];
}

// equivalent preferred form:
protected function ornSegmentSchema(): array
{
    return [OrkServices::Configuration, 'tenant-id', 'org unit'];
}
```

For an ORN `YourService:1:42:7:Widget/Read`, the values `1`, `42`, and `7` map to `Configuration`, `tenant-id`, and `org unit` by offset. Use `getSegment('tenant-id')` or `getSegment(OrnSegmentLabel::from('tenant-id'))` to read a binding. `getSegmentLabel()` and `getSegmentValue()` are the preferred accessors on binding objects.

#### Alternative: `Application` prefix

[](#alternative-application-prefix)

`OrkServices::Application` exists as a catch-all enum case. An integrator could use `Application:…` ORNs instead of custom string prefixes, but every integrator would share one prefix and therefore one `serviceFormat()` validator — strong per-service ORN validation is not possible. Custom string prefixes are preferred so each integrator can register its own claim/requirement classes and proviso layout.

Usage
-----

[](#usage)

Examples below assume `amtgard/ork-iam-orn-definitions` is installed. Adjust namespaces if you use custom definition classes.

*Single claim*

```
