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-ID
header to the appropriate value. This header contains theBIC
of 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-ID
header 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-ID
header set by the Kong API Gateway. This identifications is done using a customPrincipal
implementation 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 Key
andConsumer Secret
from the application you created. -
Copy
.env
file to.env.local
and fill in the values.
The application can be run using Docker. The following command shows how to run the application.
docker compose up
The 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:run
A 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
Direct
folder to test the Spring Cloud Swift API Gateway directly. In this case, theX-Consumer-Custom-ID
header 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-validation
In 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-ID
with the valuebnkbbebb
.
The request is processed by four filters:
RemoveRequestHeader=X-Consumer-Custom-ID
: The headerX-Consumer-Custom-ID
is removed from the request.AddRequestHeader=x-bic,swhqbebb
: The headerx-bic
is added to the request with the valueswhqbebb
.TokenRelay=bnkbbebb-pre-validation
: The OAuth2 token for the clientbnkbbebb-pre-validation
is 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: Abcd1234
The 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/token
OAuth2 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();
}
}