diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f180d191..9d2f865a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log All notable changes to this project will be documented in this file. +## 4.1.0 + +- Expose the `sap_id_type` claim on `SapIdToken` + - New `SapIdToken#getIdType()` returning a typed `SapIdType` enum (`USER`, `APP`); resolves to `null` if the claim is absent or carries an unknown value + - New `TokenClaims.SAP_ID_TYPE` constant + - `DefaultIdTokenExtension#isTechnicalUser` now prefers the `sap_id_type` claim and falls back to the `sub == azp` heuristic for tokens issued before the claim was introduced + ## 4.0.7 - Fix mTLS handshake regression in `SSLContextFactory` diff --git a/java-api/src/main/java/com/sap/cloud/security/token/SapIdType.java b/java-api/src/main/java/com/sap/cloud/security/token/SapIdType.java new file mode 100644 index 000000000..df604ac3a --- /dev/null +++ b/java-api/src/main/java/com/sap/cloud/security/token/SapIdType.java @@ -0,0 +1,54 @@ +/** + * SPDX-FileCopyrightText: 2018-2023 SAP SE or an SAP affiliate company and Cloud Security Client Java contributors + *

+ * SPDX-License-Identifier: Apache-2.0 + */ +package com.sap.cloud.security.token; + +import jakarta.annotation.Nullable; + +/** + * Type of the principal an IAS-issued token belongs to. Mirrors the {@code sap_id_type} JWT claim + * issued by SAP Cloud Identity Service. + */ +public enum SapIdType { + /** Human end-user principal. */ + USER("user"), + /** Technical / application principal. */ + APP("app"); + + private final String claimValue; + + SapIdType(String claimValue) { + this.claimValue = claimValue; + } + + /** + * Returns the raw claim value used on the wire. + * + * @return the raw claim value as it appears in the JWT (e.g. {@code "user"} or {@code "app"}). + */ + public String claimValue() { + return claimValue; + } + + /** + * Resolves a {@link SapIdType} from a raw {@code sap_id_type} claim value. + * + * @param value the claim value, may be {@code null} + * @return the matching {@link SapIdType}, or {@code null} if {@code value} is {@code null} or + * does not match a known type (forward-compatibility for future values) + */ + @Nullable + public static SapIdType fromClaimValue(@Nullable String value) { + if (value == null) { + return null; + } + for (SapIdType t : values()) { + if (t.claimValue.equals(value)) { + return t; + } + } + return null; + } +} \ No newline at end of file diff --git a/java-api/src/main/java/com/sap/cloud/security/token/TokenClaims.java b/java-api/src/main/java/com/sap/cloud/security/token/TokenClaims.java index be8d7111d..38ef68be5 100644 --- a/java-api/src/main/java/com/sap/cloud/security/token/TokenClaims.java +++ b/java-api/src/main/java/com/sap/cloud/security/token/TokenClaims.java @@ -43,6 +43,13 @@ private TokenClaims() { public static final String SAP_GLOBAL_ZONE_ID = "zone_uuid"; // legacy claim public static final String SAP_GLOBAL_APP_TID = "app_tid"; // tenant GUID + /** + * Indicates the type of the token principal. Issued by SAP Cloud Identity Service. Values + * are {@code "user"} for human end-users and {@code "app"} for technical/application + * principals. See {@link SapIdType} for the typed accessor. + */ + public static final String SAP_ID_TYPE = "sap_id_type"; + public static final String GROUPS = "groups"; // scim groups public static final String AUTHORIZATION_PARTY = "azp"; // Authorization party contains OAuth client identifier public static final String CNF = "cnf"; // X509 certificate ("cnf" (confirmation)) claim diff --git a/java-security/src/main/java/com/sap/cloud/security/token/DefaultIdTokenExtension.java b/java-security/src/main/java/com/sap/cloud/security/token/DefaultIdTokenExtension.java index 69ac75f63..3689fad2e 100644 --- a/java-security/src/main/java/com/sap/cloud/security/token/DefaultIdTokenExtension.java +++ b/java-security/src/main/java/com/sap/cloud/security/token/DefaultIdTokenExtension.java @@ -27,7 +27,8 @@ *