Chapters

19 CoAP Security: Implementation and Operations

coap
security

19.1 Start With the Decision

This section: Start With the Decision — CoAP is a compact request-and-response protocol for constrained devices.

CoAP is a compact request-and-response protocol for constrained devices. A token matches a response to its request. A CON retransmission repeats a message when its acknowledgment is missing; an application may separately retry an unanswered request. A resource is the named item the client asks about, and an error response explains why a request failed. A sound CoAP design can still fail when tokens or retries are loose. The team needs clear rules for each resource and error.

19.2 Route Overview

This section: Route Overview — This is part 1 of 2.

This is part 1 of 2. Continue with CoAP Security: CON and NON Trade-Offs.

19.3 Part Objectives

This section: Part Objectives

  • Test coap implementation patterns with a concrete scenario and pass criteria.
  • Validate troubleshooting common issues with a concrete scenario and pass criteria.

19.4 Start With the Situation

This section: Start With the Situation — The security mode and application fit are clear, but a deployment still fails if tokens, retransmissions, resources, or error responses are handled loosely.

The security mode and application fit are clear, but a deployment still fails if tokens, retransmissions, resources, or error responses are handled loosely. The team now turns the design into bounded implementation and operating checks.

19.5 Overview

This section: Overview — This route applies implementation patterns, practical resources, response-code tools, debugging records, and common-failure controls.

This route applies implementation patterns, practical resources, response-code tools, debugging records, and common-failure controls.

This is part 2 of 2. Review CoAP Security: Protection and Application Fit when you need the first route.

19.6 Learning Objectives

This section: Learning Objectives

By the end of this chapter, you will be able to:

  • implement CoAP token, retransmission, and resource patterns
  • prevent open-server reflection and retry failures
  • build an operational debugging record from response evidence

19.7 Chapter Roadmap

This section: Chapter Roadmap

  • Start With the Situation
  • Overview
  • CoAP Implementation Patterns
  • Practical CoAP Implementation Resources
  • Checkpoint: Operational Debugging
  • Try It: CoAP Response Code Reference
  • Troubleshooting Common Issues
  • Common Problems and Solutions
  • Common Pitfalls
  • Common Pitfall: CoAP Message Size Exceeds MTU
  • Common Pitfall: Misusing CON vs NON Message Types

19.8 CoAP Implementation Patterns

This section: CoAP Implementation Patterns — A CoAP implementation keeps resource intent, message delivery, and observation continuity as distinct parts of the same exchange.

A CoAP implementation keeps resource intent, message delivery, and observation continuity as distinct parts of the same exchange. GET, POST, PUT, and DELETE describe operations on resources rather than the delivery policy. CON and NON select exchange behavior, while Token and Observe state preserve the application relationship. A performance comparison must therefore account for the combined pattern instead of treating a short header as the entire implementation.

An implementation combines three contracts that are easy to learn separately but must cooperate in code. Inspect Figure 19.1 to connect message delivery, REST operations, and long-lived observation before comparing performance.

Diagram showing CoAP message types (CON, NON, ACK, RST), RESTful methods (GET, POST, PUT, DELETE), and the Observe pattern for push notifications with sequence numbers
Figure 19.1: CoAP Message Types, RESTful Methods, and Observe Pattern Overview

In Figure 19.1, begin with the message types that control delivery behavior, move to GET, POST, PUT, and DELETE as operations on resources, and finish with Observe registration plus ordered notifications. A stack must keep those layers distinct: the method states intent, the message type chooses an exchange policy, and the Token and Observe state preserve application continuity. The performance comparison below then evaluates the cost of that combined pattern.

19.8.1 CoAP vs HTTP vs MQTT: Performance Comparison

Illustrative application-header comparison (20-byte reading; CoAP over UDP, HTTP/1.1 and MQTT over TCP; transport bytes, security, topic/URI, and options excluded):

