Skip to content

Party

Type

Usage

NPL provides a built-in type Party for parties. Parties represent entities that interact with protocols. The protocol parties are declared in the protocol header as special protocol parameters.

In the following example issuer and payee represent the parties on the protocol Iou.

protocol[issuer, payee] Iou() {
    permission[issuer] pay() {
        // ...
    };

    permission[payee] forgive() {
        // ...
    };
};

See protocol for more information on how to use parties.

Claims: entity and access

The NPL party type represents these entities with the use of claims. These claims form a simplified version of attribute based access control (ABAC). This, in turn, provides a means to determine whether the party has rights to access a given protocol or access its action(s). Within NPL these claims are split into two types, entity and access.

See authorization and authentication for more about entity and access.

Entity claims indicate the essential claims necessary to identify the entity that the party represents. Once created and bound to a protocol, during a protocol instantiation, a party's entity claims cannot be modified. The claims can only be changed by replacing the party itself by performing a transfer of ownership, or via migration. More about Transfer of ownership.

Access claims represent the elements that need the flexibility to change and reflect the roles and responsibilities the party can perform on behalf of the entity. Access claims can be changed but only by the user whose JWT claims match the original claims of the NPL party. This can be done by using the engine API endpoint for changing protocol access.

Calling party and bound party

Calling party - The party initiating the action/permission. As previously stated, a party in NPL is represented as claims.

Bound party - The party/claims specified during protocol instantiation and when changing access claims via the API. This is the party used to determine if the calling party has access to the given resource.

The claims are evaluated to determine if the calling party is authorized to access the given protocol. To understand how claims are matched and party access is determined, see claims evaluation

Note:

NPL still supports the legacy party constant (shown below) from within NPL. It is considered bad practice except in testing.

const PARTY = 'Joe';

Even though it is shown as a literal value, in the system it has the following claims:

{
  "entity": {
    "party": "Joe"
  },
  "access": {}
}

Constraints

Due to its prominent role in NPL, the Party type/value cannot be used in the following situations:

  • Protocol parameters cannot be of type Party.
  • Regular (non-party) protocol fields cannot contain a value of type Party.
  • Permission, obligation, notification parameters as well as return types are not allowed to be of the Party type.

Party can however be used as a function parameter and return type.

// Illegal Party parameter type.
notification SayHello(p: Party) returns Party; // Illegal Party return type.

protocol[issuer, payee] Iou(illegalPartyAsProtocolParameter: Party) { // Illegal parameter type.
    var illegalPartyInField = issuer; // Illegal field value.

    // Illegal parameter type and return type.
    permission[issuer] pay(illegalPartyAsActionParameter: Party) returns Party {};

    // Legal return type.
    function check(legalPartyAsFunctionParameter: Party) returns Map<Text, Party> {
        // Legal local variable.
        var m = mapOf(Pair { first: "someone", second: legalPartyAsFunctionParameter });

        // Legal return type.
        return m;
    };
}

Methods

sameEntityAs

<function> Indicates whether the receiver party and the given party's entity claims are identical to each other.

Receiver

Party

Arguments

otherParty - Party - a party containing the claims to compare to

Returns

Boolean - 'true' if both parties' entity claims are identical.

Usage

partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf(
        Pair("role", setOf("Manager")),
        Pair("name", setOf("Sally"))
    )
)
.sameEntityAs(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT"))
        ),
        accessClaims = mapOf(
            Pair("role", setOf("Technician")),
            Pair("name", setOf("Mark"))
        )
    )
) == true
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar"))
    ),
    accessClaims = mapOf(
        Pair("name", setOf("Alfred"))
    )
)
.sameEntityAs(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT"))
        ),
        accessClaims = mapOf(
            Pair("role", setOf("Manager")),
            Pair("name", setOf("Sally"))
        )
    )
) == false

containsEntityValuesOf

<function> Indicates whether all of this party's entity claims are present in the given party's entity.

Receiver

Party

Arguments

otherParty - Party - a party containing the claims to which the receiver party will be compared

Returns

Boolean - 'true' if the entity claims and respective values of otherParty are present in this party's entity claims.

Usage

partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf(
        Pair("role", setOf("Manager")),
        Pair("name", setOf("Sally"))
    )
)
.containsEntityValuesOf(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT"))
        ),
        accessClaims = mapOf(
            Pair("role", setOf("Technician")),
            Pair("name", setOf("Mark"))
        )
    )
) == true
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT")),
        Pair("access", setOf("Super Secret"))
    ),
    accessClaims = mapOf(
        Pair("role", setOf("Technician")),
        Pair("name", setOf("Joe"))
    )
)
.containsEntityValuesOf(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT"))
        ),
        accessClaims = mapOf(
            Pair("role", setOf("Technician")),
            Pair("name", setOf("Mark"))
        )
    )
) == true
// Joe's entity claims contain all the entity values
// of Mark's but also has an additional claim
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf(
        Pair("role", setOf("Technician")),
        Pair("name", setOf("Mark"))
    )
)
.containsEntityValuesOf(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT")),
            Pair("access", setOf("Super Secret"))
        ),
        accessClaims = mapOf(
            Pair("role", setOf("Technician")),
            Pair("name", setOf("Joe"))
        )
    )
) == false // Mark is missing the 'access' claim in Joe's entity claims

