diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventContext.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventContext.java index d5c2ec1d04..a42847a34f 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventContext.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventContext.java @@ -52,13 +52,15 @@ public JwtEventContext( public void authorizationFailed( long traceId, long bindingId, - String identity) + String identity, + String reason) { JwtEventExFW extension = jwtEventExRW .wrap(extensionBuffer, 0, extensionBuffer.capacity()) .authorizationFailed(e -> e .typeId(AUTHORIZATION_FAILED.value()) .identity(identity) + .reason(reason) ) .build(); EventFW event = eventRW diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventFormatter.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventFormatter.java index c90d66f130..32a1c11875 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventFormatter.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtEventFormatter.java @@ -47,17 +47,20 @@ public String format( case AUTHORIZATION_FAILED: { JwtAuthorizationFailedExFW ex = extension.authorizationFailed(); - result = String.format("No active session found for token identity (%s).", identity(ex.identity())); + result = String.format("JWT token authorization failed for identity (%s). %s", + asString(ex.identity()), + asString(ex.reason()) + ); break; } } return result; } - private static String identity( - StringFW identity) + private static String asString( + StringFW stringFW) { - int length = identity.length(); - return length <= 0 ? "-" : identity.asString(); + String s = stringFW.asString(); + return s == null ? "" : s; } } diff --git a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java index d166b336c6..50ec6342bb 100644 --- a/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java +++ b/runtime/guard-jwt/src/main/java/io/aklivity/zilla/runtime/guard/jwt/internal/JwtGuardHandler.java @@ -128,6 +128,7 @@ public long reauthorize( { JwtSession session = null; String subject = null; + String reason = ""; authorize: try @@ -142,6 +143,7 @@ public long reauthorize( key == null || !Objects.equals(alg, key.getAlgorithm())) { + reason = "Invalid alg or key."; break authorize; } @@ -149,6 +151,7 @@ public long reauthorize( signature.setKey(key.getKey()); if (!signature.verifySignature()) { + reason = "Unable to verify key signature."; break authorize; } @@ -162,10 +165,15 @@ public long reauthorize( long now = Instant.now().toEpochMilli(); if (notBefore != null && now < notBefore.getValueInMillis() || - notAfter != null && now > notAfter.getValueInMillis() || - issuer == null || !issuer.equals(this.issuer) || + notAfter != null && now > notAfter.getValueInMillis()) + { + reason = "Token is expired."; + break authorize; + } + if (issuer == null || !issuer.equals(this.issuer) || audience == null || !audience.contains(this.audience)) { + reason = "Invalid issuer or audience."; break authorize; } @@ -191,11 +199,11 @@ public long reauthorize( } catch (JoseException | InvalidJwtException | MalformedClaimException ex) { - // not authorized + reason = ex.getMessage(); } if (session == null) { - event.authorizationFailed(traceId, bindingId, subject); + event.authorizationFailed(traceId, bindingId, subject, reason); } return session != null ? session.authorized : NOT_AUTHORIZED; } diff --git a/specs/guard-jwt.spec/src/main/resources/META-INF/zilla/jwt.idl b/specs/guard-jwt.spec/src/main/resources/META-INF/zilla/jwt.idl index 937f7f2cf7..81049bbab9 100644 --- a/specs/guard-jwt.spec/src/main/resources/META-INF/zilla/jwt.idl +++ b/specs/guard-jwt.spec/src/main/resources/META-INF/zilla/jwt.idl @@ -24,6 +24,7 @@ scope jwt struct JwtAuthorizationFailedEx extends core::stream::Extension { string8 identity; + string16 reason; } union JwtEventEx switch (JwtEventType) diff --git a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/event.yaml b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/event.yaml index afe098dc6b..e70027751e 100644 --- a/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/event.yaml +++ b/specs/guard-jwt.spec/src/main/scripts/io/aklivity/zilla/specs/guard/jwt/config/event.yaml @@ -24,7 +24,7 @@ telemetry: - qname: test.net0 id: guard.jwt.authorization.failed name: GUARD_JWT_AUTHORIZATION_FAILED - message: No active session found for token identity (user). + message: JWT token authorization failed for identity (user). Token is expired. guards: jwt0: type: jwt