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
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).
Claims indicate the essential attributes necessary to identify a specific party; any user intersecting these claims is permitted to represent (and act as) the party. Once created and bound to a protocol - during a protocol instantiation - a party's claims cannot be modified and can only be changed by replacing the party itself by performing a transfer of ownership, or via migration. More about Transfer of ownership.
Refer to authorization and authentication for a more in-depth explanation.
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
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
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(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),
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 claim intersects the values given.
partyOf(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),
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 his 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
Mark's claims contain one value for every claim in the IT Group (intersection). Therefore, Mark can represent the IT Group.
Joe's situation is similar to Mark's except that he has more claims than the IT Group's (proper superset). Also, Joe's 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 claims are missing the 'role' claim and therefore is not a superset and fails the qualification to represent either Mark or Joe.
partyOf(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),Pair("role", setOf("Technician")),
Pair("name", setOf("Mark"))
)
)
.mayRepresent(
partyOf(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),
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")),
Pair("role", setOf("Technician")),
Pair("name", setOf("Joe"))
)
)
.mayRepresent(
partyOf(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),
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(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),
Pair("name", setOf("Sally", "Mark", "Joe"))
)
)
.mayRepresent(
partyOf(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),
Pair("role", setOf("Technician")),
Pair("name", setOf("Mark"))
)
)
) == false // Missing role claim
partyOf(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar")),
Pair("department", setOf("IT")),
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")),
Pair("role", setOf("Technician")),
Pair("name", setOf("Joe"))
)
)
) == false // Missing role claim
claims
<function> Returns the receiver party's claims.
Receiver
Party
Returns
Map<Text, Set<Text>> - a map of the receiver party's entity claims and values
Usage
partyOf(
claims = mapOf(
Pair("iss", setOf("Noumena")),
Pair("location", setOf("Baar"))
)
).claims()
== mapOf(Pair("iss", setOf("Noumena")), Pair("location", setOf("Baar")))
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"