Protect your Kyma workloads from eavesdropping with introspection and BTP destinations


The security is paramount and the internet never forgets….

Yeah, that sounds familiar. We’ve been already there with the first instalment, namely:

This time let’s see how to implement SAP Kyma API rules oauth2_introspection access strategy with SAP IAS opaque tokens, its introspection endpoint and the BTP destinations.

Table of Contents
  1. The rationale behind the use of opaque tokens.
  2. oauth2_introspection access strategy.
    1. Retrieve an opaque token for client credentials flow with OAuth2ClientCredentials destination.
    2. oauth2_introspection access strategy configuration with an API rule.

1. Rationale behind the use of opaque tokens

They are both compact and opaque (=meta) tokens which may constitute an advantage whenever the size of a payload matters and whenever it is paramount to keep the token information secret.

However, as the opaque tokens need to be further validated and exchanged by a service provider’s introspection endpoint, that makes them not really suitable for offline scenarios.

Q. Are the opaque tokens preferred security media for securing API-driven communications in the enterprise world ?

A1. Seemingly, SAP ABAP solutions, with SAP S/4HANA Private and Public Cloud at the front, make pretty much exclusive use of opaque tokens or otherwise SAML assertions (xml tokens) with the OAuth2 APIs.

And this is for a good reason. The good reason being, in the ABAP world, both authorization and resource servers share the same database, and that makes the opaque tokens an attractive choice for securing SAP S/4HANA OAuth2 APIs.

A2. Otherwise, SPAs, mobile apps are good candidates for having their access secured with the opaque tokens as well.

2. oauth2_introspection access strategy

In order to build an oauth2_introspection strategy one needs to:

  • have a destination service fetch a valid opaque token.
  • provide a Kyma API rule with a valid opaque token.

Eventually, ory oathkeeper will be calling into the SAP IAS introspection endpoint with the value of an opaque token passed in a header of an API rule.

Good to read:

2.1 Retrieve an opaque token for client credentials flow with OAuth2ClientCredentials destination

As aforementioned, the oauth2 introspection flow requires an opaque bearer access token be retrieved first.

This is done by adding an additional propertytokenService.body.token_format -set to opaque – in the destination definition, as depicted below:

Good to know:

  • An opaque token is a short-lived bearer access token. The destination service has a built-in load-balancing logic to fetch one or more tokens from the service provider which will be cached until their expiry.
{
  "owner": {
    "SubaccountId": "<SubaccountId>",
    "InstanceId": null
  },
  "destinationConfiguration": {
    "Name": "poster-quovadis_opaque",
    "Type": "HTTP",
    "URL": "https://httpbin-anywhere.<API rule custom domain>",
    "Authentication": "OAuth2ClientCredentials",
    "ProxyType": "Internet",
    "tokenServiceURLType": "Dedicated",
    "tokenService.body.token_format": "opaque",
    "HTML5.DynamicDestination": "true",
    "clientId": "<clientId>",
    "Description": "poster-quovadis-opaque",
    "scope": "openid",
    "clientSecret": "<clientSecret>",
    "tokenServiceURL": "https://<sap ias tenant>.accounts400.ondemand.com/oauth2/token"
  },
  "authTokens": [
    {
      "type": "Bearer",
      "value": "NTM2ZGYxMzYtMDU3Yy00ZWNhLTliZDctMTIzYjA2MTg5NGE2bmdtUncyOFI1RUdLa0UxdUhqVGNoaWZ5TC1LR2xwZXdEaXVzczF0NlFxOA",
      "http_header": {
        "key": "Authorization",
        "value": "Bearer NTM2ZGYxMzYtMDU3Yy00ZWNhLTliZDctMTIzYjA2MTg5NGE2bmdtUncyOFI1RUdLa0UxdUhqVGNoaWZ5TC1LR2xwZXdEaXVzczF0NlFxOA"
      },
      "expires_in": "3600"
    }
  ]
}

 

2.2 oauth2_introspection access strategy configuration with an API rule

The opaque token needs to be passed in a header when calling an API rule….

Ory oathkeeper will retrieve this opaque bearer token either from the Authorization header (default location)  or from a custom header defined as token_from: header: <header_name> in the manifest and will pass it along to the introspection endpoint for validation and exchange.

As already mentioned, an opaque token must have the scopes defined as a string of values and not as an array of values. Failure to comply with this requirement will result in the following error message:

The authentication handler encountered an error audience=application authentication_handler=oauth2_introspection error=map[message:json: cannot unmarshal array into Go struct field AuthenticatorOAuth2IntrospectionResult.scope of type string

This can be easily accomplished by defining all scopes as a single entry scope with multiple values instead of a list of single-valued scopes, as depicted below.

On a side note, the audiences are supported as either a string of values or an array of values.

The SAP IAS introspection endpoint needs to be protected against a so-called token scanning with either Basic Authentication, Bearer Access Token or x509 certificate.

Seemingly, the ory oathkeeper supports both the Basic Authentication through theintrospection_request_headers object as shown below:

apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
  labels:
    app.kubernetes.io/name: httpbin-introspect
  name: httpbin-introspect
  namespace: quovadis
spec:
  gateway: quovadis-azure-dns-gateway.azure-dns.svc.cluster.local
  host: httpbin-introspect.btp.quovadis-anywhere.com
  rules:
    - accessStrategies:
        - config:
            introspection_request_headers:
              Authorization: >-
                Basic
                MTEwODVkYTgtNT****************FbVRzaw==
            introspection_url: https://<sap ias tenant>.accounts400.ondemand.com/oauth2/introspect
            required_scope:
              - openid
              - read
              - write
            token_from:
              header: Authorization
          handler: oauth2_introspection
      methods:
        - GET
        - POST
        - PUT
        - DELETE
        - PATCH
        - HEAD
      path: /.*
      timeout: 300
  service:
    name: httpbin
    port: 8000
  timeout: 300

On a side note, you can use the below destination definition to help you create a Basic Authentication payload for use with the introspection_request_headers object.

  {
    "Name": "introspect-me",
    "Type": "HTTP",
    "URL": "https://sap.com",
    "Authentication": "BasicAuthentication",
    "ProxyType": "Internet",
    "User": "<client_id>",
    "Description": "provide base64-encoded introspection endpoint credentials",
    "Password": "<client_secret>"
  },
  "authTokens": [
    {
      "type": "Basic",
      "value": "MTEwODVkYTgtNT****************FbVRzaw==",
      "http_header": {
        "key": "Authorization",
        "value": "Basic MTEwODVkYTgtNT****************FbVRzaw=="
      }
    }
  ]
}

Or, alternatively, you can have an APIRule with the pre_authorization object in lieu of the introspection_request_headers object, as follows:

apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
  labels:
    app.kubernetes.io/name: httpbin-introspect
  name: httpbin-introspect
  namespace: <namespace>
spec:
  gateway: quovadis-azure-dns-gateway.azure-dns.svc.cluster.local
  host: httpbin-introspect.<custom domain>
  rules:
    - accessStrategies:
        - config:
            introspection_request_headers: {}
            introspection_url: https://<sap ias tenant>.accounts400.ondemand.com/oauth2/introspect
            pre_authorization:
              client_id: <client_id>
              client_secret: <client_secret>
              enabled: true
              token_url: https://<sap ias tenant>.accounts400.ondemand.com/oauth2/token
            required_scope:
              - openid
              - read
              - write
            target_audience:
              - toto01
              - toto02
          handler: oauth2_introspection
      methods:
        - GET
        - POST
        - PUT
        - DELETE
        - PATCH
        - HEAD
      path: /.*
      service:
        name: httpbin
        port: 8000
      timeout: 300
  service:
    name: httpbin
    port: 8000
  timeout: 300

The Bearer Access token protection of the introspection endpoint can be really attractive because you can use a different and confidential SAP IAS client for this purpose.

Last but not least, it looks like the x509 client certificate protection mechanism of the SAP IAS introspection endpoint is not supported by ory oathkeeper.

As a way around you may have to use a proxy to the SAP IAS introspection endpoint with the x.509 client certificate authentication method.

 

The next blogpost will focus on bringing the user context into the picture. So stay tuned!


 

 

Scroll to Top