diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java index dbbed83b3..182555169 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java @@ -57,6 +57,7 @@ import com.nimbusds.jwt.JWTParser; @Entity @Table(name = "access_token") @NamedQueries({ + @NamedQuery(name = "OAuth2AccessTokenEntity.getAll", query = "select a from OAuth2AccessTokenEntity a"), @NamedQuery(name = "OAuth2AccessTokenEntity.getByRefreshToken", query = "select a from OAuth2AccessTokenEntity a where a.refreshToken = :refreshToken"), @NamedQuery(name = "OAuth2AccessTokenEntity.getByClient", query = "select a from OAuth2AccessTokenEntity a where a.client = :client"), @NamedQuery(name = "OAuth2AccessTokenEntity.getExpired", query = "select a from OAuth2AccessTokenEntity a where a.expiration is not null and a.expiration < current_timestamp"), diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java index 488e48930..c55ac33ab 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2RefreshTokenEntity.java @@ -49,6 +49,7 @@ import com.nimbusds.jwt.JWTParser; @Entity @Table(name = "refresh_token") @NamedQueries({ + @NamedQuery(name = "OAuth2RefreshTokenEntity.getAll", query = "select r from OAuth2RefreshTokenEntity r"), @NamedQuery(name = "OAuth2RefreshTokenEntity.getByClient", query = "select r from OAuth2RefreshTokenEntity r where r.client = :client"), @NamedQuery(name = "OAuth2RefreshTokenEntity.getExpired", query = "select r from OAuth2RefreshTokenEntity r where r.expiration is not null and r.expiration < current_timestamp"), @NamedQuery(name = "OAuth2RefreshTokenEntity.getByTokenValue", query = "select r from OAuth2RefreshTokenEntity r where r.value = :tokenValue"), diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java index bf58a3547..37b569291 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java @@ -17,6 +17,7 @@ package org.mitre.oauth2.repository; import java.util.List; +import java.util.Set; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; @@ -60,4 +61,8 @@ public interface OAuth2TokenRepository { */ public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken); + public Set getAllAccessTokens(); + + public Set getAllRefreshTokens(); + } diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java b/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java index cbb5c51df..8cd64ccd5 100644 --- a/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java +++ b/openid-connect-common/src/main/java/org/mitre/oauth2/service/OAuth2TokenEntityService.java @@ -17,6 +17,7 @@ package org.mitre.oauth2.service; import java.util.List; +import java.util.Set; import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity; @@ -27,6 +28,10 @@ import org.springframework.security.oauth2.provider.token.ResourceServerTokenSer public interface OAuth2TokenEntityService extends AuthorizationServerTokenServices, ResourceServerTokenServices { + public Set getAllAccessTokens(); + + public Set getAllRefreshTokens(); + @Override public OAuth2AccessTokenEntity readAccessToken(String accessTokenValue); @@ -55,4 +60,8 @@ public interface OAuth2TokenEntityService extends AuthorizationServerTokenServic */ public OAuth2AccessTokenEntity getAccessTokenForIdToken(OAuth2AccessTokenEntity idToken); + public OAuth2AccessTokenEntity getAccessTokenById(Long id); + + public OAuth2RefreshTokenEntity getRefreshTokenById(Long id); + } diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java index e4dd3272e..b41ccbb20 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaOAuth2TokenRepository.java @@ -16,7 +16,9 @@ ******************************************************************************/ package org.mitre.oauth2.repository.impl; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @@ -37,6 +39,18 @@ public class JpaOAuth2TokenRepository implements OAuth2TokenRepository { @PersistenceContext private EntityManager manager; + @Override + public Set getAllAccessTokens() { + TypedQuery query = manager.createNamedQuery("OAuth2AccessTokenEntity.getAll", OAuth2AccessTokenEntity.class); + return new LinkedHashSet(query.getResultList()); + } + + @Override + public Set getAllRefreshTokens() { + TypedQuery query = manager.createNamedQuery("OAuth2RefreshTokenEntity.getAll", OAuth2RefreshTokenEntity.class); + return new LinkedHashSet(query.getResultList()); + } + @Override public OAuth2AccessTokenEntity getAccessTokenByValue(String accessTokenValue) { TypedQuery query = manager.createNamedQuery("OAuth2AccessTokenEntity.getByTokenValue", OAuth2AccessTokenEntity.class); diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java index 0207fb560..53275502c 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java @@ -36,7 +36,6 @@ import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; @@ -73,6 +72,22 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi @Autowired private TokenEnhancer tokenEnhancer; + public Set getAllAccessTokens() { + return tokenRepository.getAllAccessTokens(); + } + + public Set getAllRefreshTokens() { + return tokenRepository.getAllRefreshTokens(); + } + + public OAuth2AccessTokenEntity getAccessTokenById(Long id) { + return tokenRepository.getAccessTokenById(id); + } + + public OAuth2RefreshTokenEntity getRefreshTokenById(Long id) { + return tokenRepository.getRefreshTokenById(id); + } + @Override public OAuth2AccessTokenEntity createAccessToken(OAuth2Authentication authentication) throws AuthenticationException, InvalidClientException { if (authentication != null && authentication.getAuthorizationRequest() != null) { diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/AccessTokenAPI.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/AccessTokenAPI.java new file mode 100644 index 000000000..72390ed57 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/AccessTokenAPI.java @@ -0,0 +1,86 @@ +package org.mitre.oauth2.web; + +import java.util.Set; + +import org.mitre.oauth2.model.OAuth2AccessTokenEntity; +import org.mitre.oauth2.service.OAuth2TokenEntityService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * REST-ish API for managing access tokens (no PUT; tokens cannot be updated and creation = OAuth). + * @author Amanda Anganes + * + */ +@Controller +@RequestMapping("/api/tokens/at") +@PreAuthorize("hasRole('ROLE_USER')") +public class AccessTokenAPI { + + @Autowired + private OAuth2TokenEntityService tokenService; + + private static Logger logger = LoggerFactory.getLogger(AccessTokenAPI.class); + + @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json") + public String getAll(ModelMap m) { + + Set allTokens = tokenService.getAllAccessTokens(); + + m.put("entity", allTokens); + + return "jsonEntityView"; + } + + @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json") + public String getById(@PathVariable("id") Long id, ModelMap m) { + + OAuth2AccessTokenEntity token = tokenService.getAccessTokenById(id); + + if (token != null) { + + m.put("entity", token); + + return "jsonEntityView"; + } else { + + logger.error("getToken failed; token not found: " + id); + + m.put("code", HttpStatus.NOT_FOUND); + m.put("errorMessage", "The requested token with id " + id + " could not be found."); + return "jsonErrorView"; + } + } + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + public String delete(@PathVariable("id") Long id, ModelMap m) { + + OAuth2AccessTokenEntity token = tokenService.getAccessTokenById(id); + + if (token != null) { + + tokenService.revokeAccessToken(token); + m.put("code", HttpStatus.OK); + return "httpCodeView"; + + } else { + + logger.error("Delete token failed; token not found: " + id); + + m.put("code", HttpStatus.NOT_FOUND); + m.put("errorMessage", "The requested token with id " + id + " could not be found."); + return "jsonErrorView"; + } + + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/RefreshTokenAPI.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/RefreshTokenAPI.java new file mode 100644 index 000000000..4c1e8f00b --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/RefreshTokenAPI.java @@ -0,0 +1,87 @@ +package org.mitre.oauth2.web; + +import java.util.Set; + +import org.mitre.oauth2.model.OAuth2RefreshTokenEntity; +import org.mitre.oauth2.service.OAuth2TokenEntityService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +/** + * REST-ish API for managing refresh tokens (no PUT; tokens cannot be updated and creation = OAuth). + * + * @author Amanda Anganes + * + */ +@Controller +@RequestMapping("/api/tokens/rt") +@PreAuthorize("hasRole('ROLE_USER')") +public class RefreshTokenAPI { + + @Autowired + private OAuth2TokenEntityService tokenService; + + private static Logger logger = LoggerFactory.getLogger(RefreshTokenAPI.class); + + @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json") + public String getAll(ModelMap m) { + + Set allTokens = tokenService.getAllRefreshTokens(); + + m.put("entity", allTokens); + + return "jsonEntityView"; + } + + @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json") + public String getById(@PathVariable("id") Long id, ModelMap m) { + + OAuth2RefreshTokenEntity token = tokenService.getRefreshTokenById(id); + + if (token != null) { + + m.put("entity", token); + + return "jsonEntityView"; + } else { + + logger.error("getToken failed; token not found: " + id); + + m.put("code", HttpStatus.NOT_FOUND); + m.put("errorMessage", "The requested token with id " + id + " could not be found."); + return "jsonErrorView"; + } + } + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + public String delete(@PathVariable("id") Long id, ModelMap m) { + + OAuth2RefreshTokenEntity token = tokenService.getRefreshTokenById(id); + + if (token != null) { + + tokenService.revokeRefreshToken(token); + m.put("code", HttpStatus.OK); + return "httpCodeView"; + + } else { + + logger.error("Delete token failed; token not found: " + id); + + m.put("code", HttpStatus.NOT_FOUND); + m.put("errorMessage", "The requested token with id " + id + " could not be found."); + return "jsonErrorView"; + } + + } + +}