Read these points as one illustrative scenario: CoAP over UDP has a 4-byte fixed header, 24 bytes with this payload, and 16.7% application-header share; HTTP/1.1 over TCP assumes 200 bytes of headers, 220 bytes total, and 90.9%; MQTT over TCP assumes only its 2-byte minimum fixed header, 22 bytes total, and 9.1%. Actual requests add fields and transport costs; latency depends on the network and connection state.

  • CoAP over UDP: 4-byte fixed header + 20-byte payload = 24 bytes; 4/24 = 16.7% application-header share
  • HTTP/1.1 over TCP: assumed 200-byte headers + 20-byte payload = 220 bytes; 200/220 = 90.9% header share
  • MQTT over TCP: 2-byte minimum fixed header + 20-byte payload = 22 bytes; 2/22 = 9.1% fixed-header share (a PUBLISH needs a topic and may need other fields)

Energy Consumption (24 hours, readings every 30s):

Read these points as one illustrative radio-energy model with assumed costs per message: CoAP: 2,880 messages/day × 153 mJ = 122.4 mWh/day; HTTP: × 190 mJ = 152.0 mWh/day (24.2% more message energy); MQTT: × 163 mJ = 130.4 mWh/day (6.5% more message energy). These figures do not predict total device battery life.

  • CoAP assumption: 2,880 messages/day, 153 mJ per message, 122.4 mWh/day of message energy
  • HTTP assumption: 2,880 messages/day, 190 mJ per message, 152.0 mWh/day (24.2% more than CoAP)
  • MQTT assumption: 2,880 messages/day, 163 mJ per message, 130.4 mWh/day (6.5% more than CoAP)
Practical CoAP Implementation Resources

Official Libraries and Tools:

Compare the Python and ESP32 implementation resources before choosing a library for the device.

Testing and Debugging Tools:

Keep one practical point in view: coap-client (libcoap): Command-line CoAP client for testing.

  • coap-client (libcoap): Command-line CoAP client for testing

    # GET request
    coap-client -m get coap://localhost/temperature
    
    # POST with payload
    coap-client -m post coap://localhost/sensor -e "22.5"
    
    # Observe resource
    coap-client -m get -s 60 coap://localhost/temperature
  • Copper (Cu): Firefox/Chrome plugin for CoAP browsing (deprecated but useful for learning)

  • Wireshark: CoAP dissector included (filter: coap)

  • nRF Connect CoAP: Mobile app for testing CoAP servers

Example Implementation Patterns:

Pattern 1: Sensor Reading (NON message)

Sensor → Gateway:  CON GET /temperature
Gateway → Sensor:  ACK 2.05 Content
                   Payload: 22.5°C

Overhead: 2 messages, ~50 bytes total
Latency: 1 RTT (~20-50ms on local network)
Reliability: Guaranteed (CON requires ACK)

Pattern 2: Frequent Updates (Observe)

Client → Server:   CON GET /temperature, Observe: 0
Server → Client:   ACK 2.05 Content, Observe: 12
                   Initial value: 22.5°C

[30 seconds later]
Server → Client:   CON 2.05 Content, Observe: 13
                   Updated value: 23.1°C

[30 seconds later]
Server → Client:   CON 2.05 Content, Observe: 14
                   Updated value: 22.9°C

Overhead: 1 subscribe + N notifications
Battery savings: Avoid polling every 30s

Pattern 3: Multicast Discovery

Client → FF02::FD: NON GET /.well-known/core
Device1 → Client:  NON 2.05 Content
                   </temperature>,</humidity>
Device2 → Client:  NON 2.05 Content
                   </pressure>,</light>

Use case: Discover all CoAP devices on local network
Result: List of available resources from all devices

This section:

Broker Bex, Messaging and broker domain expertCheckpoint: Operational Debugging

You now know:

  • Observe clients must map each 0-8 byte token to the resource being observed, or concurrent notifications can be misattributed.
  • CON retransmission uses ACK_TIMEOUT 2 s, ACK_RANDOM_FACTOR 1.5, and MAX_RETRANSMIT 4 by default: 45 s maximum span from first to last send, and 93 s maximum wait for ACK or RST.
  • Response code classes divide the first digit by role: 2.xx success, 4.xx client error, and 5.xx server error.

This section:

19.8.2 CoAP Response Code Categories

  • Success (2.xx): 2.01-2.05, meaning the request succeeded. Examples: 2.05 Content for a successful GET and 2.04 Changed for a successful PUT.
  • Client Error (4.xx): 4.00-4.15, meaning the client made an error. Examples: 4.04 Not Found for a bad URI and 4.01 Unauthorized when authentication is required.
  • Server Error (5.xx): 5.00-5.05, meaning the server failed. Examples: 5.00 Internal Server Error and 5.03 Service Unavailable.
Try It: CoAP Response Code Reference

Look up CoAP response codes interactively. Select a category or type a code to see its meaning, HTTP equivalent, and when you would encounter it in practice.

The troubleshooting material below reuses the same pattern: identify the failed layer first, then choose the smallest fix that matches that layer.

19.8.3 Hands-On Learning Resources

Interactive Tutorials:

  1. Eclipse Californium CoAP Demo Server: coap://californium.eclipseprojects.io:5683/

    • Try: coap-client -m get coap://californium.eclipseprojects.io:5683/.well-known/core
  2. CoAP.me Public Test Server: coap://coap.me:5683/

    • Test GET, POST, PUT, DELETE without setting up your own server

Code Examples:

Start with the CoAP examples repository, then use the aiocoap tour to follow a Python implementation.

Video Tutorials:

  • Building IoT with CoAP - IoT Developer Conference
  • CoAP Deep Dive - Eclipse Foundation
  • Constrained Devices and CoAP - IETF Educational Series

19.9 Troubleshooting Common Issues

This section: Troubleshooting Common Issues

Common Problems and Solutions

A CoAP failure needs a diagnosis at the boundary where the observed behavior stops matching the request. A timeout can involve packet loss, acknowledgement behavior, or an unavailable endpoint rather than a wrong resource path. A failed DTLS handshake instead calls for key or certificate checks before resource handling can succeed. Response codes then distinguish a missing resource from a method that the resource does not support.

  • Request times out: UDP packet loss or no ACK. Increase retransmission timeout, use CON messages instead of NON, and check network quality.
  • Confirmable message never acknowledged: Server down or wrong endpoint. Verify the server is running and confirm the CoAP URI format coap://host:port/path.
  • Block transfer fails mid-stream: MTU too large or packet fragmentation. Reduce block size from 1024 bytes to 512 or 256 and check network MTU settings.
  • Observe notifications stop: Server crashed or network partition. Re-establish the observe relationship and add client-side timeout detection.
  • Multicast discovery finds no devices: Wrong multicast address or routing. Use FF02::FD for link-local or FF05::FD for site-local and check IPv6 multicast routing.
  • DTLS handshake fails: PSK mismatch or certificate error. Verify pre-shared keys match exactly and check certificate validity for certificate mode.
  • Response code 4.04 Not Found: Wrong resource path. Check URI case sensitivity and verify the resource exists on the server.
  • Response code 4.05 Method Not Allowed: Unsupported method on the resource. Confirm that the resource supports GET, POST, PUT, or DELETE as expected.

Debug Checklist:

  • Connection and Discovery Issues:

    • Verify server is reachable on UDP port 5683 (or 5684 for DTLS)
    • Test with ping to confirm basic network connectivity
    • Check firewall allows UDP traffic on CoAP port
    • For multicast: verify IPv6 multicast is enabled on network interface
    • Use CoAP client tool to test server response (e.g., coap-client, libcoap)
  • Request/Response Problems:

    • Confirm CoAP URI format: coap://server-ip:5683/resource/path
    • Check message type (CON requires ACK, NON does not)
    • Verify token in response matches token in request
    • Review response code (2.xx success, 4.xx client error, 5.xx server error)
    • Monitor retransmission attempts (exponential backoff 2s, 4s, 8s, 16s)
  • Observe and Block Transfer Issues:

    • For Observe: confirm observe option set in request (observe=0)
    • Check server sends notifications with observe option and increasing sequence numbers
    • For Block transfers: verify block size negotiation (Block1/Block2 options)
    • Monitor block number sequence (must be consecutive)
    • Test smaller block sizes if large transfers fail

Read these points as one sequence: start with Performance and Reliability; then measure UDP packet loss and its effect on CoAP retries and latency; then check network latency, server capacity, deduplication, and congestion.

  • Performance and Reliability:

    • Measure UDP packet loss and whether it causes unacceptable CoAP retries or delay for this workload.
    • Monitor network latency (affects retransmission timing)
    • Verify server can handle request rate (no overload)
    • Review message deduplication (servers drop duplicate message IDs)
    • Check for network congestion (CoAP includes congestion control)
  • Security (DTLS) Issues:

    • Verify DTLS version compatibility (DTLSv1.2 recommended)
    • Check pre-shared key encoding (must be exact byte match)
    • For certificates: verify CA chain and server certificate validity
    • Monitor DTLS session timeouts and renegotiation
    • Test with plain CoAP first, then add DTLS layer

Common Error Codes:

  • 2.01 Created: Resource successfully created (POST response)
  • 2.02 Deleted: Resource successfully deleted
  • 2.03 Valid: Resource still valid (cache validation)
  • 2.04 Changed: Resource successfully updated (PUT response)
  • 2.05 Content: Resource content returned (GET response)
  • 4.00 Bad Request: Malformed request or invalid options
  • 4.01 Unauthorized: Authentication required or failed
  • 4.04 Not Found: Resource does not exist
  • 4.05 Method Not Allowed: HTTP method not supported on resource
  • 5.00 Internal Server Error: Server encountered error processing request
  • 5.03 Service Unavailable: Server temporarily unable to handle request

Tools for Debugging:

  • libcoap tools: coap-client and coap-server for testing
  • Copper (Cu): Firefox/Chrome plugin for CoAP browsing (deprecated but useful)
  • Wireshark: CoAP dissector for packet analysis (filter: coap)
  • tcpdump: Capture UDP packets (tcpdump -i any port 5683 -vv)
  • Eclipse Californium: Java-based CoAP library with extensive logging
  • aiocoap: Python library with good debugging output

19.10 Common Pitfalls

This section: Common Pitfalls

Common Pitfall: CoAP Message Size Exceeds MTU

A CoAP payload that works on local Wi-Fi can fail on a constrained network when its transfer exceeds the available packet budget. Fragment loss can prevent the receiver from reconstructing the complete message even though other fragments arrived. Block-wise transfer supports larger configurations, firmware, and files without treating them as one oversized payload. The acceptance test must use the actual constrained path because Wi-Fi success does not establish that path’s behavior.

The mistake: Sending CoAP payloads larger than the network MTU (typically 1280 bytes for IPv6, often much smaller for constrained networks like 6LoWPAN with 127-byte frames), causing silent packet drops or fragmentation failures.

Symptoms:

  • Large GET responses never arrive at the client
  • PUT/POST requests with substantial payloads fail intermittently
  • Works on local Wi-Fi but fails over 6LoWPAN or constrained networks
  • Wireshark shows fragmented packets but no reassembled response

Why it happens: CoAP runs over UDP, which doesn’t handle fragmentation gracefully:

  • IPv6 minimum MTU: 1280 bytes, but CoAP payload should be much smaller
  • 6LoWPAN frame: 127 bytes maximum, ~80 bytes after headers
  • UDP fragmentation: If any fragment is lost, entire message is lost
  • No automatic retransmission of individual fragments

The fix:

# Use CoAP Block-wise Transfer (RFC 7959) for large payloads
from aiocoap import Message, Context
from aiocoap.numbers.codes import GET

async def get_large_resource(uri):
    context = await Context.create_client_context()

    # Request with Block2 option - library handles chunking
    request = Message(code=GET, uri=uri)
    # Block size: 64 bytes (szx=2), 128 bytes (szx=3), 256 bytes (szx=4)
    # Smaller blocks = more round trips but works on constrained networks

    response = await context.request(request).response
    return response.payload  # Library reassembles blocks automatically
// Embedded C: Check payload size before sending
#define COAP_MAX_PAYLOAD_6LOWPAN  64   // Safe for 802.15.4
#define COAP_MAX_PAYLOAD_UDP      1024 // Safe for most networks

