From 4509f5a6a4a1d2679e3a29addd60c5360391f1b4 Mon Sep 17 00:00:00 2001 From: Claudio Mezzasalma Date: Thu, 9 Jul 2020 17:27:29 +0200 Subject: [PATCH] Use index to search for AccessTokens Signed-off-by: Claudio Mezzasalma --- .../token/AccessTokenAttributes.java | 4 ++- .../shiro/AuthenticationServiceShiroImpl.java | 14 +++++++- .../realm/AccessTokenAuthenticatingRealm.java | 32 ++++++++++++++----- .../1.3.0/atht-access_token-expires_index.xml | 26 +++++++++++++++ .../1.3.0/changelog-authentication-1.3.0.xml | 22 +++++++++++++ .../changelog-authentication-master.xml | 5 +-- 6 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 service/security/shiro/src/main/resources/liquibase/1.3.0/atht-access_token-expires_index.xml create mode 100644 service/security/shiro/src/main/resources/liquibase/1.3.0/changelog-authentication-1.3.0.xml diff --git a/service/security/authentication/api/src/main/java/org/eclipse/kapua/service/authentication/token/AccessTokenAttributes.java b/service/security/authentication/api/src/main/java/org/eclipse/kapua/service/authentication/token/AccessTokenAttributes.java index 0db39b619b9..2238300ae81 100644 --- a/service/security/authentication/api/src/main/java/org/eclipse/kapua/service/authentication/token/AccessTokenAttributes.java +++ b/service/security/authentication/api/src/main/java/org/eclipse/kapua/service/authentication/token/AccessTokenAttributes.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2016 Eurotech and/or its affiliates and others + * Copyright (c) 2011, 2020 Eurotech and/or its affiliates and others * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -22,5 +22,7 @@ public class AccessTokenAttributes extends KapuaUpdatableEntityAttributes { public static final String TOKEN_ID = "tokenId"; public static final String USER_ID = "userId"; + public static final String EXPIRES_ON = "expiresOn"; + public static final String INVALIDATED_ON = "invalidatedOn"; } diff --git a/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/AuthenticationServiceShiroImpl.java b/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/AuthenticationServiceShiroImpl.java index 22e74a4ffc4..f2298205a38 100644 --- a/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/AuthenticationServiceShiroImpl.java +++ b/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/AuthenticationServiceShiroImpl.java @@ -24,6 +24,8 @@ import org.eclipse.kapua.locator.KapuaLocator; import org.eclipse.kapua.locator.KapuaProvider; import org.eclipse.kapua.model.id.KapuaId; +import org.eclipse.kapua.model.query.predicate.AndPredicate; +import org.eclipse.kapua.model.query.predicate.AttributePredicate.Operator; import org.eclipse.kapua.service.authentication.AuthenticationService; import org.eclipse.kapua.service.authentication.LoginCredentials; import org.eclipse.kapua.service.authentication.SessionCredentials; @@ -34,8 +36,10 @@ import org.eclipse.kapua.service.authentication.shiro.setting.KapuaAuthenticationSetting; import org.eclipse.kapua.service.authentication.shiro.setting.KapuaAuthenticationSettingKeys; import org.eclipse.kapua.service.authentication.token.AccessToken; +import org.eclipse.kapua.service.authentication.token.AccessTokenAttributes; import org.eclipse.kapua.service.authentication.token.AccessTokenCreator; import org.eclipse.kapua.service.authentication.token.AccessTokenFactory; +import org.eclipse.kapua.service.authentication.token.AccessTokenQuery; import org.eclipse.kapua.service.authentication.token.AccessTokenService; import org.eclipse.kapua.service.authentication.token.LoginInfo; import org.eclipse.kapua.service.authorization.access.AccessInfo; @@ -290,7 +294,15 @@ public AccessToken findAccessToken(String tokenId) throws KapuaException { accessToken = kapuaSession.getAccessToken(); if (accessToken == null) { - accessToken = accessTokenService.findByTokenId(tokenId); + AccessTokenQuery accessTokenQuery = accessTokenFactory.newQuery(null); + AndPredicate andPredicate = accessTokenQuery.andPredicate( + accessTokenQuery.attributePredicate(AccessTokenAttributes.EXPIRES_ON, new java.sql.Timestamp(new Date().getTime()), Operator.GREATER_THAN_OR_EQUAL), + accessTokenQuery.attributePredicate(AccessTokenAttributes.INVALIDATED_ON, null, Operator.IS_NULL), + accessTokenQuery.attributePredicate(AccessTokenAttributes.TOKEN_ID, tokenId) + ); + accessTokenQuery.setPredicate(andPredicate); + accessTokenQuery.setLimit(1); + accessToken = accessTokenService.query(accessTokenQuery).getFirstItem(); } } } finally { diff --git a/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/realm/AccessTokenAuthenticatingRealm.java b/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/realm/AccessTokenAuthenticatingRealm.java index a44daca705d..b3b554e844d 100644 --- a/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/realm/AccessTokenAuthenticatingRealm.java +++ b/service/security/shiro/src/main/java/org/eclipse/kapua/service/authentication/shiro/realm/AccessTokenAuthenticatingRealm.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2016 Eurotech and/or its affiliates and others + * Copyright (c) 2011, 2020 Eurotech and/or its affiliates and others * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,6 +11,8 @@ *******************************************************************************/ package org.eclipse.kapua.service.authentication.shiro.realm; +import java.util.Date; + import org.apache.shiro.SecurityUtils; import org.apache.shiro.ShiroException; import org.apache.shiro.authc.AuthenticationException; @@ -21,23 +23,27 @@ import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.realm.AuthenticatingRealm; import org.apache.shiro.subject.Subject; + import org.eclipse.kapua.KapuaException; import org.eclipse.kapua.commons.security.KapuaSecurityUtils; import org.eclipse.kapua.commons.security.KapuaSession; import org.eclipse.kapua.locator.KapuaLocator; +import org.eclipse.kapua.model.query.predicate.AndPredicate; +import org.eclipse.kapua.model.query.predicate.AttributePredicate.Operator; import org.eclipse.kapua.service.account.Account; import org.eclipse.kapua.service.account.AccountService; import org.eclipse.kapua.service.authentication.AccessTokenCredentials; import org.eclipse.kapua.service.authentication.shiro.AccessTokenCredentialsImpl; import org.eclipse.kapua.service.authentication.shiro.exceptions.ExpiredAccountException; import org.eclipse.kapua.service.authentication.token.AccessToken; +import org.eclipse.kapua.service.authentication.token.AccessTokenAttributes; +import org.eclipse.kapua.service.authentication.token.AccessTokenFactory; +import org.eclipse.kapua.service.authentication.token.AccessTokenQuery; import org.eclipse.kapua.service.authentication.token.AccessTokenService; import org.eclipse.kapua.service.user.User; import org.eclipse.kapua.service.user.UserService; import org.eclipse.kapua.service.user.UserStatus; -import java.util.Date; - /** * {@link AccessTokenCredentials} based {@link AuthenticatingRealm} implementation. *

@@ -53,6 +59,7 @@ public class AccessTokenAuthenticatingRealm extends AuthenticatingRealm { private static final KapuaLocator LOCATOR = KapuaLocator.getInstance(); private static final AccessTokenService ACCESS_TOKEN_SERVICE = LOCATOR.getService(AccessTokenService.class); + private static final AccessTokenFactory ACCESS_TOKEN_FACTORY = LOCATOR.getFactory(AccessTokenFactory.class); private static final AccountService ACCOUNT_SERVICE = LOCATOR.getService(AccountService.class); private static final UserService USER_SERVICE = LOCATOR.getService(UserService.class); @@ -76,11 +83,20 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent AccessTokenCredentialsImpl token = (AccessTokenCredentialsImpl) authenticationToken; String tokenTokenId = token.getTokenId(); + Date now = new Date(); // // Find accessToken final AccessToken accessToken; try { - accessToken = KapuaSecurityUtils.doPrivileged(() -> ACCESS_TOKEN_SERVICE.findByTokenId(tokenTokenId)); + AccessTokenQuery accessTokenQuery = ACCESS_TOKEN_FACTORY.newQuery(null); + AndPredicate andPredicate = accessTokenQuery.andPredicate( + accessTokenQuery.attributePredicate(AccessTokenAttributes.EXPIRES_ON, new java.sql.Timestamp(now.getTime()), Operator.GREATER_THAN_OR_EQUAL), + accessTokenQuery.attributePredicate(AccessTokenAttributes.INVALIDATED_ON, null, Operator.IS_NULL), + accessTokenQuery.attributePredicate(AccessTokenAttributes.TOKEN_ID, tokenTokenId) + ); + accessTokenQuery.setPredicate(andPredicate); + accessTokenQuery.setLimit(1); + accessToken = KapuaSecurityUtils.doPrivileged(() -> ACCESS_TOKEN_SERVICE.query(accessTokenQuery).getFirstItem()); } catch (AuthenticationException ae) { throw ae; } catch (Exception e) { @@ -93,8 +109,8 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent } // Check validity - if ((accessToken.getExpiresOn() != null && accessToken.getExpiresOn().before(new Date())) || - (accessToken.getInvalidatedOn() != null && accessToken.getInvalidatedOn().before(new Date()))) { + if ((accessToken.getExpiresOn() != null && accessToken.getExpiresOn().before(now)) || + (accessToken.getInvalidatedOn() != null && accessToken.getInvalidatedOn().before(now))) { throw new ExpiredCredentialsException(); } @@ -120,7 +136,7 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent } // Check if expired - if (user.getExpirationDate() != null && !user.getExpirationDate().after(new Date())) { + if (user.getExpirationDate() != null && !user.getExpirationDate().after(now)) { throw new ExpiredCredentialsException(); } @@ -141,7 +157,7 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authent } // Check account expired - if (account.getExpirationDate() != null && !account.getExpirationDate().after(new Date())) { + if (account.getExpirationDate() != null && !account.getExpirationDate().after(now)) { throw new ExpiredAccountException(account.getExpirationDate()); } diff --git a/service/security/shiro/src/main/resources/liquibase/1.3.0/atht-access_token-expires_index.xml b/service/security/shiro/src/main/resources/liquibase/1.3.0/atht-access_token-expires_index.xml new file mode 100644 index 00000000000..47abe035f45 --- /dev/null +++ b/service/security/shiro/src/main/resources/liquibase/1.3.0/atht-access_token-expires_index.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/service/security/shiro/src/main/resources/liquibase/1.3.0/changelog-authentication-1.3.0.xml b/service/security/shiro/src/main/resources/liquibase/1.3.0/changelog-authentication-1.3.0.xml new file mode 100644 index 00000000000..bf133fbf154 --- /dev/null +++ b/service/security/shiro/src/main/resources/liquibase/1.3.0/changelog-authentication-1.3.0.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/service/security/shiro/src/main/resources/liquibase/changelog-authentication-master.xml b/service/security/shiro/src/main/resources/liquibase/changelog-authentication-master.xml index 347caf3b66c..21c4d286fd8 100644 --- a/service/security/shiro/src/main/resources/liquibase/changelog-authentication-master.xml +++ b/service/security/shiro/src/main/resources/liquibase/changelog-authentication-master.xml @@ -1,6 +1,6 @@