blob: 6d8dd4319b612fb16edc6149bd15ded35c320cad [file] [log] [blame]
margarethaa452c5e2018-04-25 22:48:09 +02001package de.ids_mannheim.korap.oauth2.dao;
2
margaretha6ad08b42018-08-22 18:33:54 +02003import java.time.ZoneId;
margarethaa2ce63d2018-06-28 10:11:43 +02004import java.time.ZonedDateTime;
margarethadc515072018-08-03 17:01:19 +02005import java.util.List;
margarethabe4c5c92018-05-03 18:55:49 +02006import java.util.Set;
7
margarethaa452c5e2018-04-25 22:48:09 +02008import javax.persistence.EntityManager;
margarethacf306d32018-05-30 19:45:35 +02009import javax.persistence.NoResultException;
margarethaa452c5e2018-04-25 22:48:09 +020010import javax.persistence.PersistenceContext;
margaretha07402f42018-05-07 19:07:45 +020011import javax.persistence.Query;
margarethac750cbb2018-12-11 12:47:02 +010012import javax.persistence.TypedQuery;
margaretha07402f42018-05-07 19:07:45 +020013import javax.persistence.criteria.CriteriaBuilder;
14import javax.persistence.criteria.CriteriaQuery;
margaretha0afd44a2020-02-05 10:49:21 +010015import javax.persistence.criteria.Predicate;
margaretha07402f42018-05-07 19:07:45 +020016import javax.persistence.criteria.Root;
margarethaa452c5e2018-04-25 22:48:09 +020017
margaretha6ad08b42018-08-22 18:33:54 +020018import org.springframework.beans.factory.annotation.Autowired;
margarethaa452c5e2018-04-25 22:48:09 +020019import org.springframework.stereotype.Repository;
20import org.springframework.transaction.annotation.Transactional;
21
margaretha6ad08b42018-08-22 18:33:54 +020022import de.ids_mannheim.korap.config.Attributes;
23import de.ids_mannheim.korap.config.FullConfiguration;
margaretha064eb6f2018-07-10 18:33:01 +020024import de.ids_mannheim.korap.config.KustvaktCacheable;
margarethabe4c5c92018-05-03 18:55:49 +020025import de.ids_mannheim.korap.exceptions.KustvaktException;
margarethacf306d32018-05-30 19:45:35 +020026import de.ids_mannheim.korap.exceptions.StatusCodes;
margaretha03b82862018-07-12 20:09:26 +020027import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
margarethabe4c5c92018-05-03 18:55:49 +020028import de.ids_mannheim.korap.oauth2.entity.AccessScope;
margarethaa452c5e2018-04-25 22:48:09 +020029import de.ids_mannheim.korap.oauth2.entity.AccessToken;
margaretha07402f42018-05-07 19:07:45 +020030import de.ids_mannheim.korap.oauth2.entity.AccessToken_;
margaretha0afd44a2020-02-05 10:49:21 +010031import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
margarethaf370f542018-08-23 18:51:49 +020032import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
margarethabe4c5c92018-05-03 18:55:49 +020033import de.ids_mannheim.korap.utils.ParameterChecker;
margarethaa452c5e2018-04-25 22:48:09 +020034
margaretha398f4722019-01-09 19:07:20 +010035/**
36 * Manages database queries and transactions regarding access tokens.
37 *
38 * @author margaretha
39 *
40 */
margarethaa452c5e2018-04-25 22:48:09 +020041@Repository
42@Transactional
margaretha064eb6f2018-07-10 18:33:01 +020043public class AccessTokenDao extends KustvaktCacheable {
44
margaretha6ad08b42018-08-22 18:33:54 +020045 @PersistenceContext
46 private EntityManager entityManager;
47 @Autowired
48 private FullConfiguration config;
margaretha0afd44a2020-02-05 10:49:21 +010049 @Autowired
50 private OAuth2ClientDao clientDao;
margaretha6ad08b42018-08-22 18:33:54 +020051
margaretha064eb6f2018-07-10 18:33:01 +020052 public AccessTokenDao () {
53 super("access_token", "key:access_token");
54 }
margarethaa452c5e2018-04-25 22:48:09 +020055
margarethaf370f542018-08-23 18:51:49 +020056 public void storeAccessToken (String token, RefreshToken refreshToken,
margaretha03b82862018-07-12 20:09:26 +020057 Set<AccessScope> scopes, String userId, String clientId,
58 ZonedDateTime authenticationTime) throws KustvaktException {
margaretha18259ce2021-05-03 17:31:58 +020059 ParameterChecker.checkStringValue(token, "access_token");
margaretha525045e2022-03-18 16:22:43 +010060 // ParameterChecker.checkObjectValue(refreshToken, "refresh
61 // token");
margarethabe4c5c92018-05-03 18:55:49 +020062 ParameterChecker.checkObjectValue(scopes, "scopes");
margarethadc515072018-08-03 17:01:19 +020063 // ParameterChecker.checkStringValue(userId, "username");
margaretha03b82862018-07-12 20:09:26 +020064 ParameterChecker.checkStringValue(clientId, "client_id");
margarethaa2ce63d2018-06-28 10:11:43 +020065 ParameterChecker.checkObjectValue(authenticationTime,
66 "authentication time");
margaretha03b82862018-07-12 20:09:26 +020067
margaretha6ad08b42018-08-22 18:33:54 +020068 ZonedDateTime now =
69 ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE));
margarethac750cbb2018-12-11 12:47:02 +010070
margaretha0afd44a2020-02-05 10:49:21 +010071 ZonedDateTime expiry;
margarethabe4c5c92018-05-03 18:55:49 +020072 AccessToken accessToken = new AccessToken();
margaretha525045e2022-03-18 16:22:43 +010073
margaretha0afd44a2020-02-05 10:49:21 +010074 if (refreshToken != null) {
75 accessToken.setRefreshToken(refreshToken);
76 expiry = now.plusSeconds(config.getAccessTokenExpiry());
77 }
78 else {
79 expiry = now.plusSeconds(config.getAccessTokenLongExpiry());
80 }
margaretha525045e2022-03-18 16:22:43 +010081
margaretha0afd44a2020-02-05 10:49:21 +010082 OAuth2Client client = clientDao.retrieveClientById(clientId);
margaretha525045e2022-03-18 16:22:43 +010083
margaretha6ad08b42018-08-22 18:33:54 +020084 accessToken.setCreatedDate(now);
margaretha0afd44a2020-02-05 10:49:21 +010085 accessToken.setExpiryDate(expiry);
margarethabe4c5c92018-05-03 18:55:49 +020086 accessToken.setToken(token);
87 accessToken.setScopes(scopes);
margaretha07402f42018-05-07 19:07:45 +020088 accessToken.setUserId(userId);
margaretha0afd44a2020-02-05 10:49:21 +010089 accessToken.setClient(client);
margarethaa2ce63d2018-06-28 10:11:43 +020090 accessToken.setUserAuthenticationTime(authenticationTime);
margarethabe4c5c92018-05-03 18:55:49 +020091 entityManager.persist(accessToken);
92 }
margaretha07402f42018-05-07 19:07:45 +020093
margaretha7f5071f2018-08-14 15:58:51 +020094 public AccessToken updateAccessToken (AccessToken accessToken)
95 throws KustvaktException {
96 ParameterChecker.checkObjectValue(accessToken, "access_token");
97 AccessToken cachedToken =
98 (AccessToken) this.getCacheValue(accessToken.getToken());
99 if (cachedToken != null) {
100 this.removeCacheEntry(accessToken.getToken());
101 }
102
103 accessToken = entityManager.merge(accessToken);
104 return accessToken;
105 }
margaretha07402f42018-05-07 19:07:45 +0200106
margarethacf306d32018-05-30 19:45:35 +0200107 public AccessToken retrieveAccessToken (String accessToken)
108 throws KustvaktException {
margarethadc515072018-08-03 17:01:19 +0200109 ParameterChecker.checkStringValue(accessToken, "access_token");
margaretha064eb6f2018-07-10 18:33:01 +0200110 AccessToken token = (AccessToken) this.getCacheValue(accessToken);
111 if (token != null) {
112 return token;
113 }
114
margaretha07402f42018-05-07 19:07:45 +0200115 CriteriaBuilder builder = entityManager.getCriteriaBuilder();
116 CriteriaQuery<AccessToken> query =
117 builder.createQuery(AccessToken.class);
118 Root<AccessToken> root = query.from(AccessToken.class);
119 query.select(root);
120 query.where(builder.equal(root.get(AccessToken_.token), accessToken));
121 Query q = entityManager.createQuery(query);
margarethacf306d32018-05-30 19:45:35 +0200122 try {
margaretha064eb6f2018-07-10 18:33:01 +0200123 token = (AccessToken) q.getSingleResult();
124 this.storeInCache(accessToken, token);
125 return token;
margarethacf306d32018-05-30 19:45:35 +0200126 }
127 catch (NoResultException e) {
128 throw new KustvaktException(StatusCodes.INVALID_ACCESS_TOKEN,
margaretha85273f12019-02-04 18:13:17 +0100129 "Access token is invalid", OAuth2Error.INVALID_TOKEN);
margarethacf306d32018-05-30 19:45:35 +0200130 }
margaretha07402f42018-05-07 19:07:45 +0200131 }
margaretha03b82862018-07-12 20:09:26 +0200132
margaretha0afd44a2020-02-05 10:49:21 +0100133 public AccessToken retrieveAccessToken (String accessToken, String username)
134 throws KustvaktException {
135 ParameterChecker.checkStringValue(accessToken, "access_token");
136 ParameterChecker.checkStringValue(username, "username");
137 AccessToken token = (AccessToken) this.getCacheValue(accessToken);
138 if (token != null) {
139 return token;
140 }
141
margaretha7f5071f2018-08-14 15:58:51 +0200142 CriteriaBuilder builder = entityManager.getCriteriaBuilder();
143 CriteriaQuery<AccessToken> query =
144 builder.createQuery(AccessToken.class);
145 Root<AccessToken> root = query.from(AccessToken.class);
margaretha525045e2022-03-18 16:22:43 +0100146
margaretha0afd44a2020-02-05 10:49:21 +0100147 Predicate condition = builder.and(
148 builder.equal(root.get(AccessToken_.userId), username),
149 builder.equal(root.get(AccessToken_.token), accessToken));
margaretha525045e2022-03-18 16:22:43 +0100150
margaretha7f5071f2018-08-14 15:58:51 +0200151 query.select(root);
margaretha0afd44a2020-02-05 10:49:21 +0100152 query.where(condition);
153 Query q = entityManager.createQuery(query);
154 try {
155 token = (AccessToken) q.getSingleResult();
156 this.storeInCache(accessToken, token);
157 return token;
158 }
159 catch (NoResultException e) {
160 return null;
161 }
162 }
163
margaretha0afd44a2020-02-05 10:49:21 +0100164 public List<AccessToken> retrieveAccessTokenByClientId (String clientId,
165 String username) throws KustvaktException {
166 ParameterChecker.checkStringValue(clientId, "client_id");
167 OAuth2Client client = clientDao.retrieveClientById(clientId);
margaretha525045e2022-03-18 16:22:43 +0100168
margaretha0afd44a2020-02-05 10:49:21 +0100169 CriteriaBuilder builder = entityManager.getCriteriaBuilder();
170 CriteriaQuery<AccessToken> query =
171 builder.createQuery(AccessToken.class);
172 Root<AccessToken> root = query.from(AccessToken.class);
margaretha525045e2022-03-18 16:22:43 +0100173
174 Predicate condition =
175 builder.equal(root.get(AccessToken_.client), client);
176 if (username != null && !username.isEmpty()) {
margaretha0afd44a2020-02-05 10:49:21 +0100177 condition = builder.and(condition,
178 builder.equal(root.get(AccessToken_.userId), username));
179 }
margaretha525045e2022-03-18 16:22:43 +0100180
margaretha0afd44a2020-02-05 10:49:21 +0100181 query.select(root);
182 query.where(condition);
margarethac750cbb2018-12-11 12:47:02 +0100183 TypedQuery<AccessToken> q = entityManager.createQuery(query);
184 return q.getResultList();
185 }
186
margaretha525045e2022-03-18 16:22:43 +0100187 public List<AccessToken> retrieveAccessTokenByUser (String username,
188 String clientId) throws KustvaktException {
margaretha35074692021-03-26 18:11:59 +0100189 ParameterChecker.checkStringValue(username, "username");
190
191 CriteriaBuilder builder = entityManager.getCriteriaBuilder();
192 CriteriaQuery<AccessToken> query =
193 builder.createQuery(AccessToken.class);
194
195 Root<AccessToken> root = query.from(AccessToken.class);
196 root.fetch(AccessToken_.client);
197 Predicate condition = builder.and(
198 builder.equal(root.get(AccessToken_.userId), username),
199 builder.equal(root.get(AccessToken_.isRevoked), false),
200 builder.greaterThan(
201 root.<ZonedDateTime> get(AccessToken_.expiryDate),
202 ZonedDateTime
203 .now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE))));
204 if (clientId != null && !clientId.isEmpty()) {
205 OAuth2Client client = clientDao.retrieveClientById(clientId);
206 condition = builder.and(condition,
207 builder.equal(root.get(AccessToken_.client), client));
208 }
margaretha525045e2022-03-18 16:22:43 +0100209
210 query.select(root);
211 query.where(condition);
212 TypedQuery<AccessToken> q = entityManager.createQuery(query);
213 return q.getResultList();
214 }
215
216 public void deleteInvalidAccessTokens () {
217 List<AccessToken> invalidAccessTokens = retrieveInvalidAccessTokens();
218 invalidAccessTokens.forEach(token -> entityManager.remove(token));
219 }
220
221 public List<AccessToken> retrieveInvalidAccessTokens () {
222 CriteriaBuilder builder = entityManager.getCriteriaBuilder();
223 CriteriaQuery<AccessToken> query =
224 builder.createQuery(AccessToken.class);
225
226 Root<AccessToken> root = query.from(AccessToken.class);
227 Predicate condition = builder.or(
228 builder.equal(root.get(AccessToken_.isRevoked), true),
229 builder.lessThan(
230 root.<ZonedDateTime> get(AccessToken_.expiryDate),
231 ZonedDateTime
232 .now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE))));
233
margaretha35074692021-03-26 18:11:59 +0100234 query.select(root);
235 query.where(condition);
236 TypedQuery<AccessToken> q = entityManager.createQuery(query);
237 return q.getResultList();
238 }
margarethaa452c5e2018-04-25 22:48:09 +0200239}