All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cloud.security.token.Token Maven / Gradle / Ivy

There is a newer version: 3.5.5
Show newest version
/**
 * 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 com.sap.cloud.security.config.Service; import com.sap.cloud.security.json.JsonObject; import com.sap.cloud.security.json.JsonParsingException; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.Serializable; import java.security.Principal; import java.security.ProviderException; import java.time.Instant; import java.util.*; import static com.sap.cloud.security.token.TokenClaims.*; /** * Represents a JSON Web Token (JWT). */ public interface Token extends Serializable { @SuppressWarnings("unchecked") List services = new ArrayList() { { ServiceLoader.load(TokenFactory.class).forEach(this::add); LoggerFactory.getLogger(Token.class).info("loaded TokenFactory service providers: {}", this); } }; String DEFAULT_TOKEN_FACTORY = "com.sap.cloud.security.servlet.HybridTokenFactory"; /** * Creates a token instance based on TokenFactory implementation. * * @param jwt * encoded JWT token * @return token instance */ static Token create(String jwt) { if (services.isEmpty()) { throw new ProviderNotFoundException("No TokenFactory implementation found in the classpath"); } if (services.size() > 2) { throw new ProviderException( "More than 1 Custom TokenFactory service provider found. There should be only one"); } if (services.size() == 2) { return services.stream() .filter(tokenFactory -> !tokenFactory.getClass().getName() .equals(DEFAULT_TOKEN_FACTORY)) .findFirst().get().create(jwt); } return services.get(0).create(jwt); } /** * Returns the header parameter value as string for the given header parameter name. * * @param headerName * the name of the header parameter as defined here {@link TokenHeader} * @return the value for the given header name or null, if the header is not provided. */ @Nullable String getHeaderParameterAsString(@Nonnull String headerName); /** * Checks whether the token contains a given header parameter. * * @param headerName * the name of the header parameter as defined here {@link TokenHeader} * @return true when the given header name is found. */ boolean hasHeaderParameter(@Nonnull String headerName); /** * Checks whether the token contains a given claim. * * @param claimName * the name of the claim as defined here {@link TokenClaims}. * @return true when the claim with the given name is found. */ boolean hasClaim(@Nonnull String claimName); /** * Extracts the value as string for the given claim. If the claim is not found, it will return null. If the given * claim is not a string, it will throw a {@link JsonParsingException}. * * @param claimName * the name of the claim as defined here {@link TokenClaims}. * @return the corresponding string value of the given claim or null. * @throws JsonParsingException * if the json object identified by the given claim is not a string. */ @Nullable String getClaimAsString(@Nonnull String claimName); /** * Extracts the value as a list of strings for the given claim. If the claim is not found, it will return null. If * the given claim is not a list of strings, it will throw a {@link JsonParsingException}. * * @param claimName * the name of the claim as defined here {@link TokenClaims}. * @return the data of the given claim as a list of strings or an empty list. */ @Nonnull List getClaimAsStringList(@Nonnull String claimName); /** * Extracts the value of the given as a JsonObject. Use this to extract nested objects. If the claim is not found, * it will return null. If the vale for the given claim is not an object, it will throw a * {@link JsonParsingException}. * * @param claimName * the name of the claim for which the object should be extracted. * @return the corresponding {@link JsonObject} for the given claim. */ @Nullable JsonObject getClaimAsJsonObject(@Nonnull String claimName); /** * Returns the moment in time when the token will be expired. * * @return the expiration point in time if present. */ @Nullable Instant getExpiration(); /** * Returns true if the token is expired. * * @return true if the token is expired. */ boolean isExpired(); /** * Returns the moment in time before which the token must not be accepted. * * @return the not before point in time if present. */ @Nullable Instant getNotBefore(); /** * Get the encoded jwt token, e.g. for token forwarding to another app. * *

* Never expose this token via log or via HTTP. * * @return the encoded token. */ String getTokenValue(); /** * Returns a principal, which can be used to represent any entity, such as an individual, a corporation, and a login * id. * * @return the principal or null if not yet implemented. */ Principal getPrincipal(); /** * Returns the identity service, the token is issued by. * * @return the service. */ Service getService(); /** * Returns the (empty) list of audiences the token is issued for.
* * @return the audiences. **/ default Set getAudiences() { return new LinkedHashSet<>(getClaimAsStringList(AUDIENCE)); } /** * @deprecated use {@link Token#getAppTid()} instead */ @Deprecated default String getZoneId() { return getAppTid(); } /** * Returns the app tenant identifier, which can be used as tenant discriminator (tenant guid). * * @return the unique application tenant identifier. */ default String getAppTid() { return hasClaim(SAP_GLOBAL_APP_TID) ? getClaimAsString(SAP_GLOBAL_APP_TID) : getClaimAsString(SAP_GLOBAL_ZONE_ID); } /** * Returns the OAuth2 client identifier of the authentication token if present. Following OpenID Connect 1.0 * standard specifications, client identifier is obtained from "azp" claim if present or when "azp" is not present * from "aud" claim, but only in case there is one audience. * * @return the OAuth client ID. * @see https://openid.net/specs/openid-connect-core-1_0.html */ default String getClientId() { String clientId = getClaimAsString(AUTHORIZATION_PARTY); if (clientId == null || clientId.trim().isEmpty()) { Set audiences = getAudiences(); if (audiences.size() == 1) { return audiences.stream().findFirst().get(); } throw new InvalidTokenException("Couldn't get client id. Invalid authorized party or audience claims."); } else { return clientId; } } /** * Returns the identifier for the Issuer of the token. Its a URL that contains scheme, host, and optionally, port * number and path components but no query or fragment components. This one is validated in the * {@code JwtIssuerValidator} and used as base url to discover jwks_uri endpoint for downloading the token keys. * * @return the issuer. */ default String getIssuer() { return getClaimAsString(ISSUER); } /** * Returns the grant type of the jwt token.
* * @return the grant type **/ @Nullable default GrantType getGrantType() { return GrantType.from(getClaimAsString(TokenClaims.XSUAA.GRANT_TYPE)); } /** * Returns the header(s). * * @return a {@code Map} of the header(s) */ default Map getHeaders() { return Collections.emptyMap(); } /** * Returns the jwt claim set. * * @return a {@code Map} of the jwt claim set */ default Map getClaims() { return Collections.emptyMap(); } /** * Returns the String value of a claim attribute.
* * "claimName": { "attributeName": "attributeValueAsString" }, *
*
* Example:
* * import static com.sap.cloud.security.token.TokenClaims.XSUAA.*; * token.getAttributeFromClaimAsString(EXTERNAL_ATTRIBUTE, EXTERNAL_ATTRIBUTE_SUBACCOUNTID); * * * @return the String value of a claim attribute or null if claim or its attribute does not exist. **/ @Nullable default String getAttributeFromClaimAsString(String claimName, String attributeName) { return Optional.ofNullable(getClaimAsJsonObject(claimName)) .map(claim -> claim.getAsString(attributeName)) .orElse(null); } /** * Returns the String list of a claim attribute.
* * "claimName": { "attributeName": ["attributeValueAsString", "attributeValue2AsString"] }, *
*
* Example:
* * import static com.sap.cloud.security.token.TokenClaims.XSUAA.*; * token.getAttributeFromClaimAsString(XS_USER_ATTRIBUTES, "custom_role"); * * * @return the list of String values of a claim attribute or empty List if claim or its attribute does not exist. **/ default List getAttributeFromClaimAsStringList(String claimName, String attributeName) { JsonObject claimAsJsonObject = getClaimAsJsonObject(claimName); return Optional.ofNullable(claimAsJsonObject) .map(jsonObject -> jsonObject.getAsList(attributeName, String.class)) .orElse(Collections.emptyList()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy