From abfe8501efbc31ee4a16f330be04f8b64fb10f1b Mon Sep 17 00:00:00 2001 From: Jean-Pierre Portier Date: Wed, 24 Jul 2024 14:44:30 +0200 Subject: [PATCH] feature (Numbers/Webhooks): Support webhook calls validation for server template --- .../com/mycompany/app/numbers/Controller.java | 33 ++++++++++++++++++- .../src/main/resources/application.yaml | 3 ++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java b/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java index e312503..6d923c0 100644 --- a/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java +++ b/templates/server/src/main/java/com/mycompany/app/numbers/Controller.java @@ -3,12 +3,17 @@ import com.sinch.sdk.SinchClient; import com.sinch.sdk.domains.numbers.api.v1.WebHooksService; import com.sinch.sdk.domains.numbers.models.v1.webhooks.NumberEvent; +import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; @RestController("Numbers") public class Controller { @@ -16,6 +21,17 @@ public class Controller { private final SinchClient sinchClient; private final ServerBusinessLogic webhooksBusinessLogic; + /** + * The secret value used for webhook calls validation have to equals to the one configured at + * number property (HmacSecret). + * + * @see update + * function Javadoc + */ + @Value("${numbers.webhooks.secret}") + private String webhooksSecret; + @Autowired public Controller(SinchClient sinchClient, ServerBusinessLogic webhooksBusinessLogic) { this.sinchClient = sinchClient; @@ -26,10 +42,25 @@ public Controller(SinchClient sinchClient, ServerBusinessLogic webhooksBusinessL value = "/NumbersEvent", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity NumbersEvent(@RequestBody String body) { + public ResponseEntity NumbersEvent( + @RequestHeader Map headers, @RequestBody String body) { WebHooksService webhooks = sinchClient.numbers().v1().webhooks(); + // ensure valid authentication to handle request + var validAuth = + webhooks.validateAuthenticationHeader( + webhooksSecret, + // request headers + headers, + // request payload body + body); + + // token validation failed + if (!validAuth) { + throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); + } + // decode the request payload NumberEvent event = webhooks.parseEvent(body); diff --git a/templates/server/src/main/resources/application.yaml b/templates/server/src/main/resources/application.yaml index 1251ccf..8dccf7a 100644 --- a/templates/server/src/main/resources/application.yaml +++ b/templates/server/src/main/resources/application.yaml @@ -20,3 +20,6 @@ credentials: # - Voice application-api-key: application-api-secret: + +# Secret value set for Numbers webhooks calls validation +numbers.webhooks.secret: