Commit e9e6e37b authored by Matija Obreza's avatar Matija Obreza
Browse files

Updates to OAuth token management

parent ba9efe93
...@@ -16,13 +16,18 @@ ...@@ -16,13 +16,18 @@
package org.genesys2.server.model.oauth; package org.genesys2.server.model.oauth;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import org.genesys2.server.model.HibernateModel; import org.genesys2.server.model.HibernateModel;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.SerializationUtils; import org.springframework.security.oauth2.common.util.SerializationUtils;
import javax.persistence.*;
import java.util.Date;
@Entity @Entity
@Table(name = "oauth_access_token") @Table(name = "oauth_access_token")
public class OAuthAccessToken implements HibernateModel { public class OAuthAccessToken implements HibernateModel {
...@@ -53,31 +58,18 @@ public class OAuthAccessToken implements HibernateModel { ...@@ -53,31 +58,18 @@ public class OAuthAccessToken implements HibernateModel {
@Column(name = "refresh_token") @Column(name = "refresh_token")
private String refreshToken; private String refreshToken;
@Column(name = "created_date") @Column(name = "created_date")
private Date createdDate; private Date createdDate;
private DefaultOAuth2AccessToken defaultOAuth2AccessToken;
private synchronized DefaultOAuth2AccessToken getDefaultOAuth2AccessToken () { public Date getCreatedDate() {
if (this.defaultOAuth2AccessToken==null) { return createdDate;
this.defaultOAuth2AccessToken = SerializationUtils.deserialize(this.token); }
}
return this.defaultOAuth2AccessToken;
}
public Date getTokenExpiration() {
return getDefaultOAuth2AccessToken().getExpiration();
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) { public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate; this.createdDate = createdDate;
} }
public String getTokenId() { public String getTokenId() {
return tokenId; return tokenId;
} }
...@@ -171,4 +163,8 @@ public class OAuthAccessToken implements HibernateModel { ...@@ -171,4 +163,8 @@ public class OAuthAccessToken implements HibernateModel {
result = 31 * result + (refreshToken != null ? refreshToken.hashCode() : 0); result = 31 * result + (refreshToken != null ? refreshToken.hashCode() : 0);
return result; return result;
} }
public OAuth2AccessToken getAccessToken() {
return SerializationUtils.deserialize(this.token);
}
} }
...@@ -107,7 +107,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore { ...@@ -107,7 +107,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore {
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>(); List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
for (OAuthAccessToken token : accessTokenPersistence.findByClientId(clientId)) { for (OAuthAccessToken token : accessTokenPersistence.findByClientId(clientId)) {
if (token != null) { if (token != null) {
tokens.add(deserializeAccessToken(token.getToken())); tokens.add(token.getAccessToken());
} }
} }
return tokens; return tokens;
...@@ -118,7 +118,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore { ...@@ -118,7 +118,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore {
List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>(); List<OAuth2AccessToken> tokens = new ArrayList<OAuth2AccessToken>();
for (OAuthAccessToken token : accessTokenPersistence.findByUserName(username)) { for (OAuthAccessToken token : accessTokenPersistence.findByUserName(username)) {
if (token != null) { if (token != null) {
tokens.add(deserializeAccessToken(token.getToken())); tokens.add(token.getAccessToken());
} }
} }
return tokens; return tokens;
...@@ -132,7 +132,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore { ...@@ -132,7 +132,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore {
try { try {
// FIXME Dies with two keys issued to same user in same client // FIXME Dies with two keys issued to same user in same client
OAuthAccessToken persisted = accessTokenPersistence.findByAuthenticationId(key); OAuthAccessToken persisted = accessTokenPersistence.findByAuthenticationId(key);
accessToken = deserializeAccessToken(persisted.getToken()); accessToken = persisted.getAccessToken();
} catch (NullPointerException e) { } catch (NullPointerException e) {
if (LOG.isInfoEnabled()) { if (LOG.isInfoEnabled()) {
LOG.debug("Failed to find access token for authentication " + authentication); LOG.debug("Failed to find access token for authentication " + authentication);
...@@ -157,7 +157,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore { ...@@ -157,7 +157,7 @@ public class OAuth2JPATokenStoreImpl implements TokenStore {
try { try {
OAuthAccessToken persisted = accessTokenPersistence.findOne(extractTokenKey(tokenValue)); OAuthAccessToken persisted = accessTokenPersistence.findOne(extractTokenKey(tokenValue));
accessToken = deserializeAccessToken(persisted.getToken()); accessToken = persisted.getAccessToken();
} catch (NullPointerException e) { } catch (NullPointerException e) {
if (LOG.isInfoEnabled()) { if (LOG.isInfoEnabled()) {
LOG.info("Failed to find access token for token " + tokenValue); LOG.info("Failed to find access token for token " + tokenValue);
...@@ -324,10 +324,6 @@ public class OAuth2JPATokenStoreImpl implements TokenStore { ...@@ -324,10 +324,6 @@ public class OAuth2JPATokenStoreImpl implements TokenStore {
return SerializationUtils.serialize(authentication); return SerializationUtils.serialize(authentication);
} }
protected OAuth2AccessToken deserializeAccessToken(byte[] token) {
return SerializationUtils.deserialize(token);
}
protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) { protected OAuth2RefreshToken deserializeRefreshToken(byte[] token) {
return SerializationUtils.deserialize(token); return SerializationUtils.deserialize(token);
} }
......
package org.genesys2.server.servlet.controller; package org.genesys2.server.servlet.controller;
import org.genesys2.server.model.oauth.OAuthAccessToken; import org.genesys2.server.model.oauth.OAuthAccessToken;
import org.genesys2.server.service.OAuth2ClientDetailsService; import org.genesys2.server.service.OAuth2ClientDetailsService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -16,70 +15,67 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -16,70 +15,67 @@ import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Collection; import java.util.Collection;
@Controller @Controller
@RequestMapping("/management") @RequestMapping("/management")
public class OAuthManagementController extends BaseController { public class OAuthManagementController extends BaseController {
@Autowired
@Autowired private OAuth2ClientDetailsService clientDetailsService;
private OAuth2ClientDetailsService clientDetailsService;
@Autowired
@Autowired @Qualifier("tokenStore")
@Qualifier("tokenStore") private TokenStore tokenStore;
private TokenStore tokenStore;
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping("/allTokens")
@PreAuthorize("hasRole('ADMINISTRATOR')") public String getAllTokens(Model model) {
@RequestMapping("/allTokens") model.addAttribute("clientDetailsList", clientDetailsService.listClientDetails());
public String getAllTokens(Model model) { return "/oauth/clientslist";
model.addAttribute("clientDetailsList", clientDetailsService.listClientDetails()); }
return "/oauth/clientslist";
} @PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping("/{clientId}")
@PreAuthorize("hasRole('ADMINISTRATOR')") public String clientDetailsInfo(Model model, @PathVariable("clientId") String clientId) {
@RequestMapping("/{clientId}") ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
public String clientDetailsInfo(Model model, @PathVariable("clientId") String clientId) { Collection<OAuthAccessToken> tokensByClientId = clientDetailsService.findTokensByClientId(clientId);
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
Collection<OAuthAccessToken> tokensByClientId = clientDetailsService.findTokensByClientId(clientId); model.addAttribute("accessTokens", tokensByClientId);
model.addAttribute("clientDetails", clientDetails);
model.addAttribute("accessTokens", tokensByClientId); return "/oauth/detailsinfo";
model.addAttribute("clientDetails", clientDetails); }
return "/oauth/detailsinfo";
} @PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping("/{clientId}/removeAll")
@PreAuthorize("hasRole('ADMINISTRATOR')") public String removeAllAccessTokens(@PathVariable("clientId") String clientId) {
@RequestMapping("/{clientId}/removeAll")
public String removeAllAccessTokens(@PathVariable("clientId") String clientId) { Collection<OAuthAccessToken> tokens = clientDetailsService.findTokensByClientId(clientId);
for (OAuthAccessToken token : tokens) {
Collection<OAuthAccessToken> tokens = clientDetailsService.findTokensByClientId(clientId); tokenStore.removeAccessToken(new DefaultOAuth2AccessToken(token.getTokenId()));
for (OAuthAccessToken token : tokens) { }
tokenStore.removeAccessToken(new DefaultOAuth2AccessToken(token.getTokenId()));
} return "redirect:/management/" + clientId;
}
return "redirect:/management/" + clientId;
} @PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping("/{clientId}/{tokenId}/remove")
@PreAuthorize("hasRole('ADMINISTRATOR')") public String removeAccessTokens(@PathVariable("tokenId") String tokenId, @PathVariable("clientId") String clientId) {
@RequestMapping("/{clientId}/{tokenId}/remove")
public String removeAccessTokens(@PathVariable("tokenId") String tokenId, tokenStore.removeAccessToken(new DefaultOAuth2AccessToken(tokenId));
@PathVariable("clientId") String clientId) { return "redirect:/management/" + clientId;
}
tokenStore.removeAccessToken(new DefaultOAuth2AccessToken(tokenId));
return "redirect:/management/" + clientId; @RequestMapping("/user/{uuid}/tokens")
} @PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.uuid == #uuid")
public String getIssuedTokens(@PathVariable("uuid") String uuid, Model model) {
@RequestMapping("/user/{userName}/tokens") Collection<OAuthAccessToken> tokens = clientDetailsService.findTokensByUserName(uuid);
public String getIssuedTokens(@PathVariable("userName") String userName, Model model) { model.addAttribute("tokens", tokens);
Collection<OAuthAccessToken> tokens = clientDetailsService.findTokensByUserName(userName); return "/oauth/tokenslist";
model.addAttribute("tokens", tokens); }
return "/oauth/tokenslist";
} @RequestMapping("/user/{uuid}/{tokenId}/remove")
@PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.uuid == #uuid")
@RequestMapping("/user/{userName}/{tokenId}/remove") public String removeUsersAccessToken(@PathVariable("tokenId") String tokenId, @PathVariable("uuid") String uuid) {
public String removeUsersAccessToken(@PathVariable("tokenId") String tokenId, tokenStore.removeAccessToken(new DefaultOAuth2AccessToken(tokenId));
@PathVariable("userName") String userName) { return "redirect:/management/user/" + uuid + "/tokens";
tokenStore.removeAccessToken(new DefaultOAuth2AccessToken(tokenId)); }
return "redirect:/management/user/" + userName + "/tokens";
}
} }
...@@ -54,7 +54,6 @@ ...@@ -54,7 +54,6 @@
<prop key="hibernate.hbm2ddl.auto">${db.hbm2ddl}</prop> <prop key="hibernate.hbm2ddl.auto">${db.hbm2ddl}</prop>
<prop key="hibernate.search.default.indexBase">${lucene.indexDir}</prop> <prop key="hibernate.search.default.indexBase">${lucene.indexDir}</prop>
<prop key="hibernate.search.default.exclusive_index_use">false</prop> <prop key="hibernate.search.default.exclusive_index_use">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props> </props>
</property> </property>
<property name="packagesToScan"> <property name="packagesToScan">
......
...@@ -61,8 +61,4 @@ ...@@ -61,8 +61,4 @@
<sec:expression-handler ref="webExpressionHandler"/> <sec:expression-handler ref="webExpressionHandler"/>
</sec:http> </sec:http>
<bean name="jdbcTokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
<constructor-arg ref="dataSource"/>
</bean>
</beans> </beans>
\ No newline at end of file
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
base.url=http://localhost:8080 base.url=http://localhost:8080
db.url=jdbc:mysql://localhost/genesys2?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false db.url=jdbc:mysql://localhost/genesys4?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
db.driverClassName = com.mysql.jdbc.Driver db.driverClassName = com.mysql.jdbc.Driver
db.username = root db.username = root
db.password = 1 db.password =
db.showSql=false db.showSql=true
db.hbm2ddl=update db.hbm2ddl=do-nothing
c3p0.acquireIncrement=1 c3p0.acquireIncrement=1
c3p0.minPoolSize=1 c3p0.minPoolSize=1
......
...@@ -23,12 +23,13 @@ ...@@ -23,12 +23,13 @@
<div class="form-group"> <div class="form-group">
<label class="col-lg-2 control-label"><spring:message code="clinet.details.token.list"/></label> <label class="col-lg-2 control-label"><spring:message code="clinet.details.token.list"/></label>
<div class="col-lg-5"> <div class="col-lg-10">
<table class="accessions"> <table class="accessions">
<tbody> <tbody>
<c:forEach items="${accessTokens}" var="accessToken"> <c:forEach items="${accessTokens}" var="accessToken">
<tr> <tr class="${accessToken.accessToken.expired ? 'expired' : ''}">
<td>${accessToken.userName}</td> <td>${accessToken.userName}</td>
<td><c:out value="${jspHelper.userByUuid(accessToken.userName).email}"/></td>
<td> <td>
<a href="<c:url value="/management/${clientDetails.clientId}/${accessToken.tokenId}/remove"/> "><spring:message <a href="<c:url value="/management/${clientDetails.clientId}/${accessToken.tokenId}/remove"/> "><spring:message
code="oauth-client.remove"/></a> code="oauth-client.remove"/></a>
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
<tbody> <tbody>
<c:forEach items="${tokens}" var="token"> <c:forEach items="${tokens}" var="token">
<tr> <tr class="${token.accessToken.expired ? 'expired' : ''}">
<td> <td>
<a href="<c:url value="/management/${token.clientId}"/> ">${token.clientId}</a> <a href="<c:url value="/management/${token.clientId}"/> ">${token.clientId}</a>
</td> </td>
...@@ -33,9 +33,10 @@ ...@@ -33,9 +33,10 @@
<fmt:formatDate value="${token.createdDate}" pattern="MM-dd-yyyy hh:mm:ss"/> <fmt:formatDate value="${token.createdDate}" pattern="MM-dd-yyyy hh:mm:ss"/>
</td> </td>
<td> <td>
<fmt:formatDate value="${token.tokenExpiration}" pattern="MM-dd-yyyy hh:mm:ss"/> <fmt:formatDate value="${token.accessToken.expiration}" pattern="MM-dd-yyyy hh:mm:ss"/>
</td> </td>
<td> <td>
<!-- FIXME Use POST -->
<a href="<c:url value="/management/user/${token.userName}/${token.tokenId}/remove"/>"><spring:message <a href="<c:url value="/management/user/${token.userName}/${token.tokenId}/remove"/>"><spring:message
code="oauth-client.remove"/></a> code="oauth-client.remove"/></a>
</td> </td>
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
<a href="<c:url value="/management/allTokens" />" class="btn btn-default"> <spring:message code="oauth-client.list" /></a> <a href="<c:url value="/management/allTokens" />" class="btn btn-default"> <spring:message code="oauth-client.list" /></a>
</security:authorize> </security:authorize>
<security:authorize access="hasRole('ADMINISTRATOR') || (isAuthenticated() && principal.user.id == #user.id)"> <security:authorize access="hasRole('ADMINISTRATOR') || (isAuthenticated() && principal.user.id == #user.id)">
<a href="<c:url value="/management/user/${user.email}/tokens" />" class="btn btn-default"><spring:message code="oauth-client.issued.tokens" /></a> <a href="<c:url value="/management/user/${user.uuid}/tokens" />" class="btn btn-default"><spring:message code="oauth-client.issued.tokens" /></a>
</security:authorize> </security:authorize>
<security:authorize access="(not hasRole('VALIDATEDUSER') && principal.user.id == #user.id)"> <security:authorize access="(not hasRole('VALIDATEDUSER') && principal.user.id == #user.id)">
<a href="<c:url value="/profile/${user.uuid}/send"/>" class="btn btn-default"/>Send validation email</a> <a href="<c:url value="/profile/${user.uuid}/send"/>" class="btn btn-default"/>Send validation email</a>
......
...@@ -1234,7 +1234,7 @@ ul.funny-list { ...@@ -1234,7 +1234,7 @@ ul.funny-list {
background-position:center right; background-position:center right;
} }
table.accessions tr.not-available > td { table.accessions tr.not-available > td, table tr.expired > td {
text-decoration: line-through; text-decoration: line-through;
opacity:0.5; opacity:0.5;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment