
com.sap.cloud.sdk.cloudplatform.security.AuthTokenDecoder Maven / Gradle / Ivy
/*
* Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved.
*/
package com.sap.cloud.sdk.cloudplatform.security;
import java.security.interfaces.RSAPublicKey;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.google.common.net.HttpHeaders;
import com.sap.cloud.sdk.cloudplatform.security.exception.AuthTokenAccessException;
import io.vavr.control.Try;
class AuthTokenDecoder
{
// We handle the value of Authorization header case insensitive. To prevent repetitive toLowerCase calls we store this prefix in lower case.
private static final String BEARER_PREFIX = "bearer ";
private int getNumberOfAuthHeaders( final HttpServletRequest request )
{
@Nullable
final Enumeration headers = request.getHeaders(HttpHeaders.AUTHORIZATION);
int numHeaders = 0;
if( headers != null ) {
while( headers.hasMoreElements() ) {
headers.nextElement();
++numHeaders;
}
}
return numHeaders;
}
@Nonnull
AuthToken decode( @Nonnull final String encodedJwt, @Nullable final String refreshToken )
throws AuthTokenAccessException
{
final List verificationKeys = AuthTokenValidator.getVerificationPublicKeysForJwt(encodedJwt);
final String targetAlgorithm =
Try.of(() -> JWT.decode(encodedJwt).getAlgorithm()).getOrElseThrow(
e -> new AuthTokenAccessException("Failed to verify JWT bearer.", e));
final AuthTokenValidator authTokenValidator = new AuthTokenValidator(targetAlgorithm, verificationKeys);
Optional verifiedToken = authTokenValidator.verifyToken(encodedJwt);
// fallback: use refresh token to request new access token and try to verify once more
if( !verifiedToken.isPresent() && refreshToken != null ) {
final String refreshedEncodedJwt = new RefreshJwtTokenCommand(encodedJwt, refreshToken).run();
verifiedToken = authTokenValidator.verifyToken(refreshedEncodedJwt);
}
return verifiedToken.map(AuthToken::new).orElseThrow(
() -> new AuthTokenAccessException("Failed to verify JWT bearer."));
}
@Nonnull
Optional decode( @Nonnull final HttpServletRequest request )
throws AuthTokenAccessException
{
@Nullable
final String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if( authorizationHeader == null ) {
return Optional.empty();
}
if( getNumberOfAuthHeaders(request) != 1 ) {
throw new AuthTokenAccessException(
"Failed to decode JWT bearer: multiple '"
+ HttpHeaders.AUTHORIZATION
+ "' headers present in request.");
}
if( !authorizationHeader.toLowerCase(Locale.ENGLISH).startsWith(BEARER_PREFIX) ) {
throw new AuthTokenAccessException(
"Failed to decode JWT bearer: no JWT bearer present in '"
+ HttpHeaders.AUTHORIZATION
+ "' header of request.");
}
final String tokenValue = authorizationHeader.substring(BEARER_PREFIX.length());
return Optional.of(decode(tokenValue, null));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy