Java tutorial
/******************************************************************************* * Copyright 2016 The MITRE Corporation * and the MIT Internet Trust Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package org.mitre.oauth2.repository.impl; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaDelete; import javax.persistence.criteria.Root; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.model.OAuth2RefreshTokenEntity; import org.mitre.oauth2.repository.OAuth2TokenRepository; import org.mitre.uma.model.ResourceSet; import org.mitre.util.jpa.JpaUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.nimbusds.jwt.JWT; import com.nimbusds.jwt.JWTParser; @Repository public class JpaOAuth2TokenRepository implements OAuth2TokenRepository { private static final int MAXEXPIREDRESULTS = 1000; private static final Logger logger = LoggerFactory.getLogger(JpaOAuth2TokenRepository.class); @PersistenceContext(unitName = "defaultPersistenceUnit") private EntityManager manager; @Override public Set<OAuth2AccessTokenEntity> getAllAccessTokens() { TypedQuery<OAuth2AccessTokenEntity> query = manager.createNamedQuery(OAuth2AccessTokenEntity.QUERY_ALL, OAuth2AccessTokenEntity.class); return new LinkedHashSet<>(query.getResultList()); } @Override public Set<OAuth2RefreshTokenEntity> getAllRefreshTokens() { TypedQuery<OAuth2RefreshTokenEntity> query = manager.createNamedQuery(OAuth2RefreshTokenEntity.QUERY_ALL, OAuth2RefreshTokenEntity.class); return new LinkedHashSet<>(query.getResultList()); } @Override public OAuth2AccessTokenEntity getAccessTokenByValue(String accessTokenValue) { try { JWT jwt = JWTParser.parse(accessTokenValue); TypedQuery<OAuth2AccessTokenEntity> query = manager .createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_TOKEN_VALUE, OAuth2AccessTokenEntity.class); query.setParameter(OAuth2AccessTokenEntity.PARAM_TOKEN_VALUE, jwt); return JpaUtil.getSingleResult(query.getResultList()); } catch (ParseException e) { return null; } } @Override public OAuth2AccessTokenEntity getAccessTokenById(Long id) { return manager.find(OAuth2AccessTokenEntity.class, id); } @Override @Transactional(value = "defaultTransactionManager") public OAuth2AccessTokenEntity saveAccessToken(OAuth2AccessTokenEntity token) { return JpaUtil.saveOrUpdate(token.getId(), manager, token); } @Override @Transactional(value = "defaultTransactionManager") public void removeAccessToken(OAuth2AccessTokenEntity accessToken) { OAuth2AccessTokenEntity found = getAccessTokenByValue(accessToken.getValue()); if (found != null) { manager.remove(found); } else { throw new IllegalArgumentException("Access token not found: " + accessToken); } } @Override @Transactional(value = "defaultTransactionManager") public void clearAccessTokensForRefreshToken(OAuth2RefreshTokenEntity refreshToken) { TypedQuery<OAuth2AccessTokenEntity> query = manager .createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_REFRESH_TOKEN, OAuth2AccessTokenEntity.class); query.setParameter(OAuth2AccessTokenEntity.PARAM_REFERSH_TOKEN, refreshToken); List<OAuth2AccessTokenEntity> accessTokens = query.getResultList(); for (OAuth2AccessTokenEntity accessToken : accessTokens) { removeAccessToken(accessToken); } } @Override public OAuth2RefreshTokenEntity getRefreshTokenByValue(String refreshTokenValue) { try { JWT jwt = JWTParser.parse(refreshTokenValue); TypedQuery<OAuth2RefreshTokenEntity> query = manager.createNamedQuery( OAuth2RefreshTokenEntity.QUERY_BY_TOKEN_VALUE, OAuth2RefreshTokenEntity.class); query.setParameter(OAuth2RefreshTokenEntity.PARAM_TOKEN_VALUE, jwt); return JpaUtil.getSingleResult(query.getResultList()); } catch (ParseException e) { return null; } } @Override public OAuth2RefreshTokenEntity getRefreshTokenById(Long id) { return manager.find(OAuth2RefreshTokenEntity.class, id); } @Override @Transactional(value = "defaultTransactionManager") public OAuth2RefreshTokenEntity saveRefreshToken(OAuth2RefreshTokenEntity refreshToken) { return JpaUtil.saveOrUpdate(refreshToken.getId(), manager, refreshToken); } @Override @Transactional(value = "defaultTransactionManager") public void removeRefreshToken(OAuth2RefreshTokenEntity refreshToken) { OAuth2RefreshTokenEntity found = getRefreshTokenByValue(refreshToken.getValue()); if (found != null) { manager.remove(found); } else { throw new IllegalArgumentException("Refresh token not found: " + refreshToken); } } @Override @Transactional(value = "defaultTransactionManager") public void clearTokensForClient(ClientDetailsEntity client) { TypedQuery<OAuth2AccessTokenEntity> queryA = manager .createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_CLIENT, OAuth2AccessTokenEntity.class); queryA.setParameter(OAuth2AccessTokenEntity.PARAM_CLIENT, client); List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList(); for (OAuth2AccessTokenEntity accessToken : accessTokens) { removeAccessToken(accessToken); } TypedQuery<OAuth2RefreshTokenEntity> queryR = manager .createNamedQuery(OAuth2RefreshTokenEntity.QUERY_BY_CLIENT, OAuth2RefreshTokenEntity.class); queryR.setParameter(OAuth2RefreshTokenEntity.PARAM_CLIENT, client); List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList(); for (OAuth2RefreshTokenEntity refreshToken : refreshTokens) { removeRefreshToken(refreshToken); } } /* (non-Javadoc) * @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity) */ @Override public List<OAuth2AccessTokenEntity> getAccessTokensForClient(ClientDetailsEntity client) { TypedQuery<OAuth2AccessTokenEntity> queryA = manager .createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_CLIENT, OAuth2AccessTokenEntity.class); queryA.setParameter(OAuth2AccessTokenEntity.PARAM_CLIENT, client); List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList(); return accessTokens; } /* (non-Javadoc) * @see org.mitre.oauth2.repository.OAuth2TokenRepository#getRefreshTokensForClient(org.mitre.oauth2.model.ClientDetailsEntity) */ @Override public List<OAuth2RefreshTokenEntity> getRefreshTokensForClient(ClientDetailsEntity client) { TypedQuery<OAuth2RefreshTokenEntity> queryR = manager .createNamedQuery(OAuth2RefreshTokenEntity.QUERY_BY_CLIENT, OAuth2RefreshTokenEntity.class); queryR.setParameter(OAuth2RefreshTokenEntity.PARAM_CLIENT, client); List<OAuth2RefreshTokenEntity> refreshTokens = queryR.getResultList(); return refreshTokens; } /* (non-Javadoc) * @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokenForIdToken(org.mitre.oauth2.model.OAuth2AccessTokenEntity) */ @Override public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken) { TypedQuery<OAuth2AccessTokenEntity> queryA = manager .createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_ID_TOKEN, OAuth2AccessTokenEntity.class); queryA.setParameter(OAuth2AccessTokenEntity.PARAM_ID_TOKEN, idToken); List<OAuth2AccessTokenEntity> accessTokens = queryA.getResultList(); return JpaUtil.getSingleResult(accessTokens); } @Override public Set<OAuth2AccessTokenEntity> getAllExpiredAccessTokens() { TypedQuery<OAuth2AccessTokenEntity> query = manager .createNamedQuery(OAuth2AccessTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2AccessTokenEntity.class); query.setParameter(OAuth2AccessTokenEntity.PARAM_DATE, new Date()); query.setMaxResults(MAXEXPIREDRESULTS); return new LinkedHashSet<>(query.getResultList()); } @Override public Set<OAuth2RefreshTokenEntity> getAllExpiredRefreshTokens() { TypedQuery<OAuth2RefreshTokenEntity> query = manager .createNamedQuery(OAuth2RefreshTokenEntity.QUERY_EXPIRED_BY_DATE, OAuth2RefreshTokenEntity.class); query.setParameter(OAuth2RefreshTokenEntity.PARAM_DATE, new Date()); query.setMaxResults(MAXEXPIREDRESULTS); return new LinkedHashSet<>(query.getResultList()); } /* (non-Javadoc) * @see org.mitre.oauth2.repository.OAuth2TokenRepository#getAccessTokensForResourceSet(org.mitre.uma.model.ResourceSet) */ @Override public Set<OAuth2AccessTokenEntity> getAccessTokensForResourceSet(ResourceSet rs) { TypedQuery<OAuth2AccessTokenEntity> query = manager .createNamedQuery(OAuth2AccessTokenEntity.QUERY_BY_RESOURCE_SET, OAuth2AccessTokenEntity.class); query.setParameter(OAuth2AccessTokenEntity.PARAM_RESOURCE_SET_ID, rs.getId()); return new LinkedHashSet<>(query.getResultList()); } /* (non-Javadoc) * @see org.mitre.oauth2.repository.OAuth2TokenRepository#clearDuplicateAccessTokens() */ @Override @Transactional(value = "defaultTransactionManager") public void clearDuplicateAccessTokens() { Query query = manager.createQuery( "select a.jwt, count(1) as c from OAuth2AccessTokenEntity a GROUP BY a.jwt HAVING c > 1"); @SuppressWarnings("unchecked") List<Object[]> resultList = query.getResultList(); List<JWT> values = new ArrayList<>(); for (Object[] r : resultList) { logger.warn("Found duplicate access tokens: {}, {}", ((JWT) r[0]).serialize(), r[1]); values.add((JWT) r[0]); } if (values.size() > 0) { CriteriaBuilder cb = manager.getCriteriaBuilder(); CriteriaDelete<OAuth2AccessTokenEntity> criteriaDelete = cb .createCriteriaDelete(OAuth2AccessTokenEntity.class); Root<OAuth2AccessTokenEntity> root = criteriaDelete.from(OAuth2AccessTokenEntity.class); criteriaDelete.where(root.get("jwt").in(values)); int result = manager.createQuery(criteriaDelete).executeUpdate(); logger.warn("Deleted {} duplicate access tokens", result); } } /* (non-Javadoc) * @see org.mitre.oauth2.repository.OAuth2TokenRepository#clearDuplicateRefreshTokens() */ @Override @Transactional(value = "defaultTransactionManager") public void clearDuplicateRefreshTokens() { Query query = manager.createQuery( "select a.jwt, count(1) as c from OAuth2RefreshTokenEntity a GROUP BY a.jwt HAVING c > 1"); @SuppressWarnings("unchecked") List<Object[]> resultList = query.getResultList(); List<JWT> values = new ArrayList<>(); for (Object[] r : resultList) { logger.warn("Found duplicate refresh tokens: {}, {}", ((JWT) r[0]).serialize(), r[1]); values.add((JWT) r[0]); } if (values.size() > 0) { CriteriaBuilder cb = manager.getCriteriaBuilder(); CriteriaDelete<OAuth2RefreshTokenEntity> criteriaDelete = cb .createCriteriaDelete(OAuth2RefreshTokenEntity.class); Root<OAuth2RefreshTokenEntity> root = criteriaDelete.from(OAuth2RefreshTokenEntity.class); criteriaDelete.where(root.get("jwt").in(values)); int result = manager.createQuery(criteriaDelete).executeUpdate(); logger.warn("Deleted {} duplicate refresh tokens", result); } } }