diff --git a/adapter-base/src/main/java/org/eclipse/hono/adapter/AbstractProtocolAdapterBase.java b/adapter-base/src/main/java/org/eclipse/hono/adapter/AbstractProtocolAdapterBase.java
index dfde5fafd0..054179a3fe 100644
--- a/adapter-base/src/main/java/org/eclipse/hono/adapter/AbstractProtocolAdapterBase.java
+++ b/adapter-base/src/main/java/org/eclipse/hono/adapter/AbstractProtocolAdapterBase.java
@@ -1062,6 +1062,7 @@ public static ConnectionAttemptOutcome getOutcome(final Throwable e) {
*
The adapter is disabled for the tenant that the client belongs to.
* The authenticated device or gateway is disabled or not registered.
* The tenant is disabled or does not exist.
+ * The authenticated device is not authorized anymore (e.g. device credentials expired).
*
*
* @param error The error to be checked.
@@ -1096,7 +1097,8 @@ protected Future isTerminalError(final Throwable error, final String de
return Future.succeededFuture(error instanceof AdapterDisabledException
|| error instanceof GatewayDisabledOrNotRegisteredException
- || error instanceof TenantDisabledOrNotRegisteredException);
+ || error instanceof TenantDisabledOrNotRegisteredException
+ || error instanceof AuthorizationException);
}
}
}
diff --git a/adapters/mqtt-base/src/main/java/org/eclipse/hono/adapter/mqtt/AbstractVertxBasedMqttProtocolAdapter.java b/adapters/mqtt-base/src/main/java/org/eclipse/hono/adapter/mqtt/AbstractVertxBasedMqttProtocolAdapter.java
index 13910a0fea..d69074db82 100644
--- a/adapters/mqtt-base/src/main/java/org/eclipse/hono/adapter/mqtt/AbstractVertxBasedMqttProtocolAdapter.java
+++ b/adapters/mqtt-base/src/main/java/org/eclipse/hono/adapter/mqtt/AbstractVertxBasedMqttProtocolAdapter.java
@@ -1310,6 +1310,7 @@ private Future checkTopic(final MqttContext context) {
private boolean disconnectOnExpired() {
if (authenticatedDevice != null && authenticatedDevice.expired()) {
+ log.debug("Credentials of device {} have expired - Disconnecting device.", authenticatedDevice.getDeviceId());
endpoint.close();
return true;
}
@@ -1318,7 +1319,7 @@ private boolean disconnectOnExpired() {
private Future checkExpiration(final MqttContext context) {
if (context.authenticatedDevice() != null && context.authenticatedDevice().expired()) {
- return Future.failedFuture(new MqttConnectionException(MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED));
+ return Future.failedFuture(new AuthorizationException(context.tenant(), "Device credentials expired.", null));
} else {
return Future.succeededFuture();
}
diff --git a/site/documentation/content/user-guide/amqp-adapter.md b/site/documentation/content/user-guide/amqp-adapter.md
index 3376ccf831..483ca0aa95 100644
--- a/site/documentation/content/user-guide/amqp-adapter.md
+++ b/site/documentation/content/user-guide/amqp-adapter.md
@@ -135,6 +135,7 @@ are listed below.
* The adapter is disabled for the tenant that the client belongs to.
* The authenticated device or gateway is disabled or not registered.
* The tenant is disabled or does not exist.
+* The authenticated device is not authorized anymore.
## Command-line Client
diff --git a/site/documentation/content/user-guide/mqtt-adapter.md b/site/documentation/content/user-guide/mqtt-adapter.md
index ffef593523..dba8562fef 100644
--- a/site/documentation/content/user-guide/mqtt-adapter.md
+++ b/site/documentation/content/user-guide/mqtt-adapter.md
@@ -856,13 +856,14 @@ The MQTT adapter publishes error messages with a UTF-8 encoded JSON payload cont
The error message's *code* field may contain the following HTTP status codes:
-| Code | Description |
-| :---- | :---------- |
-| *400* | Bad Request, the request cannot be processed. A possible reason for this is an invalid *PUBLISH* topic. |
-| *403* | Forbidden, the device's registration status cannot be asserted. |
-| *404* | Not Found, the device is disabled or does not exist. |
-| *413* | Request Entity Too Large, the request body exceeds the maximum supported size. |
-| *429* | Too Many Requests, the tenant's message limit for the current period is exceeded. |
+| Code | Description |
+| :---- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| *400* | Bad Request, the request cannot be processed. A possible reason for this is an invalid *PUBLISH* topic. |
+| *401* | Unauthorized, the device connection is not authorized (e.g. device credentials expired). |
+| *403* | Forbidden, the device's registration status cannot be asserted. |
+| *404* | Not Found, the device is disabled or does not exist. |
+| *413* | Request Entity Too Large, the request body exceeds the maximum supported size. |
+| *429* | Too Many Requests, the tenant's message limit for the current period is exceeded. |
| *503* | Service Unavailable, the request cannot be processed. Possible reasons for this include:- There is no consumer of telemetry data for the given tenant connected to Hono, or the consumer has not indicated that it may receive further messages (not giving credits).
- If the QoS level header is set to `1` (*at least once* semantics), the reason may be:
- The consumer has indicated that it didn't process the telemetry data.
- The consumer failed to indicate in time whether it has processed the telemetry data.
|
Example payload:
@@ -890,6 +891,7 @@ terminal error happens. The errors that are classified as terminal are listed be
* The adapter is disabled for the tenant that the client belongs to.
* The authenticated device or gateway is disabled or not registered.
* The tenant is disabled or does not exist.
+* The authenticated device is not authorized anymore (e.g. the connection expired).
{{% notice info %}}
When a terminal error occurs, the connection will always be closed irrespective of any *on-error* parameter or error