Skip to content

Stage 9 — Secure the IA Node

How to complete this stage

In this stage you will enable secure mode and verify that authentication and authorisation are enforced. Restart the Secure Agent Graph with authentication, attribute resolution, and access control enabled. Before starting:

  • Stop the Secure Agent Graph process from Stage 7 (Ctrl+C).
  • Ensure ianode-access is still running (Stage 4).
  • Ensure authentication was verified successfully (Stage 5).

Open a terminal for this stage and leave it running.

Approach and rationale

This stage turns the graph from an open data store into a secure IA node.

From this point on:

  • Every request must present a valid identity token.
  • User attributes are resolved dynamically.
  • Attribute-based access control (ABAC) is enforced during queries.
  • Data visibility depends on who the user is.

This is the defining behaviour of an IA node.

9.1 Start Secure Agent Graph in secure mode

Start the IA Node with secure mode enabled.

Change to the Secure Agent Graph directory if needed:

cd ~/src/secure-agent-graph

Start the graph using the secure configuration:

USER_ATTRIBUTES_URL=http://localhost:8091 \
JWKS_URL="http://localhost:9229/${USER_POOL_ID}/.well-known/jwks.json" \
java \
-Dfile.encoding=UTF-8 \
-Dsun.stdout.encoding=UTF-8 \
-Dsun.stderr.encoding=UTF-8 \
-classpath "sag-server/target/classes:sag-system/target/classes:sag-docker/target/dependency/*" \
uk.gov.dbt.ndtp.secure.agent.graph.SecureAgentGraph \
--config sag-docker/mnt/config/dev-server-graphql.ttl
Expected behaviour
  • Enables JWT validation using the JWKS endpoint.
  • Enables attribute resolution via ianode-access.
  • Applies ABAC policies during query execution.
  • Enables the GraphQL API alongside SPARQL.
  • Listens on port 3030.

The configuration file dev-server-graphql.ttl activates all security features.

9.2 Confirm unauthenticated access is denied

From another terminal, attempt to upload RDF data without an authentication token:

curl -X POST \
  -T ~/src/secure-agent-graph/sag-docker/Test/data1.trig \
  -H "Content-type: text/trig" \
  http://localhost:3030/ds/upload
Expected behaviour
  • The request should fail (for example with HTTP 401 or 403).

This confirms:

  • Authentication is enforced.
  • Anonymous access is no longer allowed.

9.3 Upload data as an authenticated user

Fetch a token for an administrative user:

cd ~/src/ianode-access
source cognito-local/fetch_id_token.sh "test+user+admin@ndtp.co.uk"

Upload the RDF data again, this time including the token:

curl -X POST \
  -T ~/src/secure-agent-graph/sag-docker/Test/data1.trig \
  -H "Content-type: text/trig" \
  -H "Authorization: bearer $COGNITO_ID_TOKEN" \
  http://localhost:3030/ds/upload
Expected behaviour
  • Authenticates the request.
  • Allows the upload based on the user’s attributes.
  • Stores the data securely in the graph.

9.4 Query data as the first user

Query the dataset using SPARQL:

curl -X POST \
  -H "Authorization: bearer $COGNITO_ID_TOKEN" \
  -d "query=select ?s ?p ?o where { ?s ?p ?o . }" \
  http://localhost:3030/ds
Expected behaviour
  • The response includes data visible to this user according to ABAC policies.
  • Certain records or fields may be visible only to this user.

9.5 Compare behaviour with a different user

Fetch a token for a second user:

source cognito-local/fetch_id_token.sh "test+user@ndtp.co.uk"

Run the same SPARQL query again:

curl -X POST \
  -H "Authorization: bearer $COGNITO_ID_TOKEN" \
  -d "query=select ?s ?p ?o where { ?s ?p ?o . }" \
  http://localhost:3030/ds
Expected behaviour
  • The underlying dataset is the same.
  • The results differ.
  • Some fields or entities may be hidden according to ABAC policy.

This demonstrates attribute-based access control in action: data is filtered dynamically based on user attributes.

9.6 Query the graph using GraphQL

Run a GraphQL query using the same authenticated token:

curl -X POST \
  -H "Authorization: bearer $COGNITO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"query":"query { node(uri:\"http://example/person4321\"){id properties{predicate value}} }"}' \
  http://localhost:3030/ds/graphql
Operational notes

If authenticated requests fail, re-check:

  • JWKS_URL
  • OPENID_PROVIDER_URL
  • That the token was fetched after group membership was created
  • That ianode-access is still running

If both users see identical results, review ABAC policy configuration.

9.7 Checkpoint

At the end of this stage:

  • Unauthenticated requests are rejected.
  • Authenticated requests succeed.
  • Different users see different views of the same data.
  • Both SPARQL and GraphQL enforce the same access rules.

If all of these are true, the IA node is enforcing security correctly.

Next Steps (Optional)

Run Node: Kafka Ingestion