size_t max_payload = is_constrained_network() ?
    COAP_MAX_PAYLOAD_6LOWPAN : COAP_MAX_PAYLOAD_UDP;

if (payload_len > max_payload) {
    // Use Block1 (request) or Block2 (response) transfer
    return coap_send_blockwise(payload, payload_len, max_payload);
}

Prevention: Design payloads to fit in 64-128 bytes for 6LoWPAN networks. Use Block-wise Transfer for firmware updates, large configurations, or file downloads. Test on the actual constrained network, not just Wi-Fi.

Common Pitfall: Misusing CON vs NON Message Types

A battery sensor needs different exchange policies for routine measurements and important control messages. Repeated confirmable exchanges add acknowledgements and retry work that may be unnecessary when the next reading replaces a missed one. Non-confirmable delivery does not supply the failure-detection behavior required by the command path in this example. A hybrid policy ties confirmation to message importance instead of treating telemetry, alarms, and device commands as equivalent.

The mistake: Using Confirmable (CON) messages for all communications because “reliability is important,” leading to excessive battery drain and network congestion, or using Non-Confirmable (NON) for critical commands where delivery must be guaranteed.

Symptoms:

  • Battery-powered sensors lasting weeks instead of years
  • Unnecessary retransmission storms when network is lossy
  • Commands occasionally not reaching actuators (lights, locks)
  • High latency due to waiting for ACKs on every message

Why it happens: Developers often misunderstand the trade-offs:

  • CON overuse: HTTP background makes developers expect reliability for everything
  • NON overuse: Trying to maximize battery life without considering message importance
  • No hybrid strategy: Treating all messages the same regardless of criticality

The fix:

from aiocoap import Message, Context
from aiocoap.numbers.codes import GET, PUT
from aiocoap.numbers.types import CON, NON

# NON for periodic telemetry (loss acceptable, battery critical)
async def send_temperature_reading(temp):
    request = Message(
        code=PUT,
        mtype=NON,  # Fire-and-forget, ~5x better battery life
        uri='coap://server/sensors/temp',
        payload=f'{temp}'.encode()
    )
    await context.request(request).response

# CON for critical commands (must know if it worked)
async def unlock_door():
    request = Message(
        code=PUT,
        mtype=CON,  # Need acknowledgment for security
        uri='coap://door/lock',
        payload=b'unlock'
    )
    try:
        response = await context.request(request).response
        return response.code.is_successful()
    except Exception:
        return False  # Command failed, alert user

# CON for configuration changes (must be applied)
async def update_reporting_interval(seconds):
    request = Message(
        code=PUT,
        mtype=CON,  # Config must be confirmed
        uri='coap://sensor/config/interval',
        payload=str(seconds).encode()
    )
    return await context.request(request).response

Decision matrix:

  • Periodic sensor readings: Use NON for routine telemetry; do not use CON.
  • Alert or alarm notifications: Use CON so the receiver must acknowledge delivery.
  • Device commands (on/off): Use CON because actuation commands need confirmation.
  • Configuration updates: Use CON so applied settings are confirmed.
  • Status queries: Depends on how critical the response is.
  • Firmware chunks: Use CON with Block2 acknowledgements.

Prevention: Default to NON for periodic telemetry. Use CON only for commands, configurations, and alerts. Implement a message priority system that selects type based on criticality.

19.11 Continue to the Next Part

This section: Continue to the Next Part — Carry this evidence into CoAP Security: CON and NON Trade-Offs, which begins with Try It: CON vs NON Message Type Advisor.

Carry this evidence into CoAP Security: CON and NON Trade-Offs, which begins with Try It: CON vs NON Message Type Advisor.

Find help

3 reviewed answers.

Where should I start in a module?

Open the module page from the sidebar to see its chapters in order. Use the module map to return to a topic you need.

Modules and paths

Reviewed

What can I try when a project does not work?

Check the symptom, then work through the diagnostic steps. Keep the error message and the smallest example that reproduces it.

When you are stuck

Reviewed

How do interactive examples work?

Use the interactive guide to check how examples and simulations work before changing your project.

Interactive examples guide

Reviewed