isRepresentableBy

<function> Indicates whether or not the given claims can be used to represent the receiver party.

Receiver

Party

Arguments

fullClaims - Map<Text,Set<Text>> - a map of claims to which the receiver party will be compared

Returns

Boolean - 'true' if the given claims contain all of the entity claims and at least a single value for each access claim match.

Usage

partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf(
        Pair("role", setOf("Manager")),
        Pair("name", setOf("Sally"))
    )
)
.isRepresentableBy(fullClaims = mapOf(
    Pair("iss", setOf("Noumena")),
    Pair("location", setOf("Baar")),
    Pair("department", setOf("IT")),
    Pair("name", setOf("Sally", "Joe")),
    Pair("role", setOf("Manager"))
)) == true
// Sally can be represented by these claims because each of her entity claims
// match and her access claims also intersect the values given.
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf(
        Pair("role", setOf("Technician")),
        Pair("name", setOf("Mark"))
    )
)
.isRepresentableBy(fullClaims = mapOf(
    Pair("iss", setOf("Noumena")),
    Pair("location", setOf("Baar")),
    Pair("department", setOf("IT")),
    Pair("name", setOf("Sally", "Joe")),
    Pair("role", setOf("Manager"))
)) == false
// Mark would not be representable because even though his entity claims are contained within the
// given claims, his access claims do not intersect ('name' and 'role' values are missing).

mayRepresent

<function> Indicates if this party can act on behalf of the given party.

Receiver

Party

Arguments

otherParty - Party - a party containing the claims to which the receiver party will be compared

Returns

Boolean - 'true' if this party's entity claims contain all of the entity claims of otherParty and at least a single value for each access claim of both parties match.

Usage

There are two claim types, entity and access, as described here.

Mark's entity claims contain all the IT Group's entity (superset). Also, Mark's access claims contain one value for every claim in the IT Group (intersection). Since both of these conditions are true Mark can represent the IT Group.

Joe's situation is similar to Mark's except that he has more entity claims than the IT Group's entity (proper superset). Also, Joe's entity claims contain all the claims and matching values with the IT Group. The access key and values also exist for both Parties. Since both of the pre-requisites are true Joe can also represent the IT Group.

However, The IT group entity claims are missing the 'role' claim and therefore is not a superset and fails the qualification to represent Mark or Joe.

partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf(
        Pair("role", setOf("Technician")),
        Pair("name", setOf("Mark"))
    )
)
.mayRepresent(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT"))
        ),
        accessClaims = mapOf<Text, Set<Text>>(
            Pair("name", setOf("Sally", "Mark", "Joe"))
        )
    )
) == true // Mark is a technician in the IT Group. Mark can represent the IT Group.
partyOf(
    mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT")),
        Pair("access", setOf("Super Secret"))
    ),
    mapOf(
        Pair("role", setOf("Technician")),
        Pair("name", setOf("Joe"))
    )
)
.mayRepresent(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT"))
        ),
        // Access
        accessClaims = mapOf<Text, Set<Text>>(
            Pair("name", setOf("Sally", "Mark", "Joe"))
        )
    )
) == true // Joe is a senior technician on the IT Group, so he can also represent the IT Group
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf<Text, Set<Text>>(
        Pair("name", setOf("Sally", "Mark", "Joe"))
    )
)
.mayRepresent(
    partyOf(
        entityClaims = mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT"))
        ),
        accessClaims = mapOf(
            Pair("role", setOf("Technician")),
            Pair("name", setOf("Mark"))
        )
    )
) == false // Missing role claim
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar")),
        Pair("department", setOf("IT"))
    ),
    accessClaims = mapOf<Text, Set<Text>>(
        Pair("name", setOf("Sally", "Mark", "Joe"))
    )
)
.mayRepresent(
    partyOf(
        mapOf(
            Pair("iss", setOf("Noumena")),
            Pair("location", setOf("Baar")),
            Pair("department", setOf("IT")),
            Pair("access", setOf("Super Secret"))
        ),
        mapOf(
            Pair("role", setOf("Technician")),
            Pair("name", setOf("Joe"))
        )
    )
) == false // Missing role claim

entity

<function> Returns the receiver party's entity claims.

Receiver

Party

Returns

Map<Text, Set<Text>> - a map of the receiver party's entity claims and values

Usage
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar"))
    ),
    accessClaims = mapOf(
        Pair("name", setOf("Alfred"))
    )
).entity()
== mapOf(Pair("iss", setOf("Noumena")), Pair("location", setOf("Baar")))

access

<function> Returns the receiver party's access claims.

Receiver

Party

Returns

Map<Text, Set<Text>> - a map of the receiver party's access claims and values

Usage
partyOf(
    entityClaims = mapOf(
        Pair("iss", setOf("Noumena")),
        Pair("location", setOf("Baar"))
    ),
    accessClaims = mapOf(
        Pair("name", setOf("Alfred"))
    )
).access()
== mapOf(Pair("name", setOf("Alfred")))

Inherited methods

toText

<function> Obtain the Text representation of this.

Receiver

T

Type Arguments

T

Returns

Text - the Text representation of this

Usage

Converts a Party to Text.

const sampleParty = 'Mario';
sampleParty.toText() == "Mario"