use of net.petafuel.styx.api.exception.StyxException in project styx by petafuel.
the class AccessTokenFilter method checkToken.
@Override
public boolean checkToken(String tokenHash) {
AccessToken accessToken;
try {
accessToken = PersistentAccessToken.get(tokenHash);
} catch (PersistenceEmptyResultSetException persistenceEmptyResultSetException) {
// if there was no matching token found in the database, always return unauthorized
ResponseEntity responseEntity = new ResponseEntity(ResponseConstant.UNAUTHORIZED, ResponseCategory.ERROR, ResponseOrigin.CLIENT);
throw new StyxException(responseEntity);
}
if (accessToken.getLastUsedOn() == null && (TimeUnit.MILLISECONDS.toSeconds(new Date().getTime() - accessToken.getCreatedAt().getTime())) > accessToken.getExpiresIn()) {
MasterToken masterToken = PersistentClientApp.get(accessToken.getClientMasterToken());
LOG.warn("Access token expired before first usage, invalidated. master={}, access_token_created={}, serviceBinding={}", masterToken.getName(), accessToken.getCreatedAt(), accessToken.getServiceType());
PersistentAccessToken.setValid(tokenHash, false);
return false;
}
// get master token and check restrictions
MasterToken masterToken = PersistentClientApp.get(accessToken.getClientMasterToken());
checkRestrictions(masterToken, accessToken.getServiceType());
// check if maxUsages is reached
checkMaxUsages(masterToken, accessToken);
// log necessary token information
LOG.info("Request sent with following token information: accessToken={} valid={} serviceType={} usages={} clientReference={} createdAt={} masterTokenName={} masterTokenEnabled={}", accessToken.getId(), accessToken.isValid(), accessToken.getServiceType(), accessToken.getUsages(), accessToken.getClientReference(), accessToken.getCreatedAt(), masterToken.getName(), masterToken.isEnabled());
// get service requirements from Target-Resource class or method
List<XS2ATokenType> serviceRequirements = null;
if (ri.getResourceMethod().getAnnotation(CheckAccessToken.class) != null) {
serviceRequirements = Arrays.asList(ri.getResourceMethod().getAnnotation(CheckAccessToken.class).allowedServices());
} else if (ri.getResourceClass().getAnnotation(CheckAccessToken.class) != null) {
serviceRequirements = Arrays.asList(ri.getResourceClass().getAnnotation(CheckAccessToken.class).allowedServices());
}
// Get all TokenTypeMapperSPI implementations
List<TokenTypeMapperSPI> tokenTypeMapperImpls = new TokenTypeMapperService().providers();
TokenTypeMapperSPI concreteTokenTypeMapper = tokenTypeMapperImpls.stream().filter(tokenTypeMapperSPI -> tokenTypeMapperSPI.getMapping(accessToken.getServiceType()) != null).findFirst().orElse(null);
if (concreteTokenTypeMapper == null || (serviceRequirements != null && !serviceRequirements.contains(concreteTokenTypeMapper.getMapping(accessToken.getServiceType())))) {
if (concreteTokenTypeMapper == null) {
LOG.error("There was not TokenTypeMapperSPI implementation found within the classpath, tokens cannot be validated against access controll");
}
ResponseEntity responseEntity = new ResponseEntity(ResponseConstant.STYX_TOKEN_ACCESS_VIOLATION, ResponseCategory.ERROR, ResponseOrigin.CLIENT);
throw new StyxException(responseEntity);
}
// update lastUsedOn and increase usages of accessToken
if (ri.getResourceClass().isAnnotationPresent(CheckAccessToken.class) && ri.getResourceClass().getAnnotation(CheckAccessToken.class).incrementUsage()) {
PersistentAccessToken.updateLastUsedOn(tokenHash);
}
return accessToken.isValid() && masterToken.isEnabled();
}
use of net.petafuel.styx.api.exception.StyxException in project styx by petafuel.
the class AccessTokenFilter method checkMaxUsages.
/**
* Check if maximum amount of usages reached => exception if reached, increase usage of token if not reached yet
*
* @param masterToken model of MasterToken
* @param accessToken model of AccessToken
*/
public void checkMaxUsages(MasterToken masterToken, AccessToken accessToken) {
if (masterToken.getRestrictions().get(accessToken.getServiceType()) == null) {
LOG.error("Accesstoken has serviceType that does not match mastertoken. Mastertoken restrictions were changed after this accesstoken was created. masterTokenName='{}', accessTokenHash='{}', accessTokenServiceType='{}', accessTokenCreatedAt='{}', accessTokenClientReference='{}'", masterToken.getName(), accessToken.getId(), accessToken.getServiceType(), accessToken.getCreatedAt(), accessToken.getClientReference());
abortMasterTokenRestricted();
}
int maxUsages = masterToken.getRestrictions().get(accessToken.getServiceType()).getMaxUsages();
if (maxUsages > 0 && maxUsages <= accessToken.getUsages()) {
ResponseEntity responseEntity = new ResponseEntity(ResponseConstant.STYX_TOKEN_ACCESS_EXEEDED, ResponseCategory.ERROR, ResponseOrigin.CLIENT);
throw new StyxException(responseEntity);
}
}
use of net.petafuel.styx.api.exception.StyxException in project styx by petafuel.
the class PreAuthAccessFilter method filter.
/**
* Supressing java:S3776 -> need to rework logic to reduce code complexity
*
* @param containerRequestContext
*/
@Override
@SuppressWarnings("java:S3776")
public void filter(ContainerRequestContext containerRequestContext) {
XS2AStandard xs2AStandard = (XS2AStandard) containerRequestContext.getProperty(XS2AStandard.class.getName());
IOParser ioParser = new IOParser(xs2AStandard.getAspsp());
ImplementerOption ioPreAuthRequired = ioParser.get("IO6");
if (ioPreAuthRequired != null && ioPreAuthRequired.getOptions().get(IOParser.Option.REQUIRED)) {
LOG.info("ASPSP bic={} requires pre-auth", xs2AStandard.getAspsp().getBic());
// preauth is available and required for this bank -> check if preauth id is present
String preAuthIdString = containerRequestContext.getHeaderString(PRE_AUTH_ID);
if (preAuthIdString == null || "".equals(preAuthIdString)) {
throw new StyxException(new ResponseEntity("The requested aspsps requires a pre-step authorisation, preAuthId Header is missing", ResponseConstant.STYX_PREAUTH_HEADER_REQUIRED, ResponseCategory.ERROR, ResponseOrigin.CLIENT));
}
try {
UUID preAuthId = UUID.fromString(preAuthIdString);
OAuthSession oAuthSession = PersistentOAuthSession.getById(preAuthId);
LOG.info("Loaded state={} oauth_session", oAuthSession.getState());
STYX03.setPreauthId(preAuthId);
if (oAuthSession.getAccessToken() == null || oAuthSession.getAccessTokenExpiresAt() == null) {
throw new PersistenceEmptyResultSetException("The access_token data should be set");
}
if (oAuthSession.getAccessTokenExpiresAt().before(new Date())) {
if (oAuthSession.getRefreshTokenExpiresAt().after(new Date())) {
oAuthSession = refreshToken(oAuthSession);
} else {
throw new OAuthTokenExpiredException(OAuthTokenExpiredException.MESSAGE);
}
}
// Add the Authorization: <type> <credentials> header to the request context so we can use it later on demand
Map<String, String> additionalHeaders = new HashMap<>();
additionalHeaders.put(XS2AHeader.AUTHORIZATION, oAuthSession.getTokenType() + " " + oAuthSession.getAccessToken());
containerRequestContext.setProperty(PreAuthAccessFilter.class.getName(), additionalHeaders);
LOG.info("Successfully attached pre-auth from oAuthSessionState={}", oAuthSession.getState());
} catch (PersistenceEmptyResultSetException noOauthSessionFound) {
throw new StyxException(new ResponseEntity("There was no valid pre-step authorisation found for the specified preAuthId", ResponseConstant.STYX_PREAUTH_NOT_AVAILABLE, ResponseCategory.ERROR, ResponseOrigin.CLIENT));
} catch (OAuthTokenExpiredException tokenExpired) {
throw new StyxException(new ResponseEntity(tokenExpired.getMessage(), ResponseConstant.STYX_PREAUTH_EXPIRED, ResponseCategory.ERROR, ResponseOrigin.CLIENT));
}
}
}
use of net.petafuel.styx.api.exception.StyxException in project styx by petafuel.
the class PSUFilter method filter.
@Override
public void filter(ContainerRequestContext containerRequestContext) {
String id = containerRequestContext.getHeaderString(XS2AHeader.PSU_ID);
if (id == null || "".equals(id)) {
throw new StyxException(new ResponseEntity("PSU-ID is not provided or empty", ResponseConstant.BAD_REQUEST, ResponseCategory.ERROR, ResponseOrigin.CLIENT));
}
PSU psu = new PSU(id);
psu.setIdType(containerRequestContext.getHeaderString(XS2AHeader.PSU_ID_TYPE));
psu.setCorporateId(containerRequestContext.getHeaderString(XS2AHeader.PSU_CORPORATE_ID));
psu.setCorporateIdType(containerRequestContext.getHeaderString(XS2AHeader.PSU_CORPORATE_ID_TYPE));
if (Boolean.getBoolean(ApiProperties.STYX_PROXY_ENABLED)) {
String forwardedIps = containerRequestContext.getHeaderString(XS2AHeader.X_FORWARDED_FOR);
psu.setIp(Sanitizer.parseClientIpFromForwardedIPs(forwardedIps));
} else {
psu.setIp(httpServletRequest.getRemoteAddr());
}
String psuPort = containerRequestContext.getHeaderString(XS2AHeader.PSU_IP_PORT);
try {
Integer intVal = psuPort != null ? Integer.valueOf(psuPort) : null;
psu.setPort(intVal);
} catch (NumberFormatException invalidDataType) {
LOG.warn("PSU-PORT header was bigger than integer MAX_VALUE, not accepting header value");
}
psu.setUserAgent(containerRequestContext.getHeaderString(XS2AHeader.PSU_USER_AGENT));
psu.setGeoLocation(containerRequestContext.getHeaderString(XS2AHeader.PSU_GEO_LOCATION));
containerRequestContext.setProperty(PSU.class.getName(), psu);
}
use of net.petafuel.styx.api.exception.StyxException in project styx by petafuel.
the class PaymentInitiationResource method initiateSinglePayment.
/**
* Initiate single or future dated payments
*
* @param paymentTypeBean contains which payment product is used
* @param singlePaymentBody contains the request body as parsed json
* @return 201 if successful
* @throws BankRequestFailedException in case the communication between styx and aspsp was not successful
*/
@POST
@Path("/payments/{paymentProduct}")
@RequiresMandatoryHeader
@AcceptsPreStepAuth
public Response initiateSinglePayment(@BeanParam PaymentTypeBean paymentTypeBean, @Valid SinglePaymentInitiation singlePaymentBody) throws BankRequestFailedException {
Optional<SinglePayment> singlePayment = singlePaymentBody.getPayments().stream().findFirst();
if (!singlePayment.isPresent()) {
throw new StyxException(new ResponseEntity("No valid single payment object was found within the payments array", ResponseConstant.BAD_REQUEST, ResponseCategory.ERROR, ResponseOrigin.CLIENT));
}
SinglePayment payment = singlePayment.get();
XS2AFactoryInput xs2AFactoryInput = new XS2AFactoryInput();
xs2AFactoryInput.setPayment(payment);
xs2AFactoryInput.setPsu(getPsu());
xs2AFactoryInput.setPaymentService(PaymentService.PAYMENTS);
xs2AFactoryInput.setPaymentProduct(paymentTypeBean.getPaymentProduct());
IOProcessor ioProcessor = new IOProcessor(getXS2AStandard());
ioProcessor.modifyInput(xs2AFactoryInput);
PISRequest paymentInitiationRequest = new PISRequestFactory().create(getXS2AStandard().getRequestClassProvider().paymentInitiation(), xs2AFactoryInput);
paymentInitiationRequest.getHeaders().putAll(getAdditionalHeaders());
paymentInitiationRequest.setTppRedirectPreferred(getRedirectPreferred());
paymentInitiationRequest.setXrequestId(ThreadContext.get(RequestUUIDAdapter.REQUEST_UUID));
ioProcessor.modifyRequest(paymentInitiationRequest, xs2AFactoryInput);
InitiatedPayment initiatedPayment = getXS2AStandard().getPis().initiatePayment(paymentInitiationRequest);
PersistentPayment.create(paymentInitiationRequest.getXrequestId(), initiatedPayment.getPaymentId(), (String) getContainerRequestContext().getProperty(AbstractTokenFilter.class.getName()), getXS2AStandard().getAspsp().getBic(), initiatedPayment.getStatus(), PaymentService.PAYMENTS, paymentTypeBean.getPaymentProduct());
if (containerRequestContext.getProperty(PreAuthAccessFilter.class.getName()) != null) {
initiatedPayment.setxRequestId(UUID.fromString(containerRequestContext.getHeaderString(PreAuthAccessFilter.PRE_AUTH_ID)));
}
xs2AFactoryInput.setPaymentId(initiatedPayment.getPaymentId());
ioProcessor.modifyResponse(initiatedPayment, xs2AFactoryInput);
PaymentResponse paymentResponse = new PaymentResponse(initiatedPayment);
SCAApproach approach = SCAHandler.decision(initiatedPayment);
if (approach instanceof OAuth2) {
paymentResponse.getLinks().getScaOAuth().setUrl(((OAuth2) approach).getAuthoriseLink());
}
LOG.info("Initiate single payment bic={} aspsp_name={} aspsp_id={} paymentId={} xrequestid={}", getXS2AStandard().getAspsp().getBic(), getXS2AStandard().getAspsp().getName(), getXS2AStandard().getAspsp().getId(), paymentResponse.getPaymentId(), paymentInitiationRequest.getXrequestId());
AspspUrlMapper aspspUrlMapper = new AspspUrlMapper(PaymentService.PAYMENTS, paymentTypeBean.getPaymentProduct(), paymentResponse.getPaymentId(), null);
paymentResponse.setLinks(aspspUrlMapper.map(paymentResponse.getLinks()));
return Response.status(ResponseConstant.CREATED).entity(paymentResponse).build();
}
Aggregations