This project is a simple example of how to use Spring Cloud Gateway to create an API Gateway for Swift APIs.
Three main components are used in the application:
-
Clients: The client is the entity that uses the APIs. The client is identified by an API key and once the it is authenticated, the API Gateway sets the
X-Customer-Custom-IDheader to the appropriate value. This header contains theBICof the client. -
Kong API Gateway: The Kong API Gateway is the entry point for all the APIs. It is responsible for routing the requests to the appropriate services. The API Gateway handles the authentication and authorization of the requests and sets the
X-Customer-Custom-IDheader to the appropriate value. Once the request is authenticated and authorized, Kong API Gateway forwards the request to the Spring Cloud Swift API gateway. -
Spring Cloud Swift API Gateway: The Spring Cloud Swift API Gateway is responsible for routing the requests to the appropriate Swift API. The application identifies the client using the
X-Customer-Custom-IDheader set by the Kong API Gateway. This identifications is done using a customPrincipalimplementation but any other authentication mechanism from Spring Security can be used.
The project is ready to use with the Swift Sandbox environment. The only thing you need to do is to create an account on the Swift Developer Portal and create an application to get the client ID and client secret.
-
Create an account on the Swift Developer Portal
-
Create an application on the Swift Developer Portal and select Pre-Validation API and GPI Tracker API options.
-
Get the
Consumer KeyandConsumer Secretfrom the application you created. -
Copy
.envfile to.env.localand fill in the values.
The application can be run using Docker. The following command shows how to run the application.
docker compose upThe Spring Boot application can be launched standalone. When the application is launched standalone, the HTTP header X-Consumer-Custom-ID is manually set in the postman collection.
To run the application standalone, go to the swift-api-gateway directory of the project and start the application.
cd swift-api-gateway
./mvnw spring-boot:runA postman collection is provided for testing. The postman collection contains the following requests:
- Bank A - Pre-Validation API
- Bank B - Pre-Validation API
- Bank B - GPI Tracker API
- Bank B - Stop and Recall API
The postman collection is located in the postman directory. You can import the collection into Postman and run the requests.
NOTE: For testing purposes, the Spring Cloud Swift API Gateway is also accessible directly. The postman collection contains a
Directfolder to test the Spring Cloud Swift API Gateway directly. In this case, theX-Consumer-Custom-IDheader must be set manually.
The configuration of the API Gateway is done using the application.yml file but Java configuration classes can be used as well.
For simplicity, all the configuration is but at the end of this document there are examples of how to configure the OAuth2 clients and the routes using Java configuration classes.
Three main configurations are required:
- Channel certificates
- OAuth2 clients
- Routes
NOTE: Please note that the route id, channel certificate and the OAuth2 client names are the same. The name is used to link all the configurations together.
The route is the entry point for the requests. The route is matched based on the predicates and the request is processed by the filters. The filters are used to modify the request before it is sent to the Swift API. The routes are configured using the spring.cloud.gateway.routes property.
The following example shows how to configure a route for the Pre-Validation API.
spring:
cloud:
gateway:
routes:
- id: bnkbbebb-pre-validation
uri: https://sandbox.swift.com
predicates:
- Path=/swift-preval/**
- Header=X-Consumer-Custom-ID,bnkbbebb
filters:
- RemoveRequestHeader=X-Consumer-Custom-ID
- AddRequestHeader=x-bic,swhqbebb
- TokenRelay=bnkbbebb-pre-validationIn this case, two predicates are used to route the request to the Pre-Validation API:
Path=/swift-preval/**: The request must start with the path/swift-preval/.Header=X-Consumer-Custom-ID,bnkbbebb: The request must have the headerX-Consumer-Custom-IDwith the valuebnkbbebb.
The request is processed by four filters:
RemoveRequestHeader=X-Consumer-Custom-ID: The headerX-Consumer-Custom-IDis removed from the request.AddRequestHeader=x-bic,swhqbebb: The headerx-bicis added to the request with the valueswhqbebb.TokenRelay=bnkbbebb-pre-validation: The OAuth2 token for the clientbnkbbebb-pre-validationis added to the request.
The SwiftSignatureGatewayFilterFactory gateway filter is responsible for signing the request before it is sent to the Swift API. The filter is configured using the SwiftSignature=<channel-certificate-name> property.
You can find and example of how to configure the filter in the Swift GPI Stop and Recall API route.
The channel certificates are used to authenticate the API Gateway to the Swift APIs. The certificates are stored in the src/main/resources/certificates directory and configured using the swift.channel-certificates property.
One keystore is created for each customer and each keystore can contain multiple certificates. Depending on the Swift API, a different certificate is used.
The following example shows how to configure the channel certificates for customer with BIC BNKBBEBB with two certificates: one for the Pre-Validation API and the other one for the GPI Tracker API.
swift:
channel-certificates:
bnkbbebb-pre-validation:
location: classpath:keystores/bnkabebb.jks
alias: pre-validation
password: Abcd1234
key-password: Abcd1234
bnkbbebb-gpi:
location: classpath:keystores/bnkbbebb.jks
alias: gpi-tracker
password: Abcd1234
key-password: Abcd1234The OAuth2 clients are used to authenticate the API Gateway to the Swift APIs. The OAuth2 clients are configured using the spring.security.oauth2.client.registration property.
The following example shows how to configure a client for the Pre-Validation API.
spring:
security:
oauth2:
client:
registration:
bnkbbebb-pre-validation:
client-id: pzGGIkKTn6ftiMh1vjXRYwjV0PMdyqQY
client-secret: 6Mn5AlnHzTRTSqZK
client-authentication-method: client_secret_basic
authorization-grant-type: urn:ietf:params:oauth:grant-type:jwt-bearer
scope: swift.preval!p
provider:
swift:
token-uri: https://sandbox.swift.com/oauth2/v1/tokenOAuth2 clients and routes can be configured using Java configuration classes.
The following example shows how to configure a OAuth2 client for the Pre-Validation API.
@Configuration
public class OAuth2ClientConfiguration {
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
ClientRegistration registration = ClientRegistration
.withRegistrationId("bnkbbebb-pre-validation")
.authorizationGrantType(AuthorizationGrantType.JWT_BEARER)
.clientId("pzGGIkKTn6ftiMh1vjXRYwjV0PMdyqQY")
.clientSecret("6Mn5AlnHzTRTSqZK")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.scope("swift.preval!p")
.tokenUri("https://sandbox.swift.com/oauth2/v1/token")
.build();
return new InMemoryClientRegistrationRepository(List.of(registration));
}
}Routes can be also configured using Java configuration classes.
@Configuration
public class RoutesConfiguration {
@Bean
public RouteLocator fluentApiRoutes(RouteLocatorBuilder builder) {
return builder.routes()
// Pre-Validation
.route("bnkbbebb-pre-validation",
r -> r.path("/swift-preval/**").and().header("X-Consumer-Custom-ID", "bnkbbebb")
.filters(f -> f.removeRequestHeader("X-Consumer-Custom-ID")
.addRequestHeader("x-bic", "swhqbebb")
.tokenRelay("bnkbbebb-pre-validation"))
.uri("https://sandbox.swift.com"))
// GPI tracker
.route("bnkbbebb-gpi-tracker",
r -> r.path("/gpi-tracker/**").and().header("X-Consumer-Custom-ID", "bnkbbebb")
.filters(f -> f.removeRequestHeader("X-Consumer-Custom-ID")
.rewritePath("/gpi-tracker/?(?<segment>.*)",
"/swift-apitracker/v6/payments/$\\{segment}/transactions")
.tokenRelay("bnkbbebb-gpi"))
.uri("https://sandbox.swift.com"))
.build();
}
}