sapse/approuter

By sapse

Updated 28 days ago

Image
7

10K+

sapse/approuter

Overview

When a business application consists of several different apps (microservices), the application router is used to provide a single entry point to that business application. It has the responsibility to:

  • Dispatch requests to backend microservices (reverse proxy)
  • Authenticate users
  • Serve static content

Application router overview diagram

Let's think of the different apps (microservices) as destinations to which the incoming request will be forwarded. The rules that determine which request should be forwarded to which destination are called routes. For every destination there can be more than one route. You may read more on the concept of routes later in this document. If the backend microservices require authentication, the application router can be configured to authenticate the users and propagate the user information. Again by using routes, the application router can serve static content.

The application router is designed to work in XS Advanced - Cloud Foundry and XS OnPremise Runtime.

A calling component accesses a target service by means of the application router only if there is no JWT token available, for example, if a user invokes the application from a Web browser. If a JWT token is already available, for example, because the user has already been authenticated, or the calling component uses a JWT token for its own OAuth client, the calling component calls the target service directly; it does not need to use the application router.

Note that the application router does not hide the backend microservices in any way. They are still directly accessible bypassing the application router. So the backend microservices must protect all their endpoints by validating the JWT token and implementing proper scope checks. Network isolation is not provided currently by the platform.

Deploying a business application with microservices

For example we can have a business application that has the following structure:

+-- manifest.yml
+-- manifest-op.yml
|  +-- microservice-1
|  | +-- ...
|  | +-- ...
|  +-- microservice-2
|  | +-- ...
|  | +-- ...
|  +-- web
|  | +-- ...
|  | +-- ...

The manifest.yml file is used to deploy the business application on Cloud Foundry and the manifest-op.yml - on the XS OnPremise Runtime. These files should describe all the microservices for that business application.

Folders are used to isolate the different microservices. Let's assume that the application router is the microservice in the web folder (every business application has its own application router). Here is how we can include the application router:

  • Manually create the node_modules folder in the web folder.
  • Copy and paste the folder that contains the self-contained application router into node_modules. In this example the name of that folder is @sap/approuter, see the start script in the package.json below.
  • Check the version of the application router you just copied.
  • Create a package.json file in web with content similar to the following and replace the version's value with the version of your application router:
{
    "name": "hello-world-approuter",
    "dependencies": {
       "@sap/approuter": "2.6.1"
    },
    "scripts": {
        "start": "node node_modules/@sap/approuter/approuter.js"
    }
}

In order to use the application router you don't have to write any JavaScript code. Only some configurations have to be provided in the web folder. Here is a complete example:

+-- web
| +-- package.json
| +-- xs-app.json
| +-- resources
| | +-- hello-world.html
| | +-- my-page.html
| +-- node_modules
| |   +-- ...
| +-- default-env.json
| +-- default-services.json

The web folder contains the package.json, node_modules, some configuration files used by the application router, and static resources to be served. You can read more about the configurations later in this document.

By default, the application router runs on port 5000 (if started locally) or it takes the port from the PORT environment variable.

Working directory

The working directory contains configuration files that the application router needs and static resources that can be served at runtime. In the previous example, the web folder is the working directory. By default the current directory is the working directory. It is possible to configure it during start up of the application router with the following command line argument:

node approuter.js -w <working-dir>

Application router will abort if the working directory does not contain xs-app.json file.

Configurations

The application router makes use of the following configurations:

  • Main configuration - this is the xs-app.json file. This file is mandatory and contains the main configurations of the application router.

  • UAA configuration - the application router reads this configuration either from the VCAP_SERVICES environment variable (when deployed on Cloud Foundry or XS Advanced OnPremise Runtime) or from the default-services.json file (when running locally). Refer to the documentation of the @sap/xsenv package for more details.

  • Configurations from the environment - these configurations are either read from the application router's environment (when deployed on Cloud Foundry or XS Advanced OnPremise Runtime) or from the default-env.json file (when running locally). Refer to the documentation of the @sap/xsenv package for more details. The environment variables that the application router takes into account are:

ConfigurationEnvironment variableDescription
UAA service nameUAA_SERVICE_NAMEContains the name of the UAA service to be used.
DestinationsdestinationsProvides information about the available destinations.
Additional headershttpHeadersProvides headers that the application router will return to the client in its responses.
Additional cookiesCOOKIESProvides cookies that the application router will return to the client in its responses. Currently only SameSite cookie is supported.
PluginspluginsA plugin is just like a route except that you can't configure some inner properties.
Session timeoutSESSION_TIMEOUTPositive integer representing the session timeout in minutes. The default timeout is 15 minutes.
X-Frame-OptionsSEND_XFRAMEOPTIONS, httpHeadersConfiguration for the X-Frame-Options header value.
Allowlist serviceCJ_PROTECT_WHITELISTConfiguration for the allowlist that is preventing clickjack attacks.
Web Sockets origins allowlistWS_ALLOWED_ORIGINSAn allowlist configuration that is used for verifying the Origin header of the initial upgrade request when establishing a web socket connection.
JWT Token refreshJWT_REFRESHThe time in minutes before a JWT token expires and the application router should trigger a token refresh routine.
Incoming connection timeoutINCOMING_CONNECTION_TIMEOUTMaximum time in milliseconds for a client connection. After that time the connection is closed. If set to 0, the timeout is disabled. Default: 120000 (2 min)
Tenant host patternTENANT_HOST_PATTERNString containing a regular expression with a capturing group. The request host is matched against this regular expression. The value of the first capturing group is used as tenant id.
Destination host patternDESTINATION_HOST_PATTERNString containing a regular expression with a capturing group. The request host is matched against this regular expression. The value of the capturing group is used as destination name.
CompressionCOMPRESSIONConfiguration regarding compressing resources before responding to the client.
Secure flag of session cookieSECURE_SESSION_COOKIECan be set to true or false. By default, the Secure flag of the session cookie is set depending on the environment the application router runs in. For example, when application router is behind a router (Cloud Foundry's router or SAP Web Dispatcher) that is configured to serve HTTPS traffic, then this flag will be present. During local development the flag is not set. This environment variable can be used to enforce setting or omitting the Secure flag. Note: If the Secure flag is enforced, the application router will reject requests sent over unencrypted connection (http).
Trusted CA certificatesXS_CACERT_PATHList of files paths with trusted CA certificates used for outbound https connections (UAA, destinations, etc.). File paths are separated by path.delimiter. If this is omitted, several well known "root" CAs (like VeriSign) will be used. This variable is set automatically by XSA On-premise runtime.
Reject untrusted certificatesNODE_TLS_REJECT_UNAUTHORIZEDBy default an outbound https connection is terminated if the remote end does not provide a trusted certificate. This check can be disabled by setting NODE_TLS_REJECT_UNAUTHORIZED to 0. This is a built-in feature of Node.js. Note: Do not use this in production as it compromises security!
External reverse proxy flagEXTERNAL_REVERSE_PROXYBoolean value that indicates the use of application router behind an external reverse proxy (outside of Cloud Foundry domain)
Skip client credentials tokens load on startSKIP_CLIENT_CREDENTIALS_TOKENS_LOADBoolean value that indicates that no client credentials tokens should be created during the application router start phase
Cross-Origin Resource SharingCORSConfiguration regarding CORS enablement.
Preserve URL fragmentPRESERVE_FRAGMENTWhen set to true or not set, fragment part of the URL provided during first request of not logged-in user to protected route will be preserved, and after login flow user is redirected to original URL including fragment part. However, this may break programmatic access to Approuter (e.g. e2e tests), since it introduces change in login flow, which is incompatible with Approuter version 4.0.1 and earlier. Setting value to false makes login flow backward compatible, however will not take fragment part of the URL into account.
Direct Routing URI PatternsDIRECT_ROUTING_URI_PATTERNSConfiguration for direct routing URI patterns.
NodeJS Minimal Logging LevelCF_NODEJS_LOGGING_LEVELConfiguration for NodeJS minimal logging level.
Dynamic Identity ProviderDYNAMIC_IDENTITY_PROVIDERConfiguration for dynamic identity provider.
Backend Cookies SecretBACKEND_COOKIES_SECRETSecret that is used to encrypt backend session cookies in service to Application Router flow. Should be set in case multiple instances of Application Router are used. By default a random sequence of characters is used.
Service to Application RouterSERVICE_2_APPROUTERIf true, when the SAP Passport header is received from the application router, it will be transferred without modification to the backend application.
Client certificate header nameCLIENT_CERTIFICATE_HEADER_NAMEWhen set application router will use this header name to get the client certificate from the request header in subscription callback. If not provided the default header name x-forwarded-client-cert is used.
Server Keep AliveSERVER_KEEP_ALIVEserver keep alive timeout (positive integer in milliseconds).
Minimum Token ValidityMINIMUM_TOKEN_VALIDITYpositive integer in seconds. When set, approuter will check that the token returned from the authorization service has an expiration time higher than the minimum token validity value.

Note: all those environment variables are optional.

Destinations

The destinations configuration can be provided by the destinations environment variable or by destination service. There has to be a destination for every single app (microservice) that is a part of the business application.

Environment destinations

The destinations configuration is an array of objects. Here are the properties that a destination can have:

PropertyTypeOptionalDescription
nameStringA unique alphanumeric identifier of the destination.
urlStringURL of the app (microservice).
proxyHostStringxThe host of the proxy server used in case the request should go through a proxy to reach the destination.
proxyPortStringxThe port of the proxy server used in case the request should go through a proxy to reach the destination.
forwardAuthTokenBooleanxIf true, the OAuth token is sent to the destination. The default value is false. This token contains user identity, scopes and other attributes. It is signed by the UAA or IAS service, so it can be used for user authentication and authorization with backend services.
strictSSLBooleanxConfigures whether the application router should reject untrusted certificates. The default value is true.
Note: Do not use this in production as it compromises security!
timeoutNumberxPositive integer representing the maximum wait time for a response (in milliseconds) from the destination. Default is 30000ms.
setXForwardedHeadersBooleanxIf true , the application router adds X-Forwarded-(Host, Path, Proto) headers to the backend request.Default value is true.
proxyTypeStringxConfigures whether the destination is used to access applications in on-premise networks or on public Internet. Possible value: OnPremise. if the property is not provided, it is assumed that it is a public Internet access.
Note: if OnPremise value is set, binding to SAP Cloud Platform connectivity service is required, and forwardAuthToken property should not be set.

Note: The timeout specified will also apply to the destination's logout path or service's logout path (if you have set one).
Note:proxyHost and proxyPort are optional, but if one of them is defined, then the other one becomes mandatory.

Sample content of the destinations environment variable:

[
  {
    "name" : "ui5",
    "url" : "https://ui5.sap.com",
    "proxyHost" : "proxy",
    "proxyPort" : "8080",
    "forwardAuthToken" : false,
    "timeout" : 1200
  }
]

It is also possible to include the destinations in the manifest.yml and manifest-op.yml files:

- name: node-hello-world
  memory: 100M
  path: web
  env:
    destinations: >
                  [
                    {"name":"ui5", "url":"https://ui5.sap.com"}
                  ]

Destination service

Destination configuration can also be read from destination service .
Here are the Approuter limitations to destination properties configuration from destination service :

PropertyAdditional PropertyDescription
Typeonly HTTP supported.
AuthenticationAll authentication types are supported.
Note:User and Password are mandatory if the authentication type is basic authentication.
Note: if the authentication type set to principal propagation the ProxyType have to be on-premise.
Note: if the authentication type set to OAuth2SAMLBearerAssertion, uaa.user scope in xs-security.json is required.
ProxyTypeSupported proxy type : on-premise, internet, private-link.
Note: if ProxyType set to on-premise, binding to SAP Cloud Platform connectivity service is required.
Note: The private-link proxy type is a beta feature and is not meant for productive use. It is only available in Azure landscapes.
Optional additional properties:
PropertyAdditional PropertyDescription
HTML5.ForwardAuthTokenxIf true the OAuth token will be sent to the destination. The default value is false. This token contains user identity, scopes and other attributes. It is signed by the UAA so it can be used for user authentication and authorization with backend services.
Note: if ProxyType set to on-premise, ForwardAuthToken property should not be set.
Note: if Authentication type is other than NoAuthentication, ForwardAuthToken property should not be set.
HTML5.TimeoutxPositive integer representing the maximum wait time for a response (in milliseconds) from the destination. Default is 30000ms.Note: The timeout specified will also apply to the destination's logout path or service's logout path (if you have set one).
HTML5.PreserveHostHeaderxIf true , the application router preserves the host header in the backend request.
This is expected by some back-end systems like AS ABAP, which do not process x-forwarded-* headers.
HTML5.DynamicDestinationxIf true , the application router allows to use this destination dynamically on host or path level.
HTML5.SetXForwardedHeadersxIf true , the application router adds X-Forwarded-(Host, Path, Proto) headers to the backend request.Default value is true.
sap-clientxIf provided, the application router propagates the sap-client and its value as a header in the backend request.
This is expected by ABAP back-end systems.
URL.headers.<header-name>xIf provided, the application router propagates this special attribute in the destination as the header. The application router can get the headers list from the destination API. Existing request headers are not overwritten.


Note:

  • In case destination with the same name is defined both in environment destination and destination service, the destination configuration will load from the environment.
  • Destinations on destination service instance level are supported.
  • Only destination client certificates of type p12 are supported.
  • Only destination trust certificates of the type privacy-enhanced mail (PEM) are supported.
UAA configuration

The User Account and Authentication (UAA) server is responsible for user authentication. In Cloud Foundry and XS OnPremise Runtime a service is created for this configuration and by using the standard service binding mechanism the content of this configuration is available in the VCAP_SERVICES environment variable.
Note: The service should have xsuaa in its tags or the environment variable UAA_SERVICE_NAME should be specified (stating the exact name of the UAA service).
During local development the UAA configuration is provided in the default-services.json file. When the UAA is used for authentication the user is redirected to the UAA's login page to enter their credentials.

Sample content for a default-services.json file:

{
    "uaa": {
        "url" : "http://my.uaa.server/",
        "clientid" : "client-id",
        "clientsecret" : "client-secret",
        "xsappname" : "my-business-application"
    }
}

The application router supports the $XSAPPNAME placeholder (upper case letters). You may use it in your route configurations in the scope property. The value of $XSAPPNAME is taken from the UAA configuration (the xsappname property).

Additional headers configuration

If configured, the application router can send additional http headers in its responses to the client. Additional headers can be set in the httpHeaders environment variable.

Sample configuration for additional headers:

[
  {
    "X-Frame-Options": "ALLOW-FROM http://localhost"
  },
  {
    "Test-Additional-Header": "1"
  }
]

In this case, the application router sends two additional headers in the responses to the client.
Custom response headers, configured in the application router configuration file (xs-app.json) are added to the list of additional http headers. If the r

Docker Pull Command

docker pull sapse/approuter