Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Change Log
All notable changes to this project will be documented in this file.

## 4.2.0

- Split `java-security` into a new `java-security-core` module for Jakarta-free token validation
- The token model (`com.sap.cloud.security.token`), the JWT validation packages (`com.sap.cloud.security.token.validation`, incl. `JwtValidatorBuilder` and all validators), `com.sap.cloud.security.x509`, and the `TokenFactory` ServiceLoader registration (via `HybridTokenFactory`) moved to `java-security-core`
- `java-security-core` has no `jakarta.servlet` and no Spring dependencies, so token validation can be used from javax-based runtimes (e.g. Tomcat 9) without any Jakarta API on the classpath
- `java-security` keeps the servlet-based authenticators (`HybridTokenAuthenticator`, `IasTokenAuthenticator`, `XsuaaTokenAuthenticator`) and the Spring security context adapter, and now depends on `java-security-core`
- No API or behavior change for existing `java-security` consumers: all moved classes keep their fully qualified names and stay on the classpath transitively (minor release)


## 4.1.2

- Enforce constructor-supplied service configurations in `HybridTokenAuthenticator`
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Key features:
Developers who need OAuth2 token validation and token access in their Jakarta EE applications can utilize the [java-security](./java-security) library. This library simplifies the process of acquiring token information such as principal and audiences from the security context and takes over token validation for tokens issued by Xsuaa or Identity services.
This library is also integrated in SAP Java Buildpack.

:bulb: **javax / Tomcat 9 environments (no Jakarta)**: If you need token validation without Jakarta EE (e.g. Tomcat 9 / `javax.servlet` runtimes), use the [java-security-core](./java-security-core) module. It contains the token model, all JWT validators (`JwtValidatorBuilder` and friends) and `TokenFactory` registration, and has **no `jakarta.servlet` or Spring dependency**. The servlet-based authenticators (`HybridTokenAuthenticator`, `IasTokenAuthenticator`, `XsuaaTokenAuthenticator`) remain in [java-security](./java-security), which depends on `java-security-core`.

In the table below you'll find links to detailed information.

| Library | Usage Examples |
Expand Down
5 changes: 5 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
<artifactId>env</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>java-security-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>java-security</artifactId>
Expand Down
68 changes: 68 additions & 0 deletions java-security-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# SAP BTP Java Security Core Client Library

The core part of the SAP BTP Java Security client library: token model, JWT validation and
X.509 helpers — **without any `jakarta.servlet` or Spring dependency**.

This module exists so that token validation can be used from non-Jakarta environments
(e.g. Tomcat 9 / `javax.servlet` runtimes) and from non-servlet code (batch jobs,
message-driven components, custom filters).

## What's in this module

| Package | Content |
|---|---|
| `com.sap.cloud.security.token` | Token model (`Token`, `XsuaaToken`, `SapIdToken`, `IdTokenExtension`, `ScopeConverter`, `TokenExchangeMode`), thread-local `SecurityContext` token cache |
| `com.sap.cloud.security.token.validation` | `Validator`, `CombiningValidator`, `ValidationResult(s)`, `ValidationListener` |
| `com.sap.cloud.security.token.validation.validators` | `JwtValidatorBuilder` and all JWT validators (signature, issuer, audience, timestamp, `X5t` / proof token, JWKS handling with cache) |
| `com.sap.cloud.security.x509` | X.509 certificate helpers (`X509Certificate`, thumbprints) |
| `com.sap.cloud.security.servlet` | `HybridTokenFactory` only — the `TokenFactory` ServiceLoader registration used by `Token.create()`. Despite the package name it has **no servlet dependency** (historical package, kept for compatibility) |

The servlet-based token authenticators (`HybridTokenAuthenticator`, `IasTokenAuthenticator`,
`XsuaaTokenAuthenticator`) and the Spring security context adapter
(`com.sap.cloud.security.adapter.spring`) live in the
[`java-security`](../java-security) module, which depends on this module. If you depend on
`java-security` you get everything transitively — no code changes needed.

## Maven

```xml
<dependency>
<groupId>com.sap.cloud.security</groupId>
<artifactId>java-security-core</artifactId>
<version>4.1.2</version>
</dependency>
```

## Usage

Token validation without a servlet context:

```java
// 1. Service configuration (Cloud Foundry VCAP / Kubernetes secrets) or built manually
OAuth2ServiceConfiguration xsuaaConfig = Environments.getCurrent().getXsuaaConfiguration();

// 2. Build the validator chain (XSUAA or IAS, with audience/JWKs cache as needed)
Validator<Token> validator = JwtValidatorBuilder.getInstance(xsuaaConfig)
.withCacheConfiguration(TokenKeyCacheConfiguration.getInstance(Duration.ofMinutes(30), 100, true))
.build();

// 3. Validate the token from the Authorization header
Token token = Token.create("Bearer <access_token>");
ValidationResults results = validator.validate(token);
```

This is exactly what `HybridTokenAuthenticator` does internally in the `java-security`
module; with `java-security-core` you drive the same validators directly and extract the
Authorization header yourself from your (javax) servlet request.

## Requirements

- Java 17
- Service configuration via Cloud Foundry (`VCAP_SERVICES`) or Kubernetes/Kyma secrets
(see [`env`](../env) module), or a manually constructed `OAuth2ServiceConfiguration`

## Supported Identity Services & Algorithms

See the [java-security README](../java-security) — this module contains the same
validators, so supported identity services (XSUAA, SAP Identity) and token signature
algorithms are identical.
163 changes: 163 additions & 0 deletions java-security-core/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- SPDX-FileCopyrightText: 2018-2023 SAP SE or an SAP affiliate company and Cloud Security Client Java contributors -->
<!-- SPDX-License-Identifier: Apache-2.0 -->
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.1 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.sap.cloud.security.xsuaa</groupId>
<artifactId>parent</artifactId>
<version>4.1.2</version>
</parent>

<groupId>com.sap.cloud.security</groupId>
<artifactId>java-security-core</artifactId>
<name>java-security-core</name>
<packaging>jar</packaging>

<url>https://github.com/SAP/cloud-security-xsuaa-integration</url>
<description>java security core library (tokens and validators) without jakarta.servlet or Spring dependencies</description>

<organization>
<name>SAP SE</name>
<url>https://www.sap.com</url>
</organization>

<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>

<developers>
<developer>
<name>Identity Service Development</name>
<email>xsuaa-development@sap.com</email>
<organization>SAP SE</organization>
<organizationUrl>https://www.sap.com</organizationUrl>
</developer>
</developers>

<scm>
<connection>scm:git:git://github.com/SAP/cloud-security-xsuaa-integration.git</connection>
<developerConnection>scm:git:ssh//github.com/SAP/cloud-security-xsuaa-integration.git</developerConnection>
<url>https://github.com/SAP/cloud-security-xsuaa-integration</url>
</scm>

<dependencies>
<dependency>
<groupId>com.sap.cloud.security</groupId>
<artifactId>java-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sap.cloud.security</groupId>
<artifactId>env</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>compile</scope>
<version>${commons.io.version}</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<scope>provided</scope>
</dependency>

<!-- for call to tokenKeyService -->
<dependency>
<groupId>com.sap.cloud.security.xsuaa</groupId>
<artifactId>token-client</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
<version>${junit-jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
<version>${junit-jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
<version>${mockito.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
<version>${assertj.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
<version>1.5.13</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven.source.plugin.version}</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
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
18 changes: 18 additions & 0 deletions java-security-core/src/test/resources/iasJsonWebTokenKeys.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"keys": [
{
"kty": "RSA",
"kid": "default-kid-ias",
"e": "AQAB",
"use": "sig",
"n": "AJtUGmczI7RHx3Ypqxz9_9mK_tc-vOXojlJcMm0VRvYvMLIDlIfj1BrkC_IYLpS2Vl1OTG8AS0xAgBDEG3EUzVU6JZKuIuuxD-iXrBySBQA2ytTYtCrjHD7osji7wyogxDJ2BtVz9191gjX7AlU_WKFPpViK2a_2bCL0K4vI3M6-EZMp20wbD2gDsoD1JYqag66WnTDtZqJjQm3mv6Ohj59_C8RMOtPSLX4AxoS-n_8lYneaRc2UFm_vZepgricMNIZ4TuoLekb_fDlg7cvRtH61gD8hH7iFvQfpkf9rxoclPSG21qbxV4svUVW27DOd_Ewo3eSRdnSb8ctuGnXQuKE="
},
{
"kty": "RSA",
"kid": "default-kid",
"e": "AQAB",
"use": "sig",
"n": "AJtUGmczI7RHx3Ypqxz9_9mK_tc-vOXojlJcMm0VRvYvMLIDlIfj1BrkC_IYLpS2Vl1OTG8AS0xAgBDEG3EUzVU6JZKuIuuxD-iXrBySBQA2ytTYtCrjHD7osji7wyogxDJ2BtVz9191gjX7AlU_WKFPpViK2a_2bCL0K4vI3M6-EZMp20wbD2gDsoD1JYqag66WnTDtZqJjQm3mv6Ohj59_C8RMOtPSLX4AxoS-n_8lYneaRc2UFm_vZepgricMNIZ4TuoLekb_fDlg7cvRtH61gD8hH7iFvQfpkf9rxoclPSG21qbxV4svUVW27DOd_Ewo3eSRdnSb8ctuGnXQuKE="
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"use": "sig",
"n": "AJtUGmczI7RHx3Ypqxz9_9mK_tc-vOXojlJcMm0VRvYvMLIDlIfj1BrkC_IYLpS2Vl1OTG8AS0xAgBDEG3EUzVU6JZKuIuuxD-iXrBySBQA2ytTYtCrjHD7osji7wyogxDJ2BtVz9191gjX7AlU_WKFPpViK2a_2bCL0K4vI3M6-EZMp20wbD2gDsoD1JYqag66WnTDtZqJjQm3mv6Ohj59_C8RMOtPSLX4AxoS-n_8lYneaRc2UFm_vZepgricMNIZ4TuoLekb_fDlg7cvRtH61gD8hH7iFvQfpkf9rxoclPSG21qbxV4svUVW27DOd_Ewo3eSRdnSb8ctuGnXQuKE="
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eyJraWQiOiJkZWZhdWx0LWtpZC1pYXMiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJQMTc2OTQ1IiwiYXBwX3RpZCI6InRoZS1hcHAtdGlkIiwiaXNzIjoiaHR0cHM6Ly9hcHBsaWNhdGlvbi5teWF1dGguY29tIiwiZ2l2ZW5fbmFtZSI6ImpvaG4iLCJhdWQiOlsiVDAwMDMxMCIsIlQwMDAzMzMiXSwic2NpbV9pZCI6InNjaW0tMTIzNDU2Nzg5MCIsInVzZXJfdXVpZCI6IjEyMzQ1Njc4OTAiLCJhenAiOiJUMDAwMzEwIiwiem9uZV91dWlkIjoidGhlLXpvbmUtaWQiLCJleHAiOjY5NzQwMzE2MDAsImZhbWlseV9uYW1lIjoiZG9lIiwiZW1haWwiOiJqb2huLmRvZUBlbWFpbC5vcmciLCJjaWQiOiJUMDAwMzEwIn0.NkM70DLlYg1kDS37QXtlj5sQbyjk-UGSh6pmeGDDAj8-En4eNxRsG3wF_b7zv-ZseRINLURKp5mSW1O_xqI91w77Z9wwT45g_7WynH7kfXhKiAU0Te0RpZ6Iy19JbZXkfmMfbSjGNNRz5VIiVlTQOMS0bsNNLtGzz5QvhC6MkpwS8afDMjw-RX4zK-KO2CHsU7r7wjsLLpOmIfzgtao_HJJUhQCBkqwPNgmEJeHKTzJeDHxeAk-_Zbz5Won7nkajNZ4W6kn7eb3E-Vry9z7HDpV2_OKZpOP5lAWHVW1b7abPQ92npPqEdKaIhZT105-oGiwp20dX5Up7enAT_um38A
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eyJraWQiOiJkZWZhdWx0LWtpZC1pYXMiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOlsibXlDbGllbnRJZCJdLCJ1c2VyX3V1aWQiOiJ0aGUtdXNlci1pZCIsImF6cCI6IlQwMDAzMTAiLCJpc3MiOiJodHRwczovL2FwcGxpY2F0aW9uLm15YXV0aC5jb20iLCJ6b25lX3V1aWQiOiJ0aGUtem9uZS1pZCIsImNuZiI6eyJ4NXQjUzI1NiI6ImludmFsaWQifSwiZXhwIjo2OTc0MDMxNjAwLCJjaWQiOiJUMDAwMzEwIn0.Z2BwS6CpC9EAuh25xDB62RgeVfHpu0BzYnNMy7j-dq_deWrBVTr0ZEYDObM-E_c7J1gtSVQ4paJHS0OTcZkv3iigpxjjjUqUp1rhCZc76KXKgVG7JKZH8AtmeK-mTP5ssaEre-oLhatkWILieMrCcAkpcxF1W4wPsnOdljFwme7PzMkXDNTkD2lHuNt1IT1hi12GEGV6cv8M8tcf-A8JG0CtVbjA15qzCXOhIS-KpYBl41x_Onk6OtHnCPLkNzTjZn9lk_59Tc1NNzPp3_EgwCNvlAmWu3o9k_bHteoWuy8Mjr78L8a5JxaJeyZ6E9zbpEDldwHMmeNg0zEe4Zj91Q
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eyJraWQiOiJkZWZhdWx0LWtpZC1pYXMiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOlsibXlDbGllbnRJZCJdLCJ1c2VyX3V1aWQiOiJ0aGUtdXNlci1pZCIsImF6cCI6IlQwMDAzMTAiLCJpc3MiOiJodHRwczovL2FwcGxpY2F0aW9uLm15YXV0aC5jb20iLCJ6b25lX3V1aWQiOiJ0aGUtem9uZS1pZCIsImNuZiI6eyJ4NXQjUzI1NiI6ImZVLVhvUWxoTVRwUXN6OUFyWGw2ekhJcE1HdVJPNEV4TEtkTFJUYzVWak0ifSwiZXhwIjo2OTc0MDMxNjAwLCJjaWQiOiJUMDAwMzEwIn0.dlALBMbhbKQg0JylLNQOdFYXYbohRPahsjJZeS7I-grIq8sIyWb2U1h9PyC6-XQa3c_d6ttvSAZluRTgCAjbjWbZbdlbojoo_Q-drr32xS8fCMRUxfBmtQ8We5FjX4U593VH0XIe6Am_64Met1g0Vq0tr5RGh0ucgqy-wQi2MCl1RVa0OEJzpPT_5tEmQgUAG3I7i-BjquMKuimBoq-srrmRgkmJlTFLn_SoOu1F54Wz6yrwdIJEz8UVmnAfjAFsvPSkwXohF9QSiAvfgtd6fYax429bdb607xCGicQFdeiIQ_FFjhF2PaTK0ZgrrmfVstcGxIvhVLQ0kVlOophEWw
Loading
Loading