11import type { Claim , SignedClaim } from '../types.js' ;
2- import type { NodeIdEncoded } from '../../ids/types.js' ;
2+ import type { NodeId , NodeIdEncoded } from '../../ids/types.js' ;
33import type { SignedTokenEncoded } from '../../tokens/types.js' ;
4+ import * as claimNetworkAuthorityUtils from './claimNetworkAuthority.js' ;
5+ import Token from '../../tokens/Token.js' ;
46import * as tokensSchema from '../../tokens/schemas/index.js' ;
57import * as ids from '../../ids/index.js' ;
68import * as claimsUtils from '../utils.js' ;
9+ import * as claimsErrors from '../errors.js' ;
710import * as tokensUtils from '../../tokens/utils.js' ;
811import * as validationErrors from '../../validation/errors.js' ;
912import * as utils from '../../utils/index.js' ;
13+ import * as nodesUtils from '../../nodes/utils.js' ;
14+ import * as keysUtils from '../../keys/utils/index.js' ;
1015
1116/**
12- * Asserts that a node is apart of a network
17+ * Asserts that a node is a part of a network
1318 */
1419interface ClaimNetworkAccess extends Claim {
1520 typ : 'ClaimNetworkAccess' ;
1621 iss : NodeIdEncoded ;
1722 sub : NodeIdEncoded ;
1823 network : string ;
19- signedClaimNetworkAuthorityEncoded ?: SignedTokenEncoded ;
24+ signedClaimNetworkAuthorityEncoded : SignedTokenEncoded ;
25+ isPrivate : boolean ;
2026}
2127
2228function assertClaimNetworkAccess (
@@ -64,6 +70,14 @@ function assertClaimNetworkAccess(
6470 '`signedClaimNetworkAuthorityEncoded` property must be an encoded signed token' ,
6571 ) ;
6672 }
73+ if (
74+ claimNetworkAccess [ 'isPrivate' ] == null ||
75+ typeof claimNetworkAccess [ 'isPrivate' ] !== 'boolean'
76+ ) {
77+ throw new validationErrors . ErrorParse (
78+ '`isPrivate` property must be a boolean' ,
79+ ) ;
80+ }
6781}
6882
6983function parseClaimNetworkAccess (
@@ -84,10 +98,81 @@ function parseSignedClaimNetworkAccess(
8498 return signedClaim as SignedClaim < ClaimNetworkAccess > ;
8599}
86100
101+ function verifyClaimNetworkAccess (
102+ networkNodeId : NodeId ,
103+ subjectNodeId : NodeId ,
104+ network : string ,
105+ tokenClaimNetworkAccess : Token < ClaimNetworkAccess > ,
106+ ) : void {
107+ const signedClaim =
108+ claimNetworkAuthorityUtils . parseSignedClaimNetworkAuthority (
109+ tokenClaimNetworkAccess . payload . signedClaimNetworkAuthorityEncoded ,
110+ ) ;
111+ const claimNetworkAuthority = Token . fromSigned ( signedClaim ) ;
112+ const issuerNodeId = nodesUtils . decodeNodeId (
113+ tokenClaimNetworkAccess . payload . iss ,
114+ ) ;
115+ if ( issuerNodeId == null ) {
116+ throw new claimsErrors . ErrorClaimsVerificationFailed (
117+ 'failed to decode issuer nodeId' ,
118+ ) ;
119+ }
120+ claimNetworkAuthorityUtils . verifyClaimNetworkAuthority (
121+ networkNodeId ,
122+ issuerNodeId ,
123+ network ,
124+ claimNetworkAuthority ,
125+ ) ;
126+ // For the access claim
127+ // 1. issuer is current node
128+ // 2. subject is target node
129+ // 3. is signed by both the target and issuer
130+
131+ // Issuer should be the subject of the ClaimNetworkAuthority and signed by it
132+ const claimNetworkAuthoritySub = claimNetworkAuthority . payload . sub ;
133+ const nodeIdIss = tokenClaimNetworkAccess . payload . iss ;
134+ if ( nodeIdIss !== claimNetworkAuthoritySub ) {
135+ throw new claimsErrors . ErrorClaimsVerificationFailed (
136+ 'Issuer NodeIdEncoded does not match the expected network id' ,
137+ ) ;
138+ }
139+ const networkPublicKey = keysUtils . publicKeyFromNodeId ( issuerNodeId ) ;
140+ if ( ! tokenClaimNetworkAccess . verifyWithPublicKey ( networkPublicKey ) ) {
141+ throw new claimsErrors . ErrorClaimsVerificationFailed (
142+ 'Token was not signed by the issuer node' ,
143+ ) ;
144+ }
145+
146+ // Subject should be the target node and signed by it
147+ const targetNodeIdEncoded = nodesUtils . encodeNodeId ( subjectNodeId ) ;
148+ const nodeIdSub = tokenClaimNetworkAccess . payload . sub ;
149+ if ( nodeIdSub !== targetNodeIdEncoded ) {
150+ throw new claimsErrors . ErrorClaimsVerificationFailed (
151+ 'Subject NodeIdEncoded does not match the expected subject node' ,
152+ ) ;
153+ }
154+ const targetPublicKey = keysUtils . publicKeyFromNodeId ( subjectNodeId ) ;
155+
156+ if ( ! tokenClaimNetworkAccess . verifyWithPublicKey ( targetPublicKey ) ) {
157+ throw new claimsErrors . ErrorClaimsVerificationFailed (
158+ 'Token was not signed by the subject node' ,
159+ ) ;
160+ }
161+
162+ // Checking if the network name matches
163+ const networkName = tokenClaimNetworkAccess . payload . network ;
164+ if ( networkName !== network ) {
165+ throw new claimsErrors . ErrorClaimsVerificationFailed (
166+ 'Network name does not match the expected network' ,
167+ ) ;
168+ }
169+ }
170+
87171export {
88172 assertClaimNetworkAccess ,
89173 parseClaimNetworkAccess ,
90174 parseSignedClaimNetworkAccess ,
175+ verifyClaimNetworkAccess ,
91176} ;
92177
93178export type { ClaimNetworkAccess } ;
0 commit comments