From 23822fe75201cbac8b4175a9459f2bb420fb53c7 Mon Sep 17 00:00:00 2001 From: diya17 Date: Thu, 19 Oct 2023 16:29:55 -0700 Subject: [PATCH 01/28] [CITE-217] Adding Access Token --- .../core/repository/oauth/AccessTokenRepository.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java new file mode 100644 index 000000000..a90a0466a --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java @@ -0,0 +1,11 @@ +package edu.asu.diging.citesphere.core.repository.oauth; + +import org.javers.spring.annotation.JaversSpringDataAuditable; +import org.springframework.data.repository.PagingAndSortingRepository; + +import edu.asu.diging.citesphere.user.impl.AccessToken; + +@JaversSpringDataAuditable +public interface AccessTokenRepository extends PagingAndSortingRepository { + +} From 17dbe638cd7cd4bd5887ee73f16e9563458c3572 Mon Sep 17 00:00:00 2001 From: diya17 Date: Wed, 25 Oct 2023 15:00:01 -0700 Subject: [PATCH 02/28] [CITE-217] Adding user token manager --- citesphere/pom.xml | 2 +- .../citesphere/core/service/oauth/IUserTokenManager.java | 9 +++++++++ .../core/service/oauth/impl/UserTokenManager.java | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java diff --git a/citesphere/pom.xml b/citesphere/pom.xml index 36ecc6b44..b45630d50 100644 --- a/citesphere/pom.xml +++ b/citesphere/pom.xml @@ -25,7 +25,7 @@ 2.2.6.RELEASE 0.12 0.4 - 1.19 + 1.21-SNAPSHOT $2a$04$oQo44vqcDIFRoYKiAXoNheurzkwX9dcNmowvTX/hsWuBMwijqn44i diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java new file mode 100644 index 000000000..bb3b6a9ad --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java @@ -0,0 +1,9 @@ +package edu.asu.diging.citesphere.core.service.oauth; + +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +import edu.asu.diging.citesphere.user.IUser; + +public interface IUserTokenManager { + OAuth2AccessToken getAccessToken(IUser user); +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java new file mode 100644 index 000000000..b57c09e31 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java @@ -0,0 +1,7 @@ +package edu.asu.diging.citesphere.core.service.oauth.impl; + +import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; + +public class UserTokenManager implements IUserTokenManager { + +} From 6f89887d6c8dfd7e8aab99015a702db79a329275 Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 31 Oct 2023 13:00:09 -0700 Subject: [PATCH 03/28] [CITE-217] Adding create token method for access token --- .../service/oauth/impl/UserTokenManager.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java index b57c09e31..6fe607dfd 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java @@ -1,7 +1,106 @@ package edu.asu.diging.citesphere.core.service.oauth.impl; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Collection; +import java.util.Date; +import java.util.Optional; +import java.util.UUID; + +import javax.annotation.PostConstruct; +import javax.transaction.Transactional; +import javax.transaction.Transactional.TxType; + +import org.javers.common.collections.Sets; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; + import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; +import edu.asu.diging.citesphere.user.IUser; public class UserTokenManager implements IUserTokenManager { + @Autowired + private TokenStore tokenStore; + + @Autowired + private ClientDetailsService clientDetailsService; + + @Value("${_citephere_oauth2_app_clientid}") + private String citesphereClientId; + + private OAuth2RequestFactory requestFactory; + + @PostConstruct + public void init() { + this.requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); + } + + @Override + @Transactional(TxType.REQUIRES_NEW) + public OAuth2AccessToken getAccessToken(IUser user) { + Collection tokens = tokenStore.findTokensByClientIdAndUserName(citesphereClientId, user.getUsername()); + Optional validToken = tokens.stream().filter(t -> !t.isExpired()).findFirst(); + if (validToken.isPresent()) { + return validToken.get(); + } + return createAccessToken(user); + } + + private OAuth2AccessToken createAccessToken(IUser user) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + + token.setScope(Sets.asSet(OAuthScope.READ.getScope())); + + AuthorizationRequest request = new AuthorizationRequest(citesphereClientId, token.getScope()); + TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); + + OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(citesphereClientId), implicitRequest, user); + tokenStore.storeAccessToken(token, authentication); + System.out.println(extractTokenKey(token.getValue())); + return token; + } + + private OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest, IUser user) { + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); + Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getRoles()); + return new OAuth2Authentication(storedOAuth2Request, authentication); + } + + private String extractTokenKey(String value) { + if(value == null) { + return null; + } else { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException var5) { + throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); + } + + try { + byte[] e = digest.digest(value.getBytes("UTF-8")); + return String.format("%032x", new Object[]{new BigInteger(1, e)}); + } catch (UnsupportedEncodingException var4) { + throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); + } + } + } } From 57f6eea16224419169b56fcdf36b0e8678c61836 Mon Sep 17 00:00:00 2001 From: diya17 Date: Thu, 2 Nov 2023 17:01:37 -0700 Subject: [PATCH 04/28] [CITE-217] Adding CRUD operations --- .../core/model/oauth/IUserAccessToken.java | 33 ++++++ .../model/oauth/impl/UserAccessToken.java | 98 ++++++++++++++++ .../oauth/AccessTokenRepository.java | 11 -- .../oauth/UserAccessTokenRepository.java | 11 ++ .../core/service/oauth/IUserTokenManager.java | 8 +- .../oauth/UserAccessTokenResultPage.java | 26 +++++ .../oauth/impl/UserAccessTokenManager.java | 61 ++++++++++ .../service/oauth/impl/UserTokenManager.java | 106 ------------------ 8 files changed, 236 insertions(+), 118 deletions(-) create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java delete mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java delete mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java new file mode 100644 index 000000000..05ca4ccfb --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java @@ -0,0 +1,33 @@ +package edu.asu.diging.citesphere.core.model.oauth; + +import java.util.Collection; +import java.util.Set; + +import org.springframework.security.core.GrantedAuthority; + +import edu.asu.diging.citesphere.user.IUser; + +public interface IUserAccessToken { + + String getToken(); + + void setToken(String token); + + IUser getUser(); + + void setUser(IUser user); + + String getName(); + + void setName(String name); + + String getClientId(); + + Set getScope(); + + void setScope(Set scope); + + Collection getAuthorities(); + + void setAuthorities(Collection authorities); +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java new file mode 100644 index 000000000..8f7f4a396 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java @@ -0,0 +1,98 @@ +package edu.asu.diging.citesphere.core.model.oauth.impl; + +import java.util.Collection; +import java.util.Set; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Parameter; +import org.springframework.security.core.GrantedAuthority; + +import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; +import edu.asu.diging.citesphere.user.IUser; +import edu.asu.diging.citesphere.user.impl.User; + +@Entity +public class UserAccessToken implements IUserAccessToken { + + @Id + @GeneratedValue(generator = "access_token_id_generator") + @GenericGenerator(name = "access_token_id_generator", + parameters = @Parameter(name = "prefix", value = "AT"), + strategy = "edu.asu.diging.citesphere.core.repository.IdGenerator" + ) + private String clientId; + + private String token; + + private String name; + + @ElementCollection + private Collection authorities; + + @ElementCollection + private Set scope; + + @ManyToOne(targetEntity=User.class) + private IUser user; + + @Override + public String getToken() { + return token; + } + + @Override + public void setToken(String token) { + this.token = token; + } + + @Override + public IUser getUser() { + return user; + } + + @Override + public void setUser(IUser user) { + this.user = user; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public String getClientId() { + return clientId; + } + + @Override + public Set getScope() { + return scope; + } + + @Override + public void setScope(Set scope) { + this.scope = scope; + } + + @Override + public Collection getAuthorities() { + return authorities; + } + + @Override + public void setAuthorities(Collection authorities) { + this.authorities = authorities; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java deleted file mode 100644 index a90a0466a..000000000 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/AccessTokenRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package edu.asu.diging.citesphere.core.repository.oauth; - -import org.javers.spring.annotation.JaversSpringDataAuditable; -import org.springframework.data.repository.PagingAndSortingRepository; - -import edu.asu.diging.citesphere.user.impl.AccessToken; - -@JaversSpringDataAuditable -public interface AccessTokenRepository extends PagingAndSortingRepository { - -} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java new file mode 100644 index 000000000..46bdcd368 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java @@ -0,0 +1,11 @@ +package edu.asu.diging.citesphere.core.repository.oauth; + +import org.javers.spring.annotation.JaversSpringDataAuditable; +import org.springframework.data.jpa.repository.JpaRepository; + +import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; + +@JaversSpringDataAuditable +public interface UserAccessTokenRepository extends JpaRepository { + +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java index bb3b6a9ad..d63cb40d9 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java @@ -1,9 +1,15 @@ package edu.asu.diging.citesphere.core.service.oauth; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientRegistrationException; import edu.asu.diging.citesphere.user.IUser; public interface IUserTokenManager { - OAuth2AccessToken getAccessToken(IUser user); + + ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException; + + OAuthCredentials create(String name, IUser user); + } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java new file mode 100644 index 000000000..9c630ceee --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java @@ -0,0 +1,26 @@ +package edu.asu.diging.citesphere.core.service.oauth; + +import java.util.List; + +import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; + +public class UserAccessTokenResultPage { + private long totalPages; + private List accessTokenList; + + public long getTotalPages() { + return totalPages; + } + + public void setTotalPages(long totalPages) { + this.totalPages = totalPages; + } + + public List getClientList() { + return accessTokenList; + } + + public void setClientList(List accessTokenList) { + this.accessTokenList = accessTokenList; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java new file mode 100644 index 000000000..c34e56182 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -0,0 +1,61 @@ +package edu.asu.diging.citesphere.core.service.oauth.impl; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import javax.transaction.Transactional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientRegistrationException; + +import edu.asu.diging.citesphere.core.model.Role; +import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; +import edu.asu.diging.citesphere.core.repository.oauth.UserAccessTokenRepository; +import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; +import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; +import edu.asu.diging.citesphere.user.IUser; + +@Transactional +public class UserAccessTokenManager implements IUserTokenManager { + + @Autowired + private UserAccessTokenRepository userAccessTokenRepository; + + @Autowired + private BCryptPasswordEncoder bCryptPasswordEncoder; + + @Override + public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { + Optional userAccessTokenOptional = userAccessTokenRepository.findById(clientId); + if (userAccessTokenOptional.isPresent()) { + ClientDetails details = (ClientDetails) userAccessTokenOptional.get(); + return details; + } + throw new InvalidClientException("Client with id " + clientId + " does not exist."); + } + + @Override + public OAuthCredentials create(String name, IUser user) { + final UserAccessToken userAccessToken = new UserAccessToken(); + userAccessToken.setName(name); + String token = UUID.randomUUID().toString(); + userAccessToken.setToken(bCryptPasswordEncoder.encode(token)); + List authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); + userAccessToken.setAuthorities(authorities); + userAccessToken.setScope(new HashSet<>()); + userAccessToken.getScope().add(OAuthScope.READ.getScope()); + userAccessToken.setUser(user); + UserAccessToken storeToken = userAccessTokenRepository.save(userAccessToken); + return new OAuthCredentials(storeToken.getClientId(), token); + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java deleted file mode 100644 index 6fe607dfd..000000000 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserTokenManager.java +++ /dev/null @@ -1,106 +0,0 @@ -package edu.asu.diging.citesphere.core.service.oauth.impl; - -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Collection; -import java.util.Date; -import java.util.Optional; -import java.util.UUID; - -import javax.annotation.PostConstruct; -import javax.transaction.Transactional; -import javax.transaction.Transactional.TxType; - -import org.javers.common.collections.Sets; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.TokenRequest; -import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; -import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.token.TokenStore; - -import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; -import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; -import edu.asu.diging.citesphere.user.IUser; - -public class UserTokenManager implements IUserTokenManager { - - @Autowired - private TokenStore tokenStore; - - @Autowired - private ClientDetailsService clientDetailsService; - - @Value("${_citephere_oauth2_app_clientid}") - private String citesphereClientId; - - private OAuth2RequestFactory requestFactory; - - @PostConstruct - public void init() { - this.requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); - } - - @Override - @Transactional(TxType.REQUIRES_NEW) - public OAuth2AccessToken getAccessToken(IUser user) { - Collection tokens = tokenStore.findTokensByClientIdAndUserName(citesphereClientId, user.getUsername()); - Optional validToken = tokens.stream().filter(t -> !t.isExpired()).findFirst(); - if (validToken.isPresent()) { - return validToken.get(); - } - return createAccessToken(user); - } - - private OAuth2AccessToken createAccessToken(IUser user) { - DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - - token.setScope(Sets.asSet(OAuthScope.READ.getScope())); - - AuthorizationRequest request = new AuthorizationRequest(citesphereClientId, token.getScope()); - TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); - - OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(citesphereClientId), implicitRequest, user); - tokenStore.storeAccessToken(token, authentication); - System.out.println(extractTokenKey(token.getValue())); - return token; - } - - private OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest, IUser user) { - OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); - Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getRoles()); - return new OAuth2Authentication(storedOAuth2Request, authentication); - } - - private String extractTokenKey(String value) { - if(value == null) { - return null; - } else { - MessageDigest digest; - try { - digest = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException var5) { - throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); - } - - try { - byte[] e = digest.digest(value.getBytes("UTF-8")); - return String.format("%032x", new Object[]{new BigInteger(1, e)}); - } catch (UnsupportedEncodingException var4) { - throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); - } - } - } -} From befbf1d3fff94c523235e6033cee2c22748da991 Mon Sep 17 00:00:00 2001 From: diya17 Date: Fri, 3 Nov 2023 16:00:22 -0700 Subject: [PATCH 05/28] Extending user access token repository and manager --- .../oauth/UserAccessTokenRepository.java | 8 ++++- .../core/service/oauth/IUserTokenManager.java | 10 +++++++ .../oauth/impl/UserAccessTokenManager.java | 30 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java index 46bdcd368..6cc6b0483 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java @@ -1,11 +1,17 @@ package edu.asu.diging.citesphere.core.repository.oauth; +import java.util.List; + import org.javers.spring.annotation.JaversSpringDataAuditable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; +import edu.asu.diging.citesphere.user.IUser; @JaversSpringDataAuditable public interface UserAccessTokenRepository extends JpaRepository { - + Page findAllByUser(IUser user, Pageable pageable); + List findAllByUser(IUser user); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java index d63cb40d9..df64666c3 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java @@ -1,9 +1,13 @@ package edu.asu.diging.citesphere.core.service.oauth; +import java.util.List; + +import org.springframework.data.domain.Pageable; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; +import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; import edu.asu.diging.citesphere.user.IUser; public interface IUserTokenManager { @@ -11,5 +15,11 @@ public interface IUserTokenManager { ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException; OAuthCredentials create(String name, IUser user); + + UserAccessTokenResultPage getAllAccessTokensDetails(Pageable pageable, IUser user); + + List getAllUserAccessTokenDetails(IUser user); + + void deleteClient(String clientId); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java index c34e56182..a99c2943d 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -9,6 +9,8 @@ import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -17,11 +19,16 @@ import org.springframework.security.oauth2.provider.ClientRegistrationException; import edu.asu.diging.citesphere.core.model.Role; +import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; +import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; +import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; import edu.asu.diging.citesphere.core.repository.oauth.UserAccessTokenRepository; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.OAuthClientResultPage; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; +import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; import edu.asu.diging.citesphere.user.IUser; @Transactional @@ -58,4 +65,27 @@ public OAuthCredentials create(String name, IUser user) { UserAccessToken storeToken = userAccessTokenRepository.save(userAccessToken); return new OAuthCredentials(storeToken.getClientId(), token); } + + @Override + public UserAccessTokenResultPage getAllAccessTokensDetails(Pageable pageable, IUser user) { + List userAccessTokenList = new ArrayList<>(); + Page userAccessTokens = userAccessTokenRepository.findAllByUser(user, pageable); + userAccessTokens.forEach(userAccessToken -> userAccessTokenList.add(userAccessToken)); + UserAccessTokenResultPage result = new UserAccessTokenResultPage(); + result.setClientList(userAccessTokenList); + result.setTotalPages(userAccessTokens.getTotalPages()); + return result; + } + + @Override + public List getAllUserAccessTokenDetails(IUser user) { + return userAccessTokenRepository.findAllByUser(user); + } + + @Override + public void deleteClient(String clientId) { + if(clientId != null) { + userAccessTokenRepository.deleteById(clientId); + } + } } From ba2c4d15efbdf2faf7318c893ab6fd3f36f4ce9e Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 7 Nov 2023 13:00:15 -0700 Subject: [PATCH 06/28] [CITE-217] Adding Form and controller --- .../core/service/oauth/IUserTokenManager.java | 3 +++ .../oauth/impl/UserAccessTokenManager.java | 14 +++++++++++ .../web/admin/forms/UserAccessTokenForm.java | 12 +++++++++ .../AddUserAccessTokenController.java | 25 +++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java index df64666c3..c7c32bea7 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java @@ -7,6 +7,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; +import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; import edu.asu.diging.citesphere.user.IUser; @@ -21,5 +22,7 @@ public interface IUserTokenManager { List getAllUserAccessTokenDetails(IUser user); void deleteClient(String clientId); + + OAuthCredentials updateClientSecret(String clientId) throws CannotFindClientException; } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java index a99c2943d..7bc58bcb6 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -18,6 +18,7 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; +import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; import edu.asu.diging.citesphere.core.model.Role; import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; @@ -88,4 +89,17 @@ public void deleteClient(String clientId) { userAccessTokenRepository.deleteById(clientId); } } + + @Override + public OAuthCredentials updateClientSecret(String clientId) throws CannotFindClientException { + Optional userAccessTokenOptional = userAccessTokenRepository.findById(clientId); + if (userAccessTokenOptional.isPresent()) { + UserAccessToken accessToken = userAccessTokenOptional.get(); + String token = UUID.randomUUID().toString(); + accessToken.setToken(bCryptPasswordEncoder.encode(token)); + UserAccessToken storeAccessToken = userAccessTokenRepository.save(accessToken); + return new OAuthCredentials(storeAccessToken.getClientId(), token); + } + throw new CannotFindClientException("Client with id " + clientId + " does not exist."); + } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java new file mode 100644 index 000000000..e27638160 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java @@ -0,0 +1,12 @@ +package edu.asu.diging.citesphere.web.admin.forms; + +public class UserAccessTokenForm { + private String name; + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java new file mode 100644 index 000000000..67e39fd5b --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -0,0 +1,25 @@ +package edu.asu.diging.citesphere.web.admin.userOAuth; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +import edu.asu.diging.citesphere.web.admin.forms.AppForm; +import edu.asu.diging.citesphere.web.admin.forms.UserAccessTokenForm; + +@Controller +public class AddUserAccessTokenController { + @Autowired + private IUserTokenManager userTokenManager; + + @RequestMapping(value="/admin/users/accessTokens/add", method=RequestMethod.GET) + public String add(@Validated UserAccessTokenForm useerAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs) { + return "admin/users/accessTokens/add"; + } +} From 8beb5a3f729be1cc378aa871d0922090b1221b9b Mon Sep 17 00:00:00 2001 From: diya17 Date: Thu, 9 Nov 2023 16:30:26 -0700 Subject: [PATCH 07/28] [CITE-217] Adding controllers --- .../core/service/oauth/IUserTokenManager.java | 2 +- .../oauth/impl/UserAccessTokenManager.java | 2 +- .../AccessTokenDetailsController.java | 23 +++++++++++++ .../AddUserAccessTokenController.java | 17 ++++++++-- .../DeleteAccessTokenController.java | 21 ++++++++++++ .../userOAuth/ShowAccessTokensController.java | 32 +++++++++++++++++++ .../UpdateAccessTokenController.java | 22 +++++++++++++ 7 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java index c7c32bea7..363327258 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java @@ -23,6 +23,6 @@ public interface IUserTokenManager { void deleteClient(String clientId); - OAuthCredentials updateClientSecret(String clientId) throws CannotFindClientException; + OAuthCredentials updateSecret(String clientId) throws CannotFindClientException; } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java index 7bc58bcb6..4cc6f19c3 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -91,7 +91,7 @@ public void deleteClient(String clientId) { } @Override - public OAuthCredentials updateClientSecret(String clientId) throws CannotFindClientException { + public OAuthCredentials updateSecret(String clientId) throws CannotFindClientException { Optional userAccessTokenOptional = userAccessTokenRepository.findById(clientId); if (userAccessTokenOptional.isPresent()) { UserAccessToken accessToken = userAccessTokenOptional.get(); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java new file mode 100644 index 000000000..84a7fd537 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -0,0 +1,23 @@ +package edu.asu.diging.citesphere.web.admin.userOAuth; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; +import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; + +public class AccessTokenDetailsController { + @Autowired + private IUserTokenManager userTokenManager; + + @RequestMapping(value="/admin/users/accessTokens/{accessTokenId}", method=RequestMethod.GET) + public String showAppDetails(Model model, @PathVariable("accessTokenId") String accessTokenId) { + IUserAccessToken details = (IUserAccessToken) userTokenManager.loadClientByClientId(accessTokenId); + model.addAttribute("clientName", details.getName()); + model.addAttribute("clientId", details.getClientId()); + return "admin/users/accessTokenId/details"; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index 67e39fd5b..39d5a60fd 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -1,5 +1,7 @@ package edu.asu.diging.citesphere.web.admin.userOAuth; +import java.security.Principal; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -10,7 +12,9 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; -import edu.asu.diging.citesphere.web.admin.forms.AppForm; +import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; +import edu.asu.diging.citesphere.core.user.IUserManager; +import edu.asu.diging.citesphere.user.IUser; import edu.asu.diging.citesphere.web.admin.forms.UserAccessTokenForm; @Controller @@ -18,8 +22,15 @@ public class AddUserAccessTokenController { @Autowired private IUserTokenManager userTokenManager; + @Autowired + private IUserManager userManager; + @RequestMapping(value="/admin/users/accessTokens/add", method=RequestMethod.GET) - public String add(@Validated UserAccessTokenForm useerAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs) { - return "admin/users/accessTokens/add"; + public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs, Principal principal) { + IUser user = userManager.findByUsername(principal.getName()); + OAuthCredentials creds = userTokenManager.create(userAccessTokenForm.getName(), user); + redirectAttrs.addFlashAttribute("clientId", creds.getClientId()); + redirectAttrs.addFlashAttribute("secret", creds.getSecret()); + return "redirect:/admin/apps/" + creds.getClientId(); } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java new file mode 100644 index 000000000..23fa7ae9a --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -0,0 +1,21 @@ +package edu.asu.diging.citesphere.web.admin.userOAuth; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; + +public class DeleteAccessTokenController { + @Autowired + private IUserTokenManager userTokenManager; + + @RequestMapping(value = "/admin/apps/{accessTokenId}", method = RequestMethod.DELETE) + public ResponseEntity deleteApp(@PathVariable("accessTokenId") String accessTokenId) { + userTokenManager.deleteClient(accessTokenId); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java new file mode 100644 index 000000000..5cc52f006 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -0,0 +1,32 @@ +package edu.asu.diging.citesphere.web.admin.userOAuth; + +import java.security.Principal; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Pageable; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; +import edu.asu.diging.citesphere.core.user.IUserManager; +import edu.asu.diging.citesphere.user.IUser; + +public class ShowAccessTokensController { + @Autowired + private IUserTokenManager userTokenManager; + + @Autowired + private IUserManager userManager; + + @RequestMapping(value="/admin/users/accessTokens", method=RequestMethod.GET) + public String showAllApps(Model model, Pageable pageable, Principal principal) { + IUser user = userManager.findByUsername(principal.getName()); + UserAccessTokenResultPage result = userTokenManager.getAllAccessTokensDetails(pageable, user); + model.addAttribute("clientList", result.getClientList()); + model.addAttribute("currentPage", pageable.getPageNumber()+1); + model.addAttribute("totalPages", result.getTotalPages()); + return "admin/apps/show"; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java new file mode 100644 index 000000000..62856d802 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -0,0 +1,22 @@ +package edu.asu.diging.citesphere.web.admin.userOAuth; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; +import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; + +public class UpdateAccessTokenController { + @Autowired + private IUserTokenManager userTokenManager; + + @RequestMapping(value="/admin/apps/{accessTokenId}/secret/update", method=RequestMethod.POST) + public @ResponseBody OAuthCredentials regenerateClientSecret(Model model, @PathVariable("accessTokenId") String accessTokenId) throws CannotFindClientException { + return userTokenManager.updateSecret(accessTokenId); + } +} From 78d74b904509d16b4406e3f6618a8f998a9b1bef Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 14 Nov 2023 13:00:16 -0700 Subject: [PATCH 08/28] [CITE-217] : Controllers and views --- .../AccessTokenDetailsController.java | 2 +- .../AddUserAccessTokenController.java | 2 +- .../userOAuth/ShowAccessTokensController.java | 2 +- .../WEB-INF/views/admin/user/auth/add.html | 15 +++ .../WEB-INF/views/admin/user/auth/show.html | 115 ++++++++++++++++++ 5 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html create mode 100644 citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java index 84a7fd537..2cf8edc09 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -18,6 +18,6 @@ public String showAppDetails(Model model, @PathVariable("accessTokenId") String IUserAccessToken details = (IUserAccessToken) userTokenManager.loadClientByClientId(accessTokenId); model.addAttribute("clientName", details.getName()); model.addAttribute("clientId", details.getClientId()); - return "admin/users/accessTokenId/details"; + return "admin/user/auth/accessTokenId/details"; } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index 39d5a60fd..3865ed94b 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -31,6 +31,6 @@ public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model mode OAuthCredentials creds = userTokenManager.create(userAccessTokenForm.getName(), user); redirectAttrs.addFlashAttribute("clientId", creds.getClientId()); redirectAttrs.addFlashAttribute("secret", creds.getSecret()); - return "redirect:/admin/apps/" + creds.getClientId(); + return "redirect:/admin/user/auth" + creds.getClientId(); } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java index 5cc52f006..1c51f1feb 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -27,6 +27,6 @@ public String showAllApps(Model model, Pageable pageable, Principal principal) { model.addAttribute("clientList", result.getClientList()); model.addAttribute("currentPage", pageable.getPageNumber()+1); model.addAttribute("totalPages", result.getTotalPages()); - return "admin/apps/show"; + return "admin/user/auth/show"; } } diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html new file mode 100644 index 000000000..54974ddef --- /dev/null +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html @@ -0,0 +1,15 @@ + + +

Add User Access Token

+
+
+ + + + +

+ + + +
+
diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html new file mode 100644 index 000000000..bfd7ae6d8 --- /dev/null +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html @@ -0,0 +1,115 @@ + + + + + + + + + + + +
+

Apps

+
    + + + + + + + + + + + + +
    Client IdNameDescription + +
    + + +
    + + From d0b037d61a45e57e4e0c850ed0a70a2df27a9c2d Mon Sep 17 00:00:00 2001 From: diya17 Date: Thu, 16 Nov 2023 16:31:02 -0700 Subject: [PATCH 09/28] [CITE-217] Adding views for details --- .../DeleteAccessTokenController.java | 2 +- .../UpdateAccessTokenController.java | 2 +- .../views/admin/user/auth/details.html | 103 ++++++++++++++++++ .../WEB-INF/views/admin/user/auth/show.html | 11 +- 4 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java index 23fa7ae9a..e10f53289 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -13,7 +13,7 @@ public class DeleteAccessTokenController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value = "/admin/apps/{accessTokenId}", method = RequestMethod.DELETE) + @RequestMapping(value = "/admin/users/accessTokens/{accessTokenId}", method = RequestMethod.DELETE) public ResponseEntity deleteApp(@PathVariable("accessTokenId") String accessTokenId) { userTokenManager.deleteClient(accessTokenId); return new ResponseEntity<>(HttpStatus.OK); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java index 62856d802..fe2046698 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -15,7 +15,7 @@ public class UpdateAccessTokenController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value="/admin/apps/{accessTokenId}/secret/update", method=RequestMethod.POST) + @RequestMapping(value="/admin/users/{accessTokenId}/secret/update", method=RequestMethod.POST) public @ResponseBody OAuthCredentials regenerateClientSecret(Model model, @PathVariable("accessTokenId") String accessTokenId) throws CannotFindClientException { return userTokenManager.updateSecret(accessTokenId); } diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html new file mode 100644 index 000000000..a2d6f9bf7 --- /dev/null +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html @@ -0,0 +1,103 @@ + + + + + + + +
    +
    +
    +
    +
    +    +
    + +
    +

    +
    + + + + + + + + + + + + + + + + + + + +
    Client Id
    Token*Secret Key is hidden*
    Name
    + + +
    + + diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html index bfd7ae6d8..25f945169 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html @@ -15,7 +15,7 @@ visiblePages: 10, initiateStartPageClick: false, onPageClick: function (event, page) { - window.location.href = "apps?page=" + (page-1); + window.location.href = "admin/users/accessTokens?page=" + (page-1); } }); }); @@ -30,13 +30,13 @@ }); $("#delete-client-button").click(function() { var id = $(this).data("client-id"); - var baseurl = 'apps/' + id; + var baseurl = 'admin/users/acessTokens/' + id; $.ajax({ 'url': baseurl + "?[(${_csrf.parameterName})]=[(${_csrf.token})]", 'type': "DELETE", 'success': function(data) { $("#tr-" + id).remove(); - $.notify(' App successfully deleted!', { + $.notify(' Access Token successfully deleted!', { type: 'success', offset: { x: 50, @@ -49,7 +49,7 @@ }); }, 'error': function(data) { - $.notify(' App could not be deleted!', { + $.notify(' Access Token could not be deleted!', { type: 'danger', offset: { x: 50, @@ -75,14 +75,13 @@
    -

    Apps

    +

    Tokens

      - From 24c634887b3fc091fc464da8f82b1596bd4d77af Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 21 Nov 2023 13:02:05 -0700 Subject: [PATCH 10/28] [CITE-217] Changing endpoints --- .../core/service/oauth/impl/UserAccessTokenManager.java | 2 ++ .../web/admin/userOAuth/AccessTokenDetailsController.java | 2 +- .../web/admin/userOAuth/AddUserAccessTokenController.java | 2 +- .../web/admin/userOAuth/DeleteAccessTokenController.java | 2 +- .../web/admin/userOAuth/ShowAccessTokensController.java | 2 +- .../web/admin/userOAuth/UpdateAccessTokenController.java | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java index 4cc6f19c3..c513c5d83 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -17,6 +17,7 @@ import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientRegistrationException; +import org.springframework.stereotype.Service; import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; import edu.asu.diging.citesphere.core.model.Role; @@ -32,6 +33,7 @@ import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; import edu.asu.diging.citesphere.user.IUser; +@Service @Transactional public class UserAccessTokenManager implements IUserTokenManager { diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java index 2cf8edc09..c28daff50 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -13,7 +13,7 @@ public class AccessTokenDetailsController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value="/admin/users/accessTokens/{accessTokenId}", method=RequestMethod.GET) + @RequestMapping(value="/admin/user/accessTokens/{accessTokenId}", method=RequestMethod.GET) public String showAppDetails(Model model, @PathVariable("accessTokenId") String accessTokenId) { IUserAccessToken details = (IUserAccessToken) userTokenManager.loadClientByClientId(accessTokenId); model.addAttribute("clientName", details.getName()); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index 3865ed94b..e901ea902 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -25,7 +25,7 @@ public class AddUserAccessTokenController { @Autowired private IUserManager userManager; - @RequestMapping(value="/admin/users/accessTokens/add", method=RequestMethod.GET) + @RequestMapping(value="/admin/user/accessTokens/add", method=RequestMethod.GET) public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); OAuthCredentials creds = userTokenManager.create(userAccessTokenForm.getName(), user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java index e10f53289..9912dce63 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -13,7 +13,7 @@ public class DeleteAccessTokenController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value = "/admin/users/accessTokens/{accessTokenId}", method = RequestMethod.DELETE) + @RequestMapping(value = "/admin/user/accessTokens/{accessTokenId}", method = RequestMethod.DELETE) public ResponseEntity deleteApp(@PathVariable("accessTokenId") String accessTokenId) { userTokenManager.deleteClient(accessTokenId); return new ResponseEntity<>(HttpStatus.OK); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java index 1c51f1feb..d3e6e3f21 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -20,7 +20,7 @@ public class ShowAccessTokensController { @Autowired private IUserManager userManager; - @RequestMapping(value="/admin/users/accessTokens", method=RequestMethod.GET) + @RequestMapping(value="/admin/user/accessTokens", method=RequestMethod.GET) public String showAllApps(Model model, Pageable pageable, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); UserAccessTokenResultPage result = userTokenManager.getAllAccessTokensDetails(pageable, user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java index fe2046698..82c3e3183 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -15,7 +15,7 @@ public class UpdateAccessTokenController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value="/admin/users/{accessTokenId}/secret/update", method=RequestMethod.POST) + @RequestMapping(value="/admin/user/{accessTokenId}/secret/update", method=RequestMethod.POST) public @ResponseBody OAuthCredentials regenerateClientSecret(Model model, @PathVariable("accessTokenId") String accessTokenId) throws CannotFindClientException { return userTokenManager.updateSecret(accessTokenId); } From 8d4de31d0c27d7fc2102beedab1272f3666719b6 Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 28 Nov 2023 13:00:17 -0700 Subject: [PATCH 11/28] [CITE-217] Adding to the header --- .../citesphere/core/model/oauth/impl/UserAccessToken.java | 2 +- citesphere/src/main/webapp/WEB-INF/views/layouts/main.html | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java index 8f7f4a396..92278b8fa 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java @@ -23,7 +23,7 @@ public class UserAccessToken implements IUserAccessToken { @Id @GeneratedValue(generator = "access_token_id_generator") @GenericGenerator(name = "access_token_id_generator", - parameters = @Parameter(name = "prefix", value = "AT"), + parameters = @Parameter(name = "prefix", value = "ACCESSTOKEN"), strategy = "edu.asu.diging.citesphere.core.repository.IdGenerator" ) private String clientId; diff --git a/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html b/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html index db0d1104e..e76bcc5d1 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html +++ b/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html @@ -67,6 +67,8 @@
    • Date: Thu, 25 Jan 2024 16:29:51 -0700 Subject: [PATCH 12/28] [CITE-217] Making changes to controllers and views --- .../citesphere/core/service/oauth/IUserTokenManager.java | 2 +- .../core/service/oauth/impl/UserAccessTokenManager.java | 4 ++-- .../admin/userOAuth/AccessTokenDetailsController.java | 6 ++++-- .../admin/userOAuth/AddUserAccessTokenController.java | 9 ++++++++- .../web/admin/userOAuth/DeleteAccessTokenController.java | 2 ++ .../web/admin/userOAuth/ShowAccessTokensController.java | 2 ++ .../web/admin/userOAuth/UpdateAccessTokenController.java | 2 ++ .../main/webapp/WEB-INF/views/admin/user/auth/add.html | 2 +- .../webapp/WEB-INF/views/admin/user/auth/details.html | 2 +- .../main/webapp/WEB-INF/views/admin/user/auth/show.html | 6 +++--- 10 files changed, 26 insertions(+), 11 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java index 363327258..8afe0a48e 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java @@ -13,7 +13,7 @@ public interface IUserTokenManager { - ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException; + UserAccessToken loadClientByClientId(String clientId) throws ClientRegistrationException; OAuthCredentials create(String name, IUser user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java index c513c5d83..bacc9cff8 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -44,10 +44,10 @@ public class UserAccessTokenManager implements IUserTokenManager { private BCryptPasswordEncoder bCryptPasswordEncoder; @Override - public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { + public UserAccessToken loadClientByClientId(String clientId) throws ClientRegistrationException { Optional userAccessTokenOptional = userAccessTokenRepository.findById(clientId); if (userAccessTokenOptional.isPresent()) { - ClientDetails details = (ClientDetails) userAccessTokenOptional.get(); + UserAccessToken details = (UserAccessToken) userAccessTokenOptional.get(); return details; } throw new InvalidClientException("Client with id " + clientId + " does not exist."); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java index c28daff50..b14afeda5 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -1,6 +1,7 @@ package edu.asu.diging.citesphere.web.admin.userOAuth; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -9,15 +10,16 @@ import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +@Controller public class AccessTokenDetailsController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value="/admin/user/accessTokens/{accessTokenId}", method=RequestMethod.GET) + @RequestMapping(value="/admin/user/auth/{accessTokenId}", method=RequestMethod.GET) public String showAppDetails(Model model, @PathVariable("accessTokenId") String accessTokenId) { IUserAccessToken details = (IUserAccessToken) userTokenManager.loadClientByClientId(accessTokenId); model.addAttribute("clientName", details.getName()); model.addAttribute("clientId", details.getClientId()); - return "admin/user/auth/accessTokenId/details"; + return "admin/user/auth/details"; } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index e901ea902..2bb52d221 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -15,6 +15,7 @@ import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; +import edu.asu.diging.citesphere.web.admin.forms.AppForm; import edu.asu.diging.citesphere.web.admin.forms.UserAccessTokenForm; @Controller @@ -26,11 +27,17 @@ public class AddUserAccessTokenController { private IUserManager userManager; @RequestMapping(value="/admin/user/accessTokens/add", method=RequestMethod.GET) + public String show(Model model) { + model.addAttribute("userAccessTokenForm", new UserAccessTokenForm()); + return "admin/user/auth/add"; + } + + @RequestMapping(value="/admin/user/accessTokens/add", method=RequestMethod.POST) public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); OAuthCredentials creds = userTokenManager.create(userAccessTokenForm.getName(), user); redirectAttrs.addFlashAttribute("clientId", creds.getClientId()); redirectAttrs.addFlashAttribute("secret", creds.getSecret()); - return "redirect:/admin/user/auth" + creds.getClientId(); + return "redirect:/admin/user/auth/" + creds.getClientId(); } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java index 9912dce63..f278c5986 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -3,12 +3,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; +@Controller public class DeleteAccessTokenController { @Autowired private IUserTokenManager userTokenManager; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java index d3e6e3f21..77f8dbd23 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -13,6 +14,7 @@ import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; +@Controller public class ShowAccessTokensController { @Autowired private IUserTokenManager userTokenManager; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java index 82c3e3183..7c03462ed 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -1,6 +1,7 @@ package edu.asu.diging.citesphere.web.admin.userOAuth; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -11,6 +12,7 @@ import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; +@Controller public class UpdateAccessTokenController { @Autowired private IUserTokenManager userTokenManager; diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html index 54974ddef..5f06dabc7 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html @@ -2,7 +2,7 @@

      Add User Access Token

      -
      + diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html index a2d6f9bf7..b3e2ec319 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html @@ -10,7 +10,7 @@ }); $("#update-client-button").click(function() { - var url = "admin/users/[(${clientId})]/secret/update"; + var url = "admin/user/[(${clientId})]/secret/update"; $.ajax({ 'url': url + "?[(${_csrf.parameterName})]=[(${_csrf.token})]", 'type': "POST", diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html index 25f945169..f9aee5738 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html @@ -15,7 +15,7 @@ visiblePages: 10, initiateStartPageClick: false, onPageClick: function (event, page) { - window.location.href = "admin/users/accessTokens?page=" + (page-1); + window.location.href = "admin/user/accessTokens?page=" + (page-1); } }); }); @@ -30,7 +30,7 @@ }); $("#delete-client-button").click(function() { var id = $(this).data("client-id"); - var baseurl = 'admin/users/acessTokens/' + id; + var baseurl = 'admin/user/acessTokens/' + id; $.ajax({ 'url': baseurl + "?[(${_csrf.parameterName})]=[(${_csrf.token})]", 'type': "DELETE", @@ -77,7 +77,7 @@
    • Client Id NameDescription
      From 5c320f363db1d6092a0ef7ce5dcd1feba4af6f68 Mon Sep 17 00:00:00 2001 From: diya17 Date: Fri, 26 Jan 2024 16:30:35 -0700 Subject: [PATCH 13/28] [CITE-217] Fixing issues with deletion and regeneration --- .../citesphere/web/admin/forms/UserAccessTokenForm.java | 8 ++++++++ .../web/admin/userOAuth/AccessTokenDetailsController.java | 2 +- .../web/admin/userOAuth/AddUserAccessTokenController.java | 5 ++--- .../web/admin/userOAuth/DeleteAccessTokenController.java | 2 +- .../web/admin/userOAuth/ShowAccessTokensController.java | 2 +- .../web/admin/userOAuth/UpdateAccessTokenController.java | 2 +- .../main/webapp/WEB-INF/views/admin/user/auth/add.html | 2 +- .../webapp/WEB-INF/views/admin/user/auth/details.html | 2 +- .../main/webapp/WEB-INF/views/admin/user/auth/show.html | 6 +++--- 9 files changed, 19 insertions(+), 12 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java index e27638160..347ad0015 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/forms/UserAccessTokenForm.java @@ -2,6 +2,7 @@ public class UserAccessTokenForm { private String name; + private String redirectUrl; public String getName() { return name; @@ -9,4 +10,11 @@ public String getName() { public void setName(String name) { this.name = name; } + + public String getRedirectUrl() { + return redirectUrl; + } + public void setRedirectUrl(String callbackUrl) { + this.redirectUrl = callbackUrl; + } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java index b14afeda5..151d45001 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -15,7 +15,7 @@ public class AccessTokenDetailsController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value="/admin/user/auth/{accessTokenId}", method=RequestMethod.GET) + @RequestMapping(value="/admin/user/auth/accessTokens/{accessTokenId}", method=RequestMethod.GET) public String showAppDetails(Model model, @PathVariable("accessTokenId") String accessTokenId) { IUserAccessToken details = (IUserAccessToken) userTokenManager.loadClientByClientId(accessTokenId); model.addAttribute("clientName", details.getName()); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index 2bb52d221..833c76716 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -15,7 +15,6 @@ import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; -import edu.asu.diging.citesphere.web.admin.forms.AppForm; import edu.asu.diging.citesphere.web.admin.forms.UserAccessTokenForm; @Controller @@ -26,13 +25,13 @@ public class AddUserAccessTokenController { @Autowired private IUserManager userManager; - @RequestMapping(value="/admin/user/accessTokens/add", method=RequestMethod.GET) + @RequestMapping(value="/admin/user/auth/accessTokens/add", method=RequestMethod.GET) public String show(Model model) { model.addAttribute("userAccessTokenForm", new UserAccessTokenForm()); return "admin/user/auth/add"; } - @RequestMapping(value="/admin/user/accessTokens/add", method=RequestMethod.POST) + @RequestMapping(value="/admin/user/auth/accessTokens/add", method=RequestMethod.POST) public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); OAuthCredentials creds = userTokenManager.create(userAccessTokenForm.getName(), user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java index f278c5986..19668a57d 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -15,7 +15,7 @@ public class DeleteAccessTokenController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value = "/admin/user/accessTokens/{accessTokenId}", method = RequestMethod.DELETE) + @RequestMapping(value = "/admin/user/auth/accessTokens/{accessTokenId}", method = RequestMethod.DELETE) public ResponseEntity deleteApp(@PathVariable("accessTokenId") String accessTokenId) { userTokenManager.deleteClient(accessTokenId); return new ResponseEntity<>(HttpStatus.OK); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java index 77f8dbd23..e89d63207 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -22,7 +22,7 @@ public class ShowAccessTokensController { @Autowired private IUserManager userManager; - @RequestMapping(value="/admin/user/accessTokens", method=RequestMethod.GET) + @RequestMapping(value="/admin/user/auth/accessTokens", method=RequestMethod.GET) public String showAllApps(Model model, Pageable pageable, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); UserAccessTokenResultPage result = userTokenManager.getAllAccessTokensDetails(pageable, user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java index 7c03462ed..3e0d73856 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -17,7 +17,7 @@ public class UpdateAccessTokenController { @Autowired private IUserTokenManager userTokenManager; - @RequestMapping(value="/admin/user/{accessTokenId}/secret/update", method=RequestMethod.POST) + @RequestMapping(value="/admin/user/auth/accessTokens/{accessTokenId}/secret/update", method=RequestMethod.POST) public @ResponseBody OAuthCredentials regenerateClientSecret(Model model, @PathVariable("accessTokenId") String accessTokenId) throws CannotFindClientException { return userTokenManager.updateSecret(accessTokenId); } diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html index 5f06dabc7..e07d7619e 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/add.html @@ -2,7 +2,7 @@

      Add User Access Token

      - + diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html index b3e2ec319..5650afe37 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html @@ -10,7 +10,7 @@ }); $("#update-client-button").click(function() { - var url = "admin/user/[(${clientId})]/secret/update"; + var url = "[(${clientId})]/secret/update"; $.ajax({ 'url': url + "?[(${_csrf.parameterName})]=[(${_csrf.token})]", 'type': "POST", diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html index f9aee5738..005e0e16c 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html @@ -30,7 +30,7 @@ }); $("#delete-client-button").click(function() { var id = $(this).data("client-id"); - var baseurl = 'admin/user/acessTokens/' + id; + var baseurl = 'accessTokens/' + id; $.ajax({ 'url': baseurl + "?[(${_csrf.parameterName})]=[(${_csrf.token})]", 'type': "DELETE", @@ -86,8 +86,8 @@

      Tokens

      - - + +
      Client Id
      From 0086228e2cc37d8d793481e34e506a46acdef558 Mon Sep 17 00:00:00 2001 From: diya17 Date: Mon, 29 Jan 2024 16:00:07 -0700 Subject: [PATCH 14/28] [CITE-217] Changing token implementation to implicit token --- .../oauth/impl/UserAccessTokenManager.java | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java index bacc9cff8..3ac783adf 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -6,17 +6,32 @@ import java.util.Optional; import java.util.UUID; +import javax.annotation.PostConstruct; import javax.transaction.Transactional; +import org.javers.common.collections.Sets; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientRegistrationException; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; import org.springframework.stereotype.Service; import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; @@ -34,15 +49,30 @@ import edu.asu.diging.citesphere.user.IUser; @Service +@PropertySource({ "classpath:config.properties", "${appConfigFile:classpath:}/app.properties" }) +@SuppressWarnings("deprecation") @Transactional public class UserAccessTokenManager implements IUserTokenManager { - + + @Value("${_citephere_oauth2_app_clientid}") + private String citesphereClientId; + @Autowired private UserAccessTokenRepository userAccessTokenRepository; @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; + @Autowired + private ClientDetailsService clientDetailsService; + + private OAuth2RequestFactory requestFactory; + + @PostConstruct + public void init() { + this.requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); + } + @Override public UserAccessToken loadClientByClientId(String clientId) throws ClientRegistrationException { Optional userAccessTokenOptional = userAccessTokenRepository.findById(clientId); @@ -56,9 +86,14 @@ public UserAccessToken loadClientByClientId(String clientId) throws ClientRegist @Override public OAuthCredentials create(String name, IUser user) { final UserAccessToken userAccessToken = new UserAccessToken(); - userAccessToken.setName(name); + userAccessToken.setName(name); String token = UUID.randomUUID().toString(); - userAccessToken.setToken(bCryptPasswordEncoder.encode(token)); +// userAccessToken.setToken(bCryptPasswordEncoder.encode(token)); + DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + accessToken.setScope(Sets.asSet(OAuthScope.READ.getScope())); + AuthorizationRequest request = new AuthorizationRequest(citesphereClientId, accessToken.getScope()); + TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); + OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(citesphereClientId), implicitRequest, user); List authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); userAccessToken.setAuthorities(authorities); @@ -66,9 +101,16 @@ public OAuthCredentials create(String name, IUser user) { userAccessToken.getScope().add(OAuthScope.READ.getScope()); userAccessToken.setUser(user); UserAccessToken storeToken = userAccessTokenRepository.save(userAccessToken); + return new OAuthCredentials(storeToken.getClientId(), token); } + private OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest, IUser user) { + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); + Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getRoles()); + return new OAuth2Authentication(storedOAuth2Request, authentication); + } + @Override public UserAccessTokenResultPage getAllAccessTokensDetails(Pageable pageable, IUser user) { List userAccessTokenList = new ArrayList<>(); From 163a27c74ed3c1986bafb034fd932744010f30d1 Mon Sep 17 00:00:00 2001 From: diya17 Date: Wed, 31 Jan 2024 16:00:26 -0700 Subject: [PATCH 15/28] [CITE-217] Extending Oauthclient manager --- .../citesphere/core/model/oauth/IOAuthClient.java | 5 +++-- .../core/model/oauth/impl/OAuthClient.java | 11 +++++++++++ .../repository/oauth/OAuthClientRepository.java | 6 +++++- .../core/service/oauth/IOAuthClientManager.java | 7 ++++++- .../service/oauth/UserAccessTokenResultPage.java | 7 ++++--- .../core/service/oauth/impl/OAuthClientManager.java | 13 +++++++++++++ .../service/oauth/impl/UserAccessTokenManager.java | 10 +++++----- .../admin/userOAuth/ShowAccessTokensController.java | 6 +++++- 8 files changed, 52 insertions(+), 13 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java index 003dac610..9860a2801 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java @@ -65,7 +65,8 @@ public interface IOAuthClient { void setDescription(String description); String getDescription(); - - + boolean getIsUserAccessToken(); + + void setisUserAccessToken(boolean isUserAccessToken); } \ No newline at end of file diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java index 181734e94..5ff13dc6c 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java @@ -46,6 +46,7 @@ public class OAuthClient implements IOAuthClient, ClientDetails { private int accessTokenValiditySeconds; private int refereshTokenValiditySeconds; private boolean autoApprove; + private boolean isUserAccessToken; @Override public String getClientId() { @@ -192,4 +193,14 @@ public void setRefereshTokenValiditySeconds(int refereshTokenValiditySeconds) { public void setAutoApprove(boolean autoApprove) { this.autoApprove = autoApprove; } + + @Override + public boolean getIsUserAccessToken() { + return isUserAccessToken; + } + + @Override + public void setisUserAccessToken(boolean isUserAccessToken) { + this.isUserAccessToken = isUserAccessToken; + } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java index ba5ab461a..01f967674 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java @@ -1,9 +1,13 @@ package edu.asu.diging.citesphere.core.repository.oauth; +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; public interface OAuthClientRepository extends JpaRepository { - + Page findByIsUserAccessTokenAndCreatedBy_Username(boolean isUserAccessToken, String createdByUsername, Pageable pageable); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java index 9bccc4459..c83fe4c45 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java @@ -10,6 +10,7 @@ import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; +import edu.asu.diging.citesphere.user.IUser; public interface IOAuthClientManager { @@ -26,4 +27,8 @@ public interface IOAuthClientManager { OAuthCredentials updateClientSecret(String clientId) throws CannotFindClientException; List getClientsDetails(List clientList); -} \ No newline at end of file + + UserAccessTokenResultPage getAllUserAccessTokenDetails(Pageable pageable, IUser user); + + OAuthCredentials createUserAccessToken(String name, IUser user); +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java index 9c630ceee..ab9ebac3c 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/UserAccessTokenResultPage.java @@ -2,11 +2,12 @@ import java.util.List; +import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; public class UserAccessTokenResultPage { private long totalPages; - private List accessTokenList; + private List accessTokenList; public long getTotalPages() { return totalPages; @@ -16,11 +17,11 @@ public void setTotalPages(long totalPages) { this.totalPages = totalPages; } - public List getClientList() { + public List getClientList() { return accessTokenList; } - public void setClientList(List accessTokenList) { + public void setClientList(List accessTokenList) { this.accessTokenList = accessTokenList; } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java index 455abd682..6d4fcf123 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java @@ -29,6 +29,8 @@ import edu.asu.diging.citesphere.core.service.oauth.OAuthClientResultPage; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; +import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; +import edu.asu.diging.citesphere.user.IUser; @Transactional public class OAuthClientManager implements ClientDetailsService, IOAuthClientManager { @@ -129,4 +131,15 @@ public List getClientsDetails(List clientList){ } return clients; } + + @Override + public UserAccessTokenResultPage getAllUserAccessTokenDetails(Pageable pageable, IUser user) { + List clientList = new ArrayList<>(); + Page userAccessClients = clientRepo.findByIsUserAccessTokenAndCreatedBy_Username(true, user.getUsername(), pageable); + userAccessClients.forEach(oAuthClient -> clientList.add(oAuthClient)); + UserAccessTokenResultPage result = new UserAccessTokenResultPage(); + result.setClientList(clientList); + result.setTotalPages(userAccessClients.getTotalPages()); + return result; + } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java index 3ac783adf..a9956b9a7 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java @@ -90,10 +90,7 @@ public OAuthCredentials create(String name, IUser user) { String token = UUID.randomUUID().toString(); // userAccessToken.setToken(bCryptPasswordEncoder.encode(token)); DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - accessToken.setScope(Sets.asSet(OAuthScope.READ.getScope())); - AuthorizationRequest request = new AuthorizationRequest(citesphereClientId, accessToken.getScope()); - TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); - OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(citesphereClientId), implicitRequest, user); + List authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); userAccessToken.setAuthorities(authorities); @@ -101,7 +98,10 @@ public OAuthCredentials create(String name, IUser user) { userAccessToken.getScope().add(OAuthScope.READ.getScope()); userAccessToken.setUser(user); UserAccessToken storeToken = userAccessTokenRepository.save(userAccessToken); - + accessToken.setScope(Sets.asSet(OAuthScope.READ.getScope())); + AuthorizationRequest request = new AuthorizationRequest(citesphereClientId, accessToken.getScope()); + TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); + OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(citesphereClientId), implicitRequest, user); return new OAuthCredentials(storeToken.getClientId(), token); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java index e89d63207..14b759924 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; import edu.asu.diging.citesphere.core.user.IUserManager; @@ -22,10 +23,13 @@ public class ShowAccessTokensController { @Autowired private IUserManager userManager; + @Autowired + private IOAuthClientManager clientManager; + @RequestMapping(value="/admin/user/auth/accessTokens", method=RequestMethod.GET) public String showAllApps(Model model, Pageable pageable, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); - UserAccessTokenResultPage result = userTokenManager.getAllAccessTokensDetails(pageable, user); + UserAccessTokenResultPage result = clientManager.getAllUserAccessTokenDetails(pageable, user); model.addAttribute("clientList", result.getClientList()); model.addAttribute("currentPage", pageable.getPageNumber()+1); model.addAttribute("totalPages", result.getTotalPages()); From a4047a138e7e59cc3138eadd11ae9f13c5b6556e Mon Sep 17 00:00:00 2001 From: diya17 Date: Fri, 2 Feb 2024 12:50:36 -0700 Subject: [PATCH 16/28] [CITE-217] Changing CRUD to OauthClient --- .../oauth/impl/OAuthClientManager.java | 26 +++++++++++++++++++ .../AccessTokenDetailsController.java | 7 ++++- .../AddUserAccessTokenController.java | 6 ++++- .../DeleteAccessTokenController.java | 6 ++++- .../UpdateAccessTokenController.java | 6 ++++- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java index 6d4fcf123..5f309cab5 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java @@ -9,21 +9,30 @@ import javax.transaction.Transactional; +import org.javers.common.collections.Sets; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; +import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientRegistrationException; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; +import edu.asu.diging.citesphere.core.model.Role; import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; +import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; import edu.asu.diging.citesphere.core.repository.oauth.OAuthClientRepository; import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; import edu.asu.diging.citesphere.core.service.oauth.OAuthClientResultPage; @@ -142,4 +151,21 @@ public UserAccessTokenResultPage getAllUserAccessTokenDetails(Pageable pageable, result.setTotalPages(userAccessClients.getTotalPages()); return result; } + + @Override + public OAuthCredentials createUserAccessToken(String name, IUser user) { + final OAuthClient client = new OAuthClient(); + client.setName(name); + String clientSecret = UUID.randomUUID().toString(); + client.setClientSecret(bCryptPasswordEncoder.encode(clientSecret)); + final UserAccessToken userAccessToken = new UserAccessToken(); + userAccessToken.setName(name); + List authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); + client.setAuthorities(authorities); + client.setScope(new HashSet<>()); + client.getScope().add(OAuthScope.READ.getScope()); + OAuthClient storeClient = clientRepo.save(client); + return new OAuthCredentials(storeClient.getClientId(), clientSecret); + } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java index 151d45001..78630012f 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -7,7 +7,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; +import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; @Controller @@ -15,9 +17,12 @@ public class AccessTokenDetailsController { @Autowired private IUserTokenManager userTokenManager; + @Autowired + private IOAuthClientManager clientManager; + @RequestMapping(value="/admin/user/auth/accessTokens/{accessTokenId}", method=RequestMethod.GET) public String showAppDetails(Model model, @PathVariable("accessTokenId") String accessTokenId) { - IUserAccessToken details = (IUserAccessToken) userTokenManager.loadClientByClientId(accessTokenId); + IOAuthClient details = (IOAuthClient) userTokenManager.loadClientByClientId(accessTokenId); model.addAttribute("clientName", details.getName()); model.addAttribute("clientId", details.getClientId()); return "admin/user/auth/details"; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index 833c76716..6a109660e 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.user.IUserManager; @@ -25,6 +26,9 @@ public class AddUserAccessTokenController { @Autowired private IUserManager userManager; + @Autowired + private IOAuthClientManager clientManager; + @RequestMapping(value="/admin/user/auth/accessTokens/add", method=RequestMethod.GET) public String show(Model model) { model.addAttribute("userAccessTokenForm", new UserAccessTokenForm()); @@ -34,7 +38,7 @@ public String show(Model model) { @RequestMapping(value="/admin/user/auth/accessTokens/add", method=RequestMethod.POST) public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); - OAuthCredentials creds = userTokenManager.create(userAccessTokenForm.getName(), user); + OAuthCredentials creds = clientManager.createUserAccessToken(userAccessTokenForm.getName(), user); redirectAttrs.addFlashAttribute("clientId", creds.getClientId()); redirectAttrs.addFlashAttribute("secret", creds.getSecret()); return "redirect:/admin/user/auth/" + creds.getClientId(); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java index 19668a57d..30052c733 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; @Controller @@ -15,9 +16,12 @@ public class DeleteAccessTokenController { @Autowired private IUserTokenManager userTokenManager; + @Autowired + private IOAuthClientManager clientManager; + @RequestMapping(value = "/admin/user/auth/accessTokens/{accessTokenId}", method = RequestMethod.DELETE) public ResponseEntity deleteApp(@PathVariable("accessTokenId") String accessTokenId) { - userTokenManager.deleteClient(accessTokenId); + clientManager.deleteClient(accessTokenId); return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java index 3e0d73856..a4eb90323 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; +import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; @@ -17,8 +18,11 @@ public class UpdateAccessTokenController { @Autowired private IUserTokenManager userTokenManager; + @Autowired + private IOAuthClientManager clientManager; + @RequestMapping(value="/admin/user/auth/accessTokens/{accessTokenId}/secret/update", method=RequestMethod.POST) public @ResponseBody OAuthCredentials regenerateClientSecret(Model model, @PathVariable("accessTokenId") String accessTokenId) throws CannotFindClientException { - return userTokenManager.updateSecret(accessTokenId); + return clientManager.updateClientSecret(accessTokenId); } } From 4a248d6399983fae8a10384c06d77881c7e776bf Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 6 Feb 2024 16:08:40 -0700 Subject: [PATCH 17/28] [CITE-217] Refactoring and changing CRUD class --- .../core/model/oauth/IOAuthClient.java | 4 + .../core/model/oauth/impl/OAuthClient.java | 11 ++ .../model/oauth/impl/UserAccessToken.java | 98 ------------ .../oauth/OAuthClientRepository.java | 2 +- .../core/service/oauth/IUserTokenManager.java | 28 ---- .../oauth/impl/OAuthClientManager.java | 9 +- .../oauth/impl/UserAccessTokenManager.java | 149 ------------------ .../AccessTokenDetailsController.java | 6 +- .../AddUserAccessTokenController.java | 5 +- .../userOAuth/ShowAccessTokensController.java | 3 - .../UpdateAccessTokenController.java | 3 - .../views/admin/user/auth/details.html | 2 +- .../WEB-INF/views/admin/user/auth/show.html | 6 +- .../webapp/WEB-INF/views/layouts/main.html | 2 +- 14 files changed, 27 insertions(+), 301 deletions(-) delete mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java delete mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java delete mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java index 9860a2801..c2a3a2c03 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java @@ -69,4 +69,8 @@ public interface IOAuthClient { boolean getIsUserAccessToken(); void setisUserAccessToken(boolean isUserAccessToken); + + String getCreatedByUsername(); + + void setCreatedByUsername(String createdBy_username); } \ No newline at end of file diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java index 5ff13dc6c..4a6de8266 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java @@ -47,6 +47,7 @@ public class OAuthClient implements IOAuthClient, ClientDetails { private int refereshTokenValiditySeconds; private boolean autoApprove; private boolean isUserAccessToken; + private String createdByUsername; @Override public String getClientId() { @@ -203,4 +204,14 @@ public boolean getIsUserAccessToken() { public void setisUserAccessToken(boolean isUserAccessToken) { this.isUserAccessToken = isUserAccessToken; } + + @Override + public String getCreatedByUsername() { + return createdByUsername; + } + + @Override + public void setCreatedByUsername(String createdByUsername) { + this.createdByUsername = createdByUsername; + } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java deleted file mode 100644 index 92278b8fa..000000000 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/UserAccessToken.java +++ /dev/null @@ -1,98 +0,0 @@ -package edu.asu.diging.citesphere.core.model.oauth.impl; - -import java.util.Collection; -import java.util.Set; - -import javax.persistence.ElementCollection; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; - -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Parameter; -import org.springframework.security.core.GrantedAuthority; - -import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; -import edu.asu.diging.citesphere.user.IUser; -import edu.asu.diging.citesphere.user.impl.User; - -@Entity -public class UserAccessToken implements IUserAccessToken { - - @Id - @GeneratedValue(generator = "access_token_id_generator") - @GenericGenerator(name = "access_token_id_generator", - parameters = @Parameter(name = "prefix", value = "ACCESSTOKEN"), - strategy = "edu.asu.diging.citesphere.core.repository.IdGenerator" - ) - private String clientId; - - private String token; - - private String name; - - @ElementCollection - private Collection authorities; - - @ElementCollection - private Set scope; - - @ManyToOne(targetEntity=User.class) - private IUser user; - - @Override - public String getToken() { - return token; - } - - @Override - public void setToken(String token) { - this.token = token; - } - - @Override - public IUser getUser() { - return user; - } - - @Override - public void setUser(IUser user) { - this.user = user; - } - - @Override - public String getName() { - return name; - } - - @Override - public void setName(String name) { - this.name = name; - } - - @Override - public String getClientId() { - return clientId; - } - - @Override - public Set getScope() { - return scope; - } - - @Override - public void setScope(Set scope) { - this.scope = scope; - } - - @Override - public Collection getAuthorities() { - return authorities; - } - - @Override - public void setAuthorities(Collection authorities) { - this.authorities = authorities; - } -} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java index 01f967674..45f406a22 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java @@ -9,5 +9,5 @@ import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; public interface OAuthClientRepository extends JpaRepository { - Page findByIsUserAccessTokenAndCreatedBy_Username(boolean isUserAccessToken, String createdByUsername, Pageable pageable); + Page findByIsUserAccessTokenAndCreatedByUsername(boolean isUserAccessToken, String createdByUsername, Pageable pageable); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java deleted file mode 100644 index 8afe0a48e..000000000 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IUserTokenManager.java +++ /dev/null @@ -1,28 +0,0 @@ -package edu.asu.diging.citesphere.core.service.oauth; - -import java.util.List; - -import org.springframework.data.domain.Pageable; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.ClientRegistrationException; - -import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; -import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; -import edu.asu.diging.citesphere.user.IUser; - -public interface IUserTokenManager { - - UserAccessToken loadClientByClientId(String clientId) throws ClientRegistrationException; - - OAuthCredentials create(String name, IUser user); - - UserAccessTokenResultPage getAllAccessTokensDetails(Pageable pageable, IUser user); - - List getAllUserAccessTokenDetails(IUser user); - - void deleteClient(String clientId); - - OAuthCredentials updateSecret(String clientId) throws CannotFindClientException; - -} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java index 5f309cab5..c6a2f49b9 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java @@ -32,7 +32,6 @@ import edu.asu.diging.citesphere.core.model.Role; import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; -import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; import edu.asu.diging.citesphere.core.repository.oauth.OAuthClientRepository; import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; import edu.asu.diging.citesphere.core.service.oauth.OAuthClientResultPage; @@ -144,7 +143,7 @@ public List getClientsDetails(List clientList){ @Override public UserAccessTokenResultPage getAllUserAccessTokenDetails(Pageable pageable, IUser user) { List clientList = new ArrayList<>(); - Page userAccessClients = clientRepo.findByIsUserAccessTokenAndCreatedBy_Username(true, user.getUsername(), pageable); + Page userAccessClients = clientRepo.findByIsUserAccessTokenAndCreatedByUsername(true, user.getUsername(), pageable); userAccessClients.forEach(oAuthClient -> clientList.add(oAuthClient)); UserAccessTokenResultPage result = new UserAccessTokenResultPage(); result.setClientList(clientList); @@ -157,14 +156,14 @@ public OAuthCredentials createUserAccessToken(String name, IUser user) { final OAuthClient client = new OAuthClient(); client.setName(name); String clientSecret = UUID.randomUUID().toString(); - client.setClientSecret(bCryptPasswordEncoder.encode(clientSecret)); - final UserAccessToken userAccessToken = new UserAccessToken(); - userAccessToken.setName(name); + client.setClientSecret(bCryptPasswordEncoder.encode(clientSecret)); List authorities = new ArrayList<>(); authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); client.setAuthorities(authorities); client.setScope(new HashSet<>()); client.getScope().add(OAuthScope.READ.getScope()); + client.setCreatedByUsername(user.getUsername()); + client.setisUserAccessToken(true); OAuthClient storeClient = clientRepo.save(client); return new OAuthCredentials(storeClient.getClientId(), clientSecret); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java deleted file mode 100644 index a9956b9a7..000000000 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/UserAccessTokenManager.java +++ /dev/null @@ -1,149 +0,0 @@ -package edu.asu.diging.citesphere.core.service.oauth.impl; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -import javax.annotation.PostConstruct; -import javax.transaction.Transactional; - -import org.javers.common.collections.Sets; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.PropertySource; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; -import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.ClientDetailsService; -import org.springframework.security.oauth2.provider.ClientRegistrationException; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.TokenRequest; -import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; -import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; -import org.springframework.stereotype.Service; - -import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; -import edu.asu.diging.citesphere.core.model.Role; -import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; -import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; -import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; -import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; -import edu.asu.diging.citesphere.core.repository.oauth.UserAccessTokenRepository; -import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; -import edu.asu.diging.citesphere.core.service.oauth.OAuthClientResultPage; -import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; -import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; -import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; -import edu.asu.diging.citesphere.user.IUser; - -@Service -@PropertySource({ "classpath:config.properties", "${appConfigFile:classpath:}/app.properties" }) -@SuppressWarnings("deprecation") -@Transactional -public class UserAccessTokenManager implements IUserTokenManager { - - @Value("${_citephere_oauth2_app_clientid}") - private String citesphereClientId; - - @Autowired - private UserAccessTokenRepository userAccessTokenRepository; - - @Autowired - private BCryptPasswordEncoder bCryptPasswordEncoder; - - @Autowired - private ClientDetailsService clientDetailsService; - - private OAuth2RequestFactory requestFactory; - - @PostConstruct - public void init() { - this.requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); - } - - @Override - public UserAccessToken loadClientByClientId(String clientId) throws ClientRegistrationException { - Optional userAccessTokenOptional = userAccessTokenRepository.findById(clientId); - if (userAccessTokenOptional.isPresent()) { - UserAccessToken details = (UserAccessToken) userAccessTokenOptional.get(); - return details; - } - throw new InvalidClientException("Client with id " + clientId + " does not exist."); - } - - @Override - public OAuthCredentials create(String name, IUser user) { - final UserAccessToken userAccessToken = new UserAccessToken(); - userAccessToken.setName(name); - String token = UUID.randomUUID().toString(); -// userAccessToken.setToken(bCryptPasswordEncoder.encode(token)); - DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - - List authorities = new ArrayList<>(); - authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); - userAccessToken.setAuthorities(authorities); - userAccessToken.setScope(new HashSet<>()); - userAccessToken.getScope().add(OAuthScope.READ.getScope()); - userAccessToken.setUser(user); - UserAccessToken storeToken = userAccessTokenRepository.save(userAccessToken); - accessToken.setScope(Sets.asSet(OAuthScope.READ.getScope())); - AuthorizationRequest request = new AuthorizationRequest(citesphereClientId, accessToken.getScope()); - TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); - OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(citesphereClientId), implicitRequest, user); - return new OAuthCredentials(storeToken.getClientId(), token); - } - - private OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest, IUser user) { - OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); - Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getRoles()); - return new OAuth2Authentication(storedOAuth2Request, authentication); - } - - @Override - public UserAccessTokenResultPage getAllAccessTokensDetails(Pageable pageable, IUser user) { - List userAccessTokenList = new ArrayList<>(); - Page userAccessTokens = userAccessTokenRepository.findAllByUser(user, pageable); - userAccessTokens.forEach(userAccessToken -> userAccessTokenList.add(userAccessToken)); - UserAccessTokenResultPage result = new UserAccessTokenResultPage(); - result.setClientList(userAccessTokenList); - result.setTotalPages(userAccessTokens.getTotalPages()); - return result; - } - - @Override - public List getAllUserAccessTokenDetails(IUser user) { - return userAccessTokenRepository.findAllByUser(user); - } - - @Override - public void deleteClient(String clientId) { - if(clientId != null) { - userAccessTokenRepository.deleteById(clientId); - } - } - - @Override - public OAuthCredentials updateSecret(String clientId) throws CannotFindClientException { - Optional userAccessTokenOptional = userAccessTokenRepository.findById(clientId); - if (userAccessTokenOptional.isPresent()) { - UserAccessToken accessToken = userAccessTokenOptional.get(); - String token = UUID.randomUUID().toString(); - accessToken.setToken(bCryptPasswordEncoder.encode(token)); - UserAccessToken storeAccessToken = userAccessTokenRepository.save(accessToken); - return new OAuthCredentials(storeAccessToken.getClientId(), token); - } - throw new CannotFindClientException("Client with id " + clientId + " does not exist."); - } -} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java index 78630012f..adea9ea06 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -8,21 +8,17 @@ import org.springframework.web.bind.annotation.RequestMethod; import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; -import edu.asu.diging.citesphere.core.model.oauth.IUserAccessToken; import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; @Controller public class AccessTokenDetailsController { - @Autowired - private IUserTokenManager userTokenManager; @Autowired private IOAuthClientManager clientManager; @RequestMapping(value="/admin/user/auth/accessTokens/{accessTokenId}", method=RequestMethod.GET) public String showAppDetails(Model model, @PathVariable("accessTokenId") String accessTokenId) { - IOAuthClient details = (IOAuthClient) userTokenManager.loadClientByClientId(accessTokenId); + IOAuthClient details = (IOAuthClient) clientManager.loadClientByClientId(accessTokenId); model.addAttribute("clientName", details.getName()); model.addAttribute("clientId", details.getClientId()); return "admin/user/auth/details"; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index 6a109660e..06a85c818 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -12,7 +12,6 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes; import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; @@ -20,8 +19,6 @@ @Controller public class AddUserAccessTokenController { - @Autowired - private IUserTokenManager userTokenManager; @Autowired private IUserManager userManager; @@ -41,6 +38,6 @@ public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model mode OAuthCredentials creds = clientManager.createUserAccessToken(userAccessTokenForm.getName(), user); redirectAttrs.addFlashAttribute("clientId", creds.getClientId()); redirectAttrs.addFlashAttribute("secret", creds.getSecret()); - return "redirect:/admin/user/auth/" + creds.getClientId(); + return "redirect:/admin/user/auth/accessTokens/" + creds.getClientId(); } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java index 14b759924..1ba1fce8a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -10,15 +10,12 @@ import org.springframework.web.bind.annotation.RequestMethod; import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; @Controller public class ShowAccessTokensController { - @Autowired - private IUserTokenManager userTokenManager; @Autowired private IUserManager userManager; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java index a4eb90323..5cfa3044b 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -10,13 +10,10 @@ import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; @Controller public class UpdateAccessTokenController { - @Autowired - private IUserTokenManager userTokenManager; @Autowired private IOAuthClientManager clientManager; diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html index 5650afe37..13797932e 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/details.html @@ -51,7 +51,7 @@
      - +
         diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html index 005e0e16c..e114d1aae 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html @@ -77,7 +77,7 @@

      Tokens

        - + @@ -86,8 +86,8 @@

        Tokens

        - - + +
        Client Id
        diff --git a/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html b/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html index e76bcc5d1..d6c648967 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html +++ b/citesphere/src/main/webapp/WEB-INF/views/layouts/main.html @@ -67,7 +67,7 @@ From 5e4088dc71407ba5dbda95251973952758afcaab Mon Sep 17 00:00:00 2001 From: diya17 Date: Wed, 7 Feb 2024 15:59:54 -0700 Subject: [PATCH 18/28] [CITE-217] Changing access token generation --- .../oauth/impl/OAuthClientManager.java | 73 ++++++++++++++++++- .../DeleteAccessTokenController.java | 3 - 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java index c6a2f49b9..6c8a65a19 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java @@ -1,5 +1,9 @@ package edu.asu.diging.citesphere.core.service.oauth.impl; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -10,23 +14,30 @@ import javax.transaction.Transactional; import org.javers.common.collections.Sets; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientRegistrationException; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; import edu.asu.diging.citesphere.core.model.Role; @@ -38,6 +49,7 @@ import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; +import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; @Transactional @@ -48,11 +60,23 @@ public class OAuthClientManager implements ClientDetailsService, IOAuthClientMan private BCryptPasswordEncoder bCryptPasswordEncoder; private int accessTokenValidity; + + private OAuth2RequestFactory requestFactory; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + private IUserManager userManager; public OAuthClientManager(OAuthClientRepository repo, BCryptPasswordEncoder bCryptPasswordEncoder, int accessTokenValidity) { this.clientRepo = repo; this.bCryptPasswordEncoder = bCryptPasswordEncoder; this.accessTokenValidity = accessTokenValidity; + this.requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); } /* (non-Javadoc) @@ -123,6 +147,13 @@ public OAuthCredentials updateClientSecret(String clientId) throws CannotFindCli Optional clientOptional = clientRepo.findById(clientId); if (clientOptional.isPresent()) { OAuthClient client = clientOptional.get(); + if (client.getIsUserAccessToken()) { + IUser user = userManager.findByUsername(client.getCreatedByUsername()); + OAuth2AccessToken accessToken = createAccessToken(client.getClientId(), user); + client.setClientSecret(bCryptPasswordEncoder.encode(accessToken.getValue())); + OAuthClient storeClient = clientRepo.save(client); + return new OAuthCredentials(storeClient.getClientId(), accessToken.getValue()); + } String clientSecret = UUID.randomUUID().toString(); client.setClientSecret(bCryptPasswordEncoder.encode(clientSecret)); OAuthClient storeClient = clientRepo.save(client); @@ -165,6 +196,46 @@ public OAuthCredentials createUserAccessToken(String name, IUser user) { client.setCreatedByUsername(user.getUsername()); client.setisUserAccessToken(true); OAuthClient storeClient = clientRepo.save(client); - return new OAuthCredentials(storeClient.getClientId(), clientSecret); + OAuth2AccessToken accessToken = createAccessToken(storeClient.getClientId(), user); + storeClient.setClientSecret(bCryptPasswordEncoder.encode(accessToken.getValue())); + clientRepo.save(storeClient); + return new OAuthCredentials(storeClient.getClientId(), accessToken.getValue()); + } + + private OAuth2AccessToken createAccessToken(String clientId, IUser user) { + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + token.setScope(Sets.asSet(OAuthScope.READ.getScope())); + AuthorizationRequest request = new AuthorizationRequest(clientId, token.getScope()); + TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); + OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(clientId), implicitRequest, user); + tokenStore.storeAccessToken(token, authentication); + System.out.println(extractTokenKey(token.getValue())); + return token; + } + + private OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest, IUser user) { + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); + Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getRoles()); + return new OAuth2Authentication(storedOAuth2Request, authentication); + } + + private String extractTokenKey(String value) { + if(value == null) { + return null; + } else { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException var5) { + throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); + } + + try { + byte[] e = digest.digest(value.getBytes("UTF-8")); + return String.format("%032x", new Object[]{new BigInteger(1, e)}); + } catch (UnsupportedEncodingException var4) { + throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); + } + } } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java index 30052c733..2a0e10b5c 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -9,12 +9,9 @@ import org.springframework.web.bind.annotation.RequestMethod; import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.IUserTokenManager; @Controller public class DeleteAccessTokenController { - @Autowired - private IUserTokenManager userTokenManager; @Autowired private IOAuthClientManager clientManager; From 7c617b43063c6940ca2d8bbc1675aeb0eb536d76 Mon Sep 17 00:00:00 2001 From: diya17 Date: Fri, 9 Feb 2024 13:00:13 -0700 Subject: [PATCH 19/28] [CITE-217] Adding testcases --- citesphere/pom.xml | 15 +++- .../oauth/impl/OAuthClientManagerTest.java | 68 +++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/citesphere/pom.xml b/citesphere/pom.xml index b45630d50..0fd48eb5a 100644 --- a/citesphere/pom.xml +++ b/citesphere/pom.xml @@ -536,14 +536,23 @@ 4.13.1 test - + + + org.mockito mockito-all 1.10.19 test + + + org.mockito + mockito-core + 3.12.4 + test + @@ -648,8 +657,8 @@ maven-compiler-plugin - 1.8 - 1.8 + 11 + 11 diff --git a/citesphere/src/test/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManagerTest.java b/citesphere/src/test/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManagerTest.java index 5b34f6ed2..545046f69 100644 --- a/citesphere/src/test/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManagerTest.java +++ b/citesphere/src/test/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManagerTest.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import org.junit.Assert; import org.junit.Before; @@ -10,10 +11,25 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; import edu.asu.diging.citesphere.core.repository.oauth.OAuthClientRepository; +import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; +import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; +import edu.asu.diging.citesphere.core.user.IUserManager; +import edu.asu.diging.citesphere.user.IUser; +import edu.asu.diging.citesphere.user.impl.User; public class OAuthClientManagerTest { @@ -23,6 +39,21 @@ public class OAuthClientManagerTest { @Mock private BCryptPasswordEncoder bCryptPasswordEncoder; + @Mock + private TokenStore tokenStore; + + @Mock + private ClientDetailsService clientDetailsService; + + @Mock + private IUserManager userManager; + + @Mock + private OAuth2RequestFactory requestFactory; + + @Mock + private DefaultOAuth2RequestFactory defaultOAuth2RequestFactory; + private int accessTokenValidity = 3600; @InjectMocks @@ -104,4 +135,41 @@ public void test_getAllApps_emptyList() { Assert.assertEquals(0, managerToTest.getAllApps().size()); } + @Test + public void test_getAllUserAccessTokenDetails_success() { + Pageable pageable = PageRequest.of(0, 10); + IUser user = new User(); + user.setUsername("testuser"); + + List mockClientList = new ArrayList<>(); + mockClientList.add(new OAuthClient()); + + Page mockPage = new PageImpl<>(mockClientList); + + Mockito.when(clientRepo.findByIsUserAccessTokenAndCreatedByUsername( + true, "testuser", pageable)) + .thenReturn(mockPage); + + UserAccessTokenResultPage resultPage = managerToTest.getAllUserAccessTokenDetails(pageable, user); + + Assert.assertEquals(1, resultPage.getClientList().size()); + } + + @Test + public void test_getAllUserAccessTokenDetails_returnsEmptyList() { + Pageable pageable = PageRequest.of(0, 10); + IUser user = new User(); + user.setUsername("testuser"); + + List mockClientList = new ArrayList<>(); + Page mockPage = new PageImpl<>(mockClientList); + + Mockito.when(clientRepo.findByIsUserAccessTokenAndCreatedByUsername( + true, "testuser", pageable)) + .thenReturn(mockPage); + + UserAccessTokenResultPage resultPage = managerToTest.getAllUserAccessTokenDetails(pageable, user); + + Assert.assertEquals(0, resultPage.getClientList().size()); + } } From a1229541425593820d563084c2dd85c96347f2c0 Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 13 Feb 2024 11:13:54 -0700 Subject: [PATCH 20/28] [CITE-217] : Refactoring --- .../core/model/oauth/IUserAccessToken.java | 33 ------------------- .../oauth/UserAccessTokenRepository.java | 17 ---------- 2 files changed, 50 deletions(-) delete mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java delete mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java deleted file mode 100644 index 05ca4ccfb..000000000 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IUserAccessToken.java +++ /dev/null @@ -1,33 +0,0 @@ -package edu.asu.diging.citesphere.core.model.oauth; - -import java.util.Collection; -import java.util.Set; - -import org.springframework.security.core.GrantedAuthority; - -import edu.asu.diging.citesphere.user.IUser; - -public interface IUserAccessToken { - - String getToken(); - - void setToken(String token); - - IUser getUser(); - - void setUser(IUser user); - - String getName(); - - void setName(String name); - - String getClientId(); - - Set getScope(); - - void setScope(Set scope); - - Collection getAuthorities(); - - void setAuthorities(Collection authorities); -} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java deleted file mode 100644 index 6cc6b0483..000000000 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/UserAccessTokenRepository.java +++ /dev/null @@ -1,17 +0,0 @@ -package edu.asu.diging.citesphere.core.repository.oauth; - -import java.util.List; - -import org.javers.spring.annotation.JaversSpringDataAuditable; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; - -import edu.asu.diging.citesphere.core.model.oauth.impl.UserAccessToken; -import edu.asu.diging.citesphere.user.IUser; - -@JaversSpringDataAuditable -public interface UserAccessTokenRepository extends JpaRepository { - Page findAllByUser(IUser user, Pageable pageable); - List findAllByUser(IUser user); -} From 0f0f5fe5850834ed24173e73f90980a49db89a0b Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 13 Feb 2024 11:15:08 -0700 Subject: [PATCH 21/28] [CITE-217] Update pom --- citesphere/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/citesphere/pom.xml b/citesphere/pom.xml index 0fd48eb5a..cf659d4c5 100644 --- a/citesphere/pom.xml +++ b/citesphere/pom.xml @@ -25,7 +25,7 @@ 2.2.6.RELEASE 0.12 0.4 - 1.21-SNAPSHOT + 1.19 $2a$04$oQo44vqcDIFRoYKiAXoNheurzkwX9dcNmowvTX/hsWuBMwijqn44i From c7d70e0b30f235627342c264d2afd84926d8565a Mon Sep 17 00:00:00 2001 From: diya17 Date: Wed, 6 Mar 2024 10:48:58 -0700 Subject: [PATCH 22/28] [CITE-217] : Update Method --- .../asu/diging/citesphere/core/model/oauth/IOAuthClient.java | 2 +- .../diging/citesphere/core/model/oauth/impl/OAuthClient.java | 2 +- .../citesphere/core/service/oauth/impl/OAuthClientManager.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java index c2a3a2c03..1c6421ef0 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java @@ -68,7 +68,7 @@ public interface IOAuthClient { boolean getIsUserAccessToken(); - void setisUserAccessToken(boolean isUserAccessToken); + void setIsUserAccessToken(boolean isUserAccessToken); String getCreatedByUsername(); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java index 4a6de8266..f97d015f5 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java @@ -201,7 +201,7 @@ public boolean getIsUserAccessToken() { } @Override - public void setisUserAccessToken(boolean isUserAccessToken) { + public void setIsUserAccessToken(boolean isUserAccessToken) { this.isUserAccessToken = isUserAccessToken; } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java index 6c8a65a19..f3d47136f 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java @@ -194,7 +194,7 @@ public OAuthCredentials createUserAccessToken(String name, IUser user) { client.setScope(new HashSet<>()); client.getScope().add(OAuthScope.READ.getScope()); client.setCreatedByUsername(user.getUsername()); - client.setisUserAccessToken(true); + client.setIsUserAccessToken(true); OAuthClient storeClient = clientRepo.save(client); OAuth2AccessToken accessToken = createAccessToken(storeClient.getClientId(), user); storeClient.setClientSecret(bCryptPasswordEncoder.encode(accessToken.getValue())); From 27d7271615919bd656fc0ac586e044c1268424c2 Mon Sep 17 00:00:00 2001 From: PradnyaC11 Date: Tue, 1 Apr 2025 16:44:22 -0700 Subject: [PATCH 23/28] [CITE-217] Resolved the errors and removed duplicate codes --- .../citesphere/core/model/oauth/IOAuthClient.java | 4 ---- .../core/model/oauth/impl/OAuthClient.java | 13 ++----------- .../core/service/oauth/impl/OAuthClientManager.java | 6 ++++-- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java index 54393fdb1..fdb1fdac6 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IOAuthClient.java @@ -72,10 +72,6 @@ public interface IOAuthClient { void setIsUserAccessToken(boolean isUserAccessToken); - String getCreatedByUsername(); - - void setCreatedByUsername(String createdBy_username); - IUser getCreatedBy(); void setCreatedBy(IUser user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java index f8bcd79a1..f7db2769d 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/OAuthClient.java @@ -51,7 +51,6 @@ public class OAuthClient implements IOAuthClient, ClientDetails { private int refereshTokenValiditySeconds; private boolean autoApprove; private boolean isUserAccessToken; - private String createdByUsername; @OneToOne(targetEntity=User.class) private IUser createdBy; @@ -210,16 +209,8 @@ public boolean getIsUserAccessToken() { @Override public void setIsUserAccessToken(boolean isUserAccessToken) { this.isUserAccessToken = isUserAccessToken; - } - - @Override - public String getCreatedByUsername() { - return createdByUsername; - } - - @Override - public void setCreatedByUsername(String createdByUsername) { - this.createdByUsername = createdByUsername; + } + public IUser getCreatedBy() { return this.createdBy; } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java index ee69d7f8b..e873b38c1 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java @@ -149,7 +149,7 @@ public OAuthCredentials updateClientSecret(String clientId) throws CannotFindCli if (clientOptional.isPresent()) { OAuthClient client = clientOptional.get(); if (client.getIsUserAccessToken()) { - IUser user = userManager.findByUsername(client.getCreatedByUsername()); + IUser user = client.getCreatedBy(); OAuth2AccessToken accessToken = createAccessToken(client.getClientId(), user); client.setClientSecret(bCryptPasswordEncoder.encode(accessToken.getValue())); OAuthClient storeClient = clientRepo.save(client); @@ -194,7 +194,7 @@ public OAuthCredentials createUserAccessToken(String name, IUser user) { client.setAuthorities(authorities); client.setScope(new HashSet<>()); client.getScope().add(OAuthScope.READ.getScope()); - client.setCreatedByUsername(user.getUsername()); + client.setCreatedBy(user); client.setIsUserAccessToken(true); OAuthClient storeClient = clientRepo.save(client); OAuth2AccessToken accessToken = createAccessToken(storeClient.getClientId(), user); @@ -238,6 +238,8 @@ private String extractTokenKey(String value) { throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); } } + } + public void setAccessTokenValidity(int accessTokenValidity) { this.accessTokenValidity = accessTokenValidity; } From ec9d30187a6763e76422e0d4925708c37cb1f2d0 Mon Sep 17 00:00:00 2001 From: Girik1105 Date: Mon, 22 Dec 2025 16:27:11 -0700 Subject: [PATCH 24/28] [CITE-217] Seperated manager class for personal oauth --- .../exceptions/CannotFindTokenException.java | 10 + .../model/oauth/IPersonalAccessToken.java | 24 ++ .../core/model/oauth/impl/DbAccessToken.java | 50 +++- .../oauth/DbAccessTokenRepository.java | 7 +- .../oauth/OAuthClientRepository.java | 4 +- .../service/oauth/IOAuthClientManager.java | 4 - .../oauth/IPersonalAccessTokenManager.java | 61 +++++ .../oauth/PersonalAccessTokenCredentials.java | 43 +++ .../oauth/PersonalAccessTokenResultPage.java | 30 +++ .../oauth/impl/OAuthClientManager.java | 133 +--------- .../impl/PersonalAccessTokenManager.java | 246 ++++++++++++++++++ .../AccessTokenDetailsController.java | 18 +- .../AddUserAccessTokenController.java | 22 +- .../DeleteAccessTokenController.java | 27 +- .../userOAuth/ShowAccessTokensController.java | 16 +- .../UpdateAccessTokenController.java | 24 +- .../WEB-INF/views/admin/user/auth/show.html | 8 +- .../oauth/impl/OAuthClientManagerTest.java | 91 +------ .../impl/PersonalAccessTokenManagerTest.java | 178 +++++++++++++ 19 files changed, 736 insertions(+), 260 deletions(-) create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/exceptions/CannotFindTokenException.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IPersonalAccessToken.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IPersonalAccessTokenManager.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenCredentials.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenResultPage.java create mode 100644 citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/PersonalAccessTokenManager.java create mode 100644 citesphere/src/test/java/edu/asu/diging/citesphere/core/service/oauth/impl/PersonalAccessTokenManagerTest.java diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/exceptions/CannotFindTokenException.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/exceptions/CannotFindTokenException.java new file mode 100644 index 000000000..3b669e247 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/exceptions/CannotFindTokenException.java @@ -0,0 +1,10 @@ +package edu.asu.diging.citesphere.core.exceptions; + +public class CannotFindTokenException extends Exception { + + private static final long serialVersionUID = 1L; + + public CannotFindTokenException(String message) { + super(message); + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IPersonalAccessToken.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IPersonalAccessToken.java new file mode 100644 index 000000000..589f9143c --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/IPersonalAccessToken.java @@ -0,0 +1,24 @@ +package edu.asu.diging.citesphere.core.model.oauth; + +import java.time.OffsetDateTime; + +/** + * Interface representing a personal access token for API access. + * Personal access tokens allow users to authenticate against the API + * without going through the OAuth authorization code flow. + */ +public interface IPersonalAccessToken { + + String getId(); + + String getName(); + void setName(String name); + + String getUsername(); + + OffsetDateTime getCreatedAt(); + void setCreatedAt(OffsetDateTime createdAt); + + boolean isPersonalAccessToken(); + void setPersonalAccessToken(boolean isPersonalAccessToken); +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/DbAccessToken.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/DbAccessToken.java index fc03a63ba..cf7d79ad5 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/DbAccessToken.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/model/oauth/impl/DbAccessToken.java @@ -1,5 +1,7 @@ package edu.asu.diging.citesphere.core.model.oauth.impl; +import java.time.OffsetDateTime; + import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Lob; @@ -7,6 +9,8 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; +import edu.asu.diging.citesphere.core.model.oauth.IPersonalAccessToken; + /** * Modeled after: * https://blog.couchbase.com/custom-token-store-spring-securtiy-oauth2/ @@ -14,8 +18,8 @@ * */ @Entity -public class DbAccessToken { - +public class DbAccessToken implements IPersonalAccessToken { + @Id private String id; private String tokenId; @@ -28,12 +32,15 @@ public class DbAccessToken { private String authentication; @Lob private String refreshToken; - - + + private String name; + private OffsetDateTime createdAt; + private boolean personalAccessToken; + public OAuth2Authentication getAuthentication() { return SerializableObjectConverter.deserialize(authentication); } - + public void setAuthentication(OAuth2Authentication authentication) { this.authentication = SerializableObjectConverter.serialize(authentication); } @@ -97,5 +104,34 @@ public void setRefreshToken(String refreshToken) { public void setAuthentication(String authentication) { this.authentication = authentication; } - -} \ No newline at end of file + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + @Override + public void setCreatedAt(OffsetDateTime createdAt) { + this.createdAt = createdAt; + } + + @Override + public boolean isPersonalAccessToken() { + return personalAccessToken; + } + + @Override + public void setPersonalAccessToken(boolean personalAccessToken) { + this.personalAccessToken = personalAccessToken; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/DbAccessTokenRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/DbAccessTokenRepository.java index be60818bd..e3f97dfa1 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/DbAccessTokenRepository.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/DbAccessTokenRepository.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import edu.asu.diging.citesphere.core.model.oauth.impl.DbAccessToken; @@ -28,5 +30,8 @@ public interface DbAccessTokenRepository extends JpaRepository findByAuthenticationId(String authenticationId); void deleteByClientIdAndUsername(String clientId, String username); - + + Page findByUsernameAndPersonalAccessToken(String username, boolean isPersonalAccessToken, Pageable pageable); + + Optional findByIdAndUsername(String id, String username); } \ No newline at end of file diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java index 45f406a22..dc628df0b 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/repository/oauth/OAuthClientRepository.java @@ -1,6 +1,6 @@ package edu.asu.diging.citesphere.core.repository.oauth; -import java.util.List; +import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -10,4 +10,6 @@ public interface OAuthClientRepository extends JpaRepository { Page findByIsUserAccessTokenAndCreatedByUsername(boolean isUserAccessToken, String createdByUsername, Pageable pageable); + + Optional findByCreatedByUsernameAndIsUserAccessToken(String username, boolean isUserAccessToken); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java index adbff584d..ea6b20ab1 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IOAuthClientManager.java @@ -27,8 +27,4 @@ public interface IOAuthClientManager { OAuthCredentials updateClientSecret(String clientId) throws CannotFindClientException; List getClientsDetails(List clientList); - - UserAccessTokenResultPage getAllUserAccessTokenDetails(Pageable pageable, IUser user); - - OAuthCredentials createUserAccessToken(String name, IUser user); } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IPersonalAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IPersonalAccessTokenManager.java new file mode 100644 index 000000000..27775acf0 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/IPersonalAccessTokenManager.java @@ -0,0 +1,61 @@ +package edu.asu.diging.citesphere.core.service.oauth; + +import org.springframework.data.domain.Pageable; + +import edu.asu.diging.citesphere.core.exceptions.CannotFindTokenException; +import edu.asu.diging.citesphere.core.model.oauth.IPersonalAccessToken; +import edu.asu.diging.citesphere.user.IUser; + +/** + * Manager for personal access token operations. + * Personal access tokens allow users to authenticate against the API + * without going through the OAuth authorization code flow. + */ +public interface IPersonalAccessTokenManager { + + /** + * Creates a new personal access token for the user. + * + * @param name the user-given name for the token + * @param user the user creating the token + * @return credentials containing the token ID and token value (shown only once) + */ + PersonalAccessTokenCredentials createToken(String name, IUser user); + + /** + * Gets all personal access tokens for the user. + * + * @param user the user whose tokens to retrieve + * @param pageable pagination information + * @return paginated result of tokens + */ + PersonalAccessTokenResultPage getTokensForUser(IUser user, Pageable pageable); + + /** + * Deletes a personal access token. + * + * @param tokenId the ID of the token to delete + * @param user the user who owns the token + * @throws CannotFindTokenException if the token is not found or doesn't belong to the user + */ + void deleteToken(String tokenId, IUser user) throws CannotFindTokenException; + + /** + * Regenerates a personal access token, invalidating the old token value + * and creating a new one. + * + * @param tokenId the ID of the token to regenerate + * @param user the user who owns the token + * @return credentials containing the token ID and new token value + * @throws CannotFindTokenException if the token is not found or doesn't belong to the user + */ + PersonalAccessTokenCredentials regenerateToken(String tokenId, IUser user) throws CannotFindTokenException; + + /** + * Gets a personal access token by ID. + * + * @param tokenId the ID of the token + * @return the token, or null if not found + */ + IPersonalAccessToken getTokenById(String tokenId); +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenCredentials.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenCredentials.java new file mode 100644 index 000000000..9c71240f1 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenCredentials.java @@ -0,0 +1,43 @@ +package edu.asu.diging.citesphere.core.service.oauth; + +/** + * This class is a temporary holder for personal access token ID and token value + * to be used after creation of a new token. The token value should only be shown + * once to the user and not stored unencrypted. + */ +public class PersonalAccessTokenCredentials { + + private String tokenId; + private String tokenValue; + private String name; + + public PersonalAccessTokenCredentials(String tokenId, String tokenValue, String name) { + this.tokenId = tokenId; + this.tokenValue = tokenValue; + this.name = name; + } + + public String getTokenId() { + return tokenId; + } + + public void setTokenId(String tokenId) { + this.tokenId = tokenId; + } + + public String getTokenValue() { + return tokenValue; + } + + public void setTokenValue(String tokenValue) { + this.tokenValue = tokenValue; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenResultPage.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenResultPage.java new file mode 100644 index 000000000..52a847e26 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/PersonalAccessTokenResultPage.java @@ -0,0 +1,30 @@ +package edu.asu.diging.citesphere.core.service.oauth; + +import java.util.List; + +import edu.asu.diging.citesphere.core.model.oauth.IPersonalAccessToken; + +/** + * Result page for paginated personal access token listings. + */ +public class PersonalAccessTokenResultPage { + + private long totalPages; + private List tokens; + + public long getTotalPages() { + return totalPages; + } + + public void setTotalPages(long totalPages) { + this.totalPages = totalPages; + } + + public List getTokens() { + return tokens; + } + + public void setTokens(List tokens) { + this.tokens = tokens; + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java index e873b38c1..06c7c32bb 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/OAuthClientManager.java @@ -1,9 +1,5 @@ package edu.asu.diging.citesphere.core.service.oauth.impl; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -13,34 +9,16 @@ import javax.transaction.Transactional; -import org.javers.common.collections.Sets; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; -import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; -import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientRegistrationException; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; -import org.springframework.security.oauth2.provider.OAuth2RequestFactory; -import org.springframework.security.oauth2.provider.TokenRequest; -import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; -import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; -import org.springframework.security.oauth2.provider.token.TokenStore; import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; -import edu.asu.diging.citesphere.core.model.Role; import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; import edu.asu.diging.citesphere.core.repository.oauth.OAuthClientRepository; @@ -48,35 +26,21 @@ import edu.asu.diging.citesphere.core.service.oauth.OAuthClientResultPage; import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; -import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; -import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; @Transactional public class OAuthClientManager implements ClientDetailsService, IOAuthClientManager { private OAuthClientRepository clientRepo; - + private BCryptPasswordEncoder bCryptPasswordEncoder; - + private int accessTokenValidity; - - private OAuth2RequestFactory requestFactory; - - @Autowired - private TokenStore tokenStore; - - @Autowired - private ClientDetailsService clientDetailsService; - - @Autowired - private IUserManager userManager; - + public OAuthClientManager(OAuthClientRepository repo, BCryptPasswordEncoder bCryptPasswordEncoder, int accessTokenValidity) { this.clientRepo = repo; this.bCryptPasswordEncoder = bCryptPasswordEncoder; this.accessTokenValidity = accessTokenValidity; - this.requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); } /* (non-Javadoc) @@ -92,10 +56,10 @@ public ClientDetails loadClientByClientId(String clientId) throws ClientRegistra // load authorities, ugly but best I can come up with right now } return details; - } + } throw new InvalidClientException("Client with id " + clientId + " does not exist."); } - + /* (non-Javadoc) * @see edu.asu.diging.citesphere.core.service.oauth.impl.IOAuthClientManager#store(org.springframework.security.oauth2.provider.ClientDetails) */ @@ -118,7 +82,7 @@ public OAuthCredentials create(String name, String description, List OAuthClient storeClient = clientRepo.save(client); return new OAuthCredentials(storeClient.getClientId(), clientSecret); } - + @Override public OAuthClientResultPage getAllClientDetails(Pageable pageable) { List clientList = new ArrayList<>(); @@ -128,33 +92,26 @@ public OAuthClientResultPage getAllClientDetails(Pageable pageable) { result.setClientList(clientList); result.setTotalPages(oAuthClients.getTotalPages()); return result; - + } - + @Override public List getAllApps() { return clientRepo.findAll(); } - + @Override public void deleteClient(String clientId) { if(clientId != null) { clientRepo.deleteById(clientId); } } - + @Override public OAuthCredentials updateClientSecret(String clientId) throws CannotFindClientException { Optional clientOptional = clientRepo.findById(clientId); if (clientOptional.isPresent()) { OAuthClient client = clientOptional.get(); - if (client.getIsUserAccessToken()) { - IUser user = client.getCreatedBy(); - OAuth2AccessToken accessToken = createAccessToken(client.getClientId(), user); - client.setClientSecret(bCryptPasswordEncoder.encode(accessToken.getValue())); - OAuthClient storeClient = clientRepo.save(client); - return new OAuthCredentials(storeClient.getClientId(), accessToken.getValue()); - } String clientSecret = UUID.randomUUID().toString(); client.setClientSecret(bCryptPasswordEncoder.encode(clientSecret)); OAuthClient storeClient = clientRepo.save(client); @@ -162,7 +119,7 @@ public OAuthCredentials updateClientSecret(String clientId) throws CannotFindCli } throw new CannotFindClientException("Client with id " + clientId + " does not exist."); } - + @Override public List getClientsDetails(List clientList){ List clients = new ArrayList<>(); @@ -172,74 +129,6 @@ public List getClientsDetails(List clientList){ return clients; } - @Override - public UserAccessTokenResultPage getAllUserAccessTokenDetails(Pageable pageable, IUser user) { - List clientList = new ArrayList<>(); - Page userAccessClients = clientRepo.findByIsUserAccessTokenAndCreatedByUsername(true, user.getUsername(), pageable); - userAccessClients.forEach(oAuthClient -> clientList.add(oAuthClient)); - UserAccessTokenResultPage result = new UserAccessTokenResultPage(); - result.setClientList(clientList); - result.setTotalPages(userAccessClients.getTotalPages()); - return result; - } - - @Override - public OAuthCredentials createUserAccessToken(String name, IUser user) { - final OAuthClient client = new OAuthClient(); - client.setName(name); - String clientSecret = UUID.randomUUID().toString(); - client.setClientSecret(bCryptPasswordEncoder.encode(clientSecret)); - List authorities = new ArrayList<>(); - authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); - client.setAuthorities(authorities); - client.setScope(new HashSet<>()); - client.getScope().add(OAuthScope.READ.getScope()); - client.setCreatedBy(user); - client.setIsUserAccessToken(true); - OAuthClient storeClient = clientRepo.save(client); - OAuth2AccessToken accessToken = createAccessToken(storeClient.getClientId(), user); - storeClient.setClientSecret(bCryptPasswordEncoder.encode(accessToken.getValue())); - clientRepo.save(storeClient); - return new OAuthCredentials(storeClient.getClientId(), accessToken.getValue()); - } - - private OAuth2AccessToken createAccessToken(String clientId, IUser user) { - DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); - token.setScope(Sets.asSet(OAuthScope.READ.getScope())); - AuthorizationRequest request = new AuthorizationRequest(clientId, token.getScope()); - TokenRequest implicitRequest = new ImplicitTokenRequest(requestFactory.createTokenRequest(request, "implicit"), requestFactory.createOAuth2Request(request)); - OAuth2Authentication authentication = getOAuth2Authentication(clientDetailsService.loadClientByClientId(clientId), implicitRequest, user); - tokenStore.storeAccessToken(token, authentication); - System.out.println(extractTokenKey(token.getValue())); - return token; - } - - private OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest, IUser user) { - OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); - Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getRoles()); - return new OAuth2Authentication(storedOAuth2Request, authentication); - } - - private String extractTokenKey(String value) { - if(value == null) { - return null; - } else { - MessageDigest digest; - try { - digest = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException var5) { - throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); - } - - try { - byte[] e = digest.digest(value.getBytes("UTF-8")); - return String.format("%032x", new Object[]{new BigInteger(1, e)}); - } catch (UnsupportedEncodingException var4) { - throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); - } - } - } - public void setAccessTokenValidity(int accessTokenValidity) { this.accessTokenValidity = accessTokenValidity; } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/PersonalAccessTokenManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/PersonalAccessTokenManager.java new file mode 100644 index 000000000..f102ffe46 --- /dev/null +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/oauth/impl/PersonalAccessTokenManager.java @@ -0,0 +1,246 @@ +package edu.asu.diging.citesphere.core.service.oauth.impl; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import javax.transaction.Transactional; + +import org.javers.common.collections.Sets; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.OAuth2RequestFactory; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.implicit.ImplicitTokenRequest; +import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.stereotype.Service; + +import edu.asu.diging.citesphere.core.exceptions.CannotFindTokenException; +import edu.asu.diging.citesphere.core.model.Role; +import edu.asu.diging.citesphere.core.model.oauth.IPersonalAccessToken; +import edu.asu.diging.citesphere.core.model.oauth.impl.DbAccessToken; +import edu.asu.diging.citesphere.core.model.oauth.impl.OAuthClient; +import edu.asu.diging.citesphere.core.repository.oauth.DbAccessTokenRepository; +import edu.asu.diging.citesphere.core.repository.oauth.OAuthClientRepository; +import edu.asu.diging.citesphere.core.service.oauth.IPersonalAccessTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.OAuthScope; +import edu.asu.diging.citesphere.core.service.oauth.PersonalAccessTokenCredentials; +import edu.asu.diging.citesphere.core.service.oauth.PersonalAccessTokenResultPage; +import edu.asu.diging.citesphere.user.IUser; + +/** + * Manager for personal access token operations. + * This class handles the creation, retrieval, and management of personal access tokens, + * which allow users to authenticate against the API without going through the OAuth + * authorization code flow. + */ +@Service +@Transactional +public class PersonalAccessTokenManager implements IPersonalAccessTokenManager { + + @Autowired + private OAuthClientRepository clientRepo; + + @Autowired + private DbAccessTokenRepository accessTokenRepo; + + @Autowired + private BCryptPasswordEncoder bCryptPasswordEncoder; + + @Autowired + private TokenStore tokenStore; + + @Autowired + private ClientDetailsService clientDetailsService; + + private OAuth2RequestFactory requestFactory; + + @Override + public PersonalAccessTokenCredentials createToken(String name, IUser user) { + OAuthClient patClient = getOrCreatePATClientForUser(user); + + OAuth2AccessToken accessToken = createAccessToken(patClient.getClientId(), user); + + DbAccessToken dbToken = new DbAccessToken(); + dbToken.setId(UUID.randomUUID().toString() + UUID.randomUUID().toString()); + dbToken.setTokenId(extractTokenKey(accessToken.getValue())); + dbToken.setToken(accessToken); + dbToken.setUsername(user.getUsername()); + dbToken.setClientId(patClient.getClientId()); + dbToken.setName(name); + dbToken.setCreatedAt(OffsetDateTime.now()); + dbToken.setPersonalAccessToken(true); + + accessTokenRepo.save(dbToken); + + return new PersonalAccessTokenCredentials(dbToken.getId(), accessToken.getValue(), name); + } + + @Override + public PersonalAccessTokenResultPage getTokensForUser(IUser user, Pageable pageable) { + Page tokensPage = accessTokenRepo.findByUsernameAndPersonalAccessToken( + user.getUsername(), true, pageable); + + List tokens = new ArrayList<>(); + tokensPage.forEach(token -> tokens.add(token)); + + PersonalAccessTokenResultPage result = new PersonalAccessTokenResultPage(); + result.setTokens(tokens); + result.setTotalPages(tokensPage.getTotalPages()); + return result; + } + + @Override + public void deleteToken(String tokenId, IUser user) throws CannotFindTokenException { + Optional tokenOptional = accessTokenRepo.findByIdAndUsername(tokenId, user.getUsername()); + if (!tokenOptional.isPresent()) { + throw new CannotFindTokenException("Token with id " + tokenId + " does not exist or does not belong to user."); + } + + DbAccessToken token = tokenOptional.get(); + if (!token.isPersonalAccessToken()) { + throw new CannotFindTokenException("Token with id " + tokenId + " is not a personal access token."); + } + + accessTokenRepo.delete(token); + } + + @Override + public PersonalAccessTokenCredentials regenerateToken(String tokenId, IUser user) throws CannotFindTokenException { + Optional tokenOptional = accessTokenRepo.findByIdAndUsername(tokenId, user.getUsername()); + if (!tokenOptional.isPresent()) { + throw new CannotFindTokenException("Token with id " + tokenId + " does not exist or does not belong to user."); + } + + DbAccessToken oldToken = tokenOptional.get(); + if (!oldToken.isPersonalAccessToken()) { + throw new CannotFindTokenException("Token with id " + tokenId + " is not a personal access token."); + } + + String tokenName = oldToken.getName(); + + accessTokenRepo.delete(oldToken); + + OAuthClient patClient = getOrCreatePATClientForUser(user); + OAuth2AccessToken newAccessToken = createAccessToken(patClient.getClientId(), user); + + DbAccessToken newDbToken = new DbAccessToken(); + newDbToken.setId(UUID.randomUUID().toString() + UUID.randomUUID().toString()); + newDbToken.setTokenId(extractTokenKey(newAccessToken.getValue())); + newDbToken.setToken(newAccessToken); + newDbToken.setUsername(user.getUsername()); + newDbToken.setClientId(patClient.getClientId()); + newDbToken.setName(tokenName); + newDbToken.setCreatedAt(OffsetDateTime.now()); + newDbToken.setPersonalAccessToken(true); + + accessTokenRepo.save(newDbToken); + + return new PersonalAccessTokenCredentials(newDbToken.getId(), newAccessToken.getValue(), tokenName); + } + + @Override + public IPersonalAccessToken getTokenById(String tokenId) { + Optional tokenOptional = accessTokenRepo.findById(tokenId); + if (tokenOptional.isPresent() && tokenOptional.get().isPersonalAccessToken()) { + return tokenOptional.get(); + } + return null; + } + + /** + * Gets or creates the personal access token OAuthClient for a user. + * Each user has exactly one OAuthClient that is used for all their personal access tokens. + */ + private OAuthClient getOrCreatePATClientForUser(IUser user) { + Optional existingClient = clientRepo.findByCreatedByUsernameAndIsUserAccessToken( + user.getUsername(), true); + + if (existingClient.isPresent()) { + return existingClient.get(); + } + + OAuthClient client = new OAuthClient(); + client.setName("Personal Access Token Client for " + user.getUsername()); + String clientSecret = UUID.randomUUID().toString(); + client.setClientSecret(bCryptPasswordEncoder.encode(clientSecret)); + + List authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority(Role.TRUSTED_CLIENT)); + client.setAuthorities(authorities); + + client.setScope(new HashSet<>()); + client.getScope().add(OAuthScope.READ.getScope()); + + client.setCreatedBy(user); + client.setIsUserAccessToken(true); + + return clientRepo.save(client); + } + + private OAuth2AccessToken createAccessToken(String clientId, IUser user) { + if (requestFactory == null) { + requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); + } + + DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); + token.setScope(Sets.asSet(OAuthScope.READ.getScope())); + AuthorizationRequest request = new AuthorizationRequest(clientId, token.getScope()); + TokenRequest implicitRequest = new ImplicitTokenRequest( + requestFactory.createTokenRequest(request, "implicit"), + requestFactory.createOAuth2Request(request)); + OAuth2Authentication authentication = getOAuth2Authentication( + clientDetailsService.loadClientByClientId(clientId), implicitRequest, user); + tokenStore.storeAccessToken(token, authentication); + return token; + } + + private OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest, IUser user) { + if (requestFactory == null) { + requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService); + } + OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(client, tokenRequest); + Authentication authentication = new UsernamePasswordAuthenticationToken(user, null, user.getRoles()); + return new OAuth2Authentication(storedOAuth2Request, authentication); + } + + private String extractTokenKey(String value) { + if (value == null) { + return null; + } + MessageDigest digest; + try { + digest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); + } + + try { + byte[] bytes = digest.digest(value.getBytes("UTF-8")); + return String.format("%032x", new BigInteger(1, bytes)); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); + } + } +} diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java index adea9ea06..be08e4afb 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AccessTokenDetailsController.java @@ -7,20 +7,22 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import edu.asu.diging.citesphere.core.model.oauth.IOAuthClient; -import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; +import edu.asu.diging.citesphere.core.model.oauth.IPersonalAccessToken; +import edu.asu.diging.citesphere.core.service.oauth.IPersonalAccessTokenManager; @Controller public class AccessTokenDetailsController { - + @Autowired - private IOAuthClientManager clientManager; - + private IPersonalAccessTokenManager tokenManager; + @RequestMapping(value="/admin/user/auth/accessTokens/{accessTokenId}", method=RequestMethod.GET) public String showAppDetails(Model model, @PathVariable("accessTokenId") String accessTokenId) { - IOAuthClient details = (IOAuthClient) clientManager.loadClientByClientId(accessTokenId); - model.addAttribute("clientName", details.getName()); - model.addAttribute("clientId", details.getClientId()); + IPersonalAccessToken token = tokenManager.getTokenById(accessTokenId); + if (token != null) { + model.addAttribute("clientName", token.getName()); + model.addAttribute("clientId", accessTokenId); + } return "admin/user/auth/details"; } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java index 06a85c818..b8f8aa757 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/AddUserAccessTokenController.java @@ -11,33 +11,33 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; +import edu.asu.diging.citesphere.core.service.oauth.IPersonalAccessTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.PersonalAccessTokenCredentials; import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; import edu.asu.diging.citesphere.web.admin.forms.UserAccessTokenForm; @Controller public class AddUserAccessTokenController { - + @Autowired private IUserManager userManager; - + @Autowired - private IOAuthClientManager clientManager; - + private IPersonalAccessTokenManager tokenManager; + @RequestMapping(value="/admin/user/auth/accessTokens/add", method=RequestMethod.GET) public String show(Model model) { model.addAttribute("userAccessTokenForm", new UserAccessTokenForm()); return "admin/user/auth/add"; } - + @RequestMapping(value="/admin/user/auth/accessTokens/add", method=RequestMethod.POST) public String add(@Validated UserAccessTokenForm userAccessTokenForm, Model model, BindingResult errors, RedirectAttributes redirectAttrs, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); - OAuthCredentials creds = clientManager.createUserAccessToken(userAccessTokenForm.getName(), user); - redirectAttrs.addFlashAttribute("clientId", creds.getClientId()); - redirectAttrs.addFlashAttribute("secret", creds.getSecret()); - return "redirect:/admin/user/auth/accessTokens/" + creds.getClientId(); + PersonalAccessTokenCredentials creds = tokenManager.createToken(userAccessTokenForm.getName(), user); + redirectAttrs.addFlashAttribute("clientId", creds.getTokenId()); + redirectAttrs.addFlashAttribute("secret", creds.getTokenValue()); + return "redirect:/admin/user/auth/accessTokens/" + creds.getTokenId(); } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java index 2a0e10b5c..21b1881c4 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/DeleteAccessTokenController.java @@ -1,5 +1,7 @@ package edu.asu.diging.citesphere.web.admin.userOAuth; +import java.security.Principal; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -8,17 +10,28 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; +import edu.asu.diging.citesphere.core.exceptions.CannotFindTokenException; +import edu.asu.diging.citesphere.core.service.oauth.IPersonalAccessTokenManager; +import edu.asu.diging.citesphere.core.user.IUserManager; +import edu.asu.diging.citesphere.user.IUser; @Controller public class DeleteAccessTokenController { - + @Autowired - private IOAuthClientManager clientManager; - + private IUserManager userManager; + + @Autowired + private IPersonalAccessTokenManager tokenManager; + @RequestMapping(value = "/admin/user/auth/accessTokens/{accessTokenId}", method = RequestMethod.DELETE) - public ResponseEntity deleteApp(@PathVariable("accessTokenId") String accessTokenId) { - clientManager.deleteClient(accessTokenId); - return new ResponseEntity<>(HttpStatus.OK); + public ResponseEntity deleteApp(@PathVariable("accessTokenId") String accessTokenId, Principal principal) { + IUser user = userManager.findByUsername(principal.getName()); + try { + tokenManager.deleteToken(accessTokenId, user); + return new ResponseEntity<>(HttpStatus.OK); + } catch (CannotFindTokenException e) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } } } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java index 1ba1fce8a..207981aea 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/ShowAccessTokensController.java @@ -9,25 +9,25 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.UserAccessTokenResultPage; +import edu.asu.diging.citesphere.core.service.oauth.IPersonalAccessTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.PersonalAccessTokenResultPage; import edu.asu.diging.citesphere.core.user.IUserManager; import edu.asu.diging.citesphere.user.IUser; @Controller public class ShowAccessTokensController { - + @Autowired private IUserManager userManager; - + @Autowired - private IOAuthClientManager clientManager; - + private IPersonalAccessTokenManager tokenManager; + @RequestMapping(value="/admin/user/auth/accessTokens", method=RequestMethod.GET) public String showAllApps(Model model, Pageable pageable, Principal principal) { IUser user = userManager.findByUsername(principal.getName()); - UserAccessTokenResultPage result = clientManager.getAllUserAccessTokenDetails(pageable, user); - model.addAttribute("clientList", result.getClientList()); + PersonalAccessTokenResultPage result = tokenManager.getTokensForUser(user, pageable); + model.addAttribute("tokenList", result.getTokens()); model.addAttribute("currentPage", pageable.getPageNumber()+1); model.addAttribute("totalPages", result.getTotalPages()); return "admin/user/auth/show"; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java index 5cfa3044b..85cbcc296 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/admin/userOAuth/UpdateAccessTokenController.java @@ -1,5 +1,7 @@ package edu.asu.diging.citesphere.web.admin.userOAuth; +import java.security.Principal; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -8,18 +10,24 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import edu.asu.diging.citesphere.core.exceptions.CannotFindClientException; -import edu.asu.diging.citesphere.core.service.oauth.IOAuthClientManager; -import edu.asu.diging.citesphere.core.service.oauth.OAuthCredentials; +import edu.asu.diging.citesphere.core.exceptions.CannotFindTokenException; +import edu.asu.diging.citesphere.core.service.oauth.IPersonalAccessTokenManager; +import edu.asu.diging.citesphere.core.service.oauth.PersonalAccessTokenCredentials; +import edu.asu.diging.citesphere.core.user.IUserManager; +import edu.asu.diging.citesphere.user.IUser; @Controller public class UpdateAccessTokenController { - + @Autowired - private IOAuthClientManager clientManager; - + private IUserManager userManager; + + @Autowired + private IPersonalAccessTokenManager tokenManager; + @RequestMapping(value="/admin/user/auth/accessTokens/{accessTokenId}/secret/update", method=RequestMethod.POST) - public @ResponseBody OAuthCredentials regenerateClientSecret(Model model, @PathVariable("accessTokenId") String accessTokenId) throws CannotFindClientException { - return clientManager.updateClientSecret(accessTokenId); + public @ResponseBody PersonalAccessTokenCredentials regenerateToken(Model model, @PathVariable("accessTokenId") String accessTokenId, Principal principal) throws CannotFindTokenException { + IUser user = userManager.findByUsername(principal.getName()); + return tokenManager.regenerateToken(accessTokenId, user); } } diff --git a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html index e114d1aae..88e849c2e 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html +++ b/citesphere/src/main/webapp/WEB-INF/views/admin/user/auth/show.html @@ -85,10 +85,10 @@

        Tokens

        - - - - + + + +