Fleshed out nonce service classes, added code to token service impl to check for and store nonces. Added JodaTime library for working with dates.
parent
c7ae315e98
commit
a4637ec395
|
@ -19,13 +19,15 @@ import javax.persistence.Temporal;
|
||||||
@NamedQueries({
|
@NamedQueries({
|
||||||
@NamedQuery(name = "Nonce.getAll", query = "select n from Nonce n"),
|
@NamedQuery(name = "Nonce.getAll", query = "select n from Nonce n"),
|
||||||
@NamedQuery(name = "Nonce.getByClientId", query = "select n from Nonce n where n.clientId = :clientId"),
|
@NamedQuery(name = "Nonce.getByClientId", query = "select n from Nonce n where n.clientId = :clientId"),
|
||||||
@NamedQuery(name = "Nonce.getExpired", query = "select n from Nonce n where n.expireDate < now()")
|
@NamedQuery(name = "Nonce.getExpired", query = "select n from Nonce n where n.expireDate is not null and n.expireDate < current_timestamp")
|
||||||
})
|
})
|
||||||
public class Nonce {
|
public class Nonce {
|
||||||
|
|
||||||
|
|
||||||
private Long id; //the ID of this Nonce
|
private Long id; //the ID of this Nonce
|
||||||
|
|
||||||
|
private String value; //the value of this Nonce
|
||||||
|
|
||||||
private String clientId;//The id of the client who used this Nonce
|
private String clientId;//The id of the client who used this Nonce
|
||||||
|
|
||||||
private Date useDate; //the date this Nonce was used
|
private Date useDate; //the date this Nonce was used
|
||||||
|
@ -48,6 +50,22 @@ public class Nonce {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the value
|
||||||
|
*/
|
||||||
|
@Basic
|
||||||
|
@Column(name="value")
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param value the value to set
|
||||||
|
*/
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the clientId
|
* @return the clientId
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,4 +60,9 @@ public interface NonceService {
|
||||||
*/
|
*/
|
||||||
public Collection<Nonce> getByClientId(String clientId);
|
public Collection<Nonce> getByClientId(String clientId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear expired nonces from the database
|
||||||
|
*/
|
||||||
|
void clearExpiredNonces();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
<artifactId>hsqldb</artifactId>
|
<artifactId>hsqldb</artifactId>
|
||||||
<version>2.2.9</version>
|
<version>2.2.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>joda-time</groupId>
|
||||||
|
<artifactId>joda-time</artifactId>
|
||||||
|
<version>2.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<description>Reference implementation of OpenID Connect spec (http://openid.net/connect/).
|
<description>Reference implementation of OpenID Connect spec (http://openid.net/connect/).
|
||||||
</description>
|
</description>
|
||||||
|
|
|
@ -18,11 +18,15 @@
|
||||||
*/
|
*/
|
||||||
package org.mitre.oauth2.service.impl;
|
package org.mitre.oauth2.service.impl;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.Period;
|
||||||
|
import org.mitre.oauth2.exception.NonceReuseException;
|
||||||
import org.mitre.oauth2.model.AuthenticationHolderEntity;
|
import org.mitre.oauth2.model.AuthenticationHolderEntity;
|
||||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||||
|
@ -31,6 +35,8 @@ import org.mitre.oauth2.repository.AuthenticationHolderRepository;
|
||||||
import org.mitre.oauth2.repository.OAuth2TokenRepository;
|
import org.mitre.oauth2.repository.OAuth2TokenRepository;
|
||||||
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
||||||
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
||||||
|
import org.mitre.openid.connect.model.Nonce;
|
||||||
|
import org.mitre.openid.connect.service.NonceService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -65,6 +71,12 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
|
||||||
@Autowired
|
@Autowired
|
||||||
private ClientDetailsEntityService clientDetailsService;
|
private ClientDetailsEntityService clientDetailsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NonceService nonceService;
|
||||||
|
|
||||||
|
//TODO how to specify this?
|
||||||
|
private Period nonceStorageDuration = new Period(1, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TokenEnhancer tokenEnhancer;
|
private TokenEnhancer tokenEnhancer;
|
||||||
|
|
||||||
|
@ -80,6 +92,28 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
|
||||||
throw new InvalidClientException("Client not found: " + clientAuth.getClientId());
|
throw new InvalidClientException("Client not found: " + clientAuth.getClientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String requestNonce = clientAuth.getAuthorizationParameters().get("nonce");
|
||||||
|
|
||||||
|
//Check request nonce for reuse
|
||||||
|
Collection<Nonce> clientNonces = nonceService.getByClientId(client.getClientId());
|
||||||
|
for (Nonce nonce : clientNonces) {
|
||||||
|
if (nonce.getValue().equals(requestNonce)) {
|
||||||
|
throw new NonceReuseException(client.getClientId(), nonce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Store nonce
|
||||||
|
Nonce nonce = new Nonce();
|
||||||
|
nonce.setClientId(client.getClientId());
|
||||||
|
nonce.setValue(requestNonce);
|
||||||
|
DateTime now = new DateTime(new Date());
|
||||||
|
DateTime expDate = now.plus(nonceStorageDuration);
|
||||||
|
Date expirationJdkDate = expDate.toDate();
|
||||||
|
nonce.setExpireDate(expirationJdkDate);
|
||||||
|
|
||||||
|
nonceService.save(nonce);
|
||||||
|
|
||||||
|
|
||||||
OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();//accessTokenFactory.createNewAccessToken();
|
OAuth2AccessTokenEntity token = new OAuth2AccessTokenEntity();//accessTokenFactory.createNewAccessToken();
|
||||||
|
|
||||||
// attach the client
|
// attach the client
|
||||||
|
@ -395,4 +429,18 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
|
||||||
return tokenRepository.getAccessTokenForIdToken(idToken);
|
return tokenRepository.getAccessTokenForIdToken(idToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the nonceStorageDuration
|
||||||
|
*/
|
||||||
|
public Period getNonceStorageDuration() {
|
||||||
|
return nonceStorageDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nonceStorageDuration the nonceStorageDuration to set
|
||||||
|
*/
|
||||||
|
public void setNonceStorageDuration(Period nonceStorageDuration) {
|
||||||
|
this.nonceStorageDuration = nonceStorageDuration;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,71 @@
|
||||||
package org.mitre.openid.connect.repository.impl;
|
package org.mitre.openid.connect.repository.impl;
|
||||||
|
|
||||||
|
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
import org.mitre.openid.connect.model.Nonce;
|
import org.mitre.openid.connect.model.Nonce;
|
||||||
import org.mitre.openid.connect.repository.NonceRepository;
|
import org.mitre.openid.connect.repository.NonceRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
public class JpaNonceRepository implements NonceRepository {
|
public class JpaNonceRepository implements NonceRepository {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager manager;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public Nonce getById(Long id) {
|
public Nonce getById(Long id) {
|
||||||
// TODO Auto-generated method stub
|
return manager.find(Nonce.class, id);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public void remove(Nonce nonce) {
|
public void remove(Nonce nonce) {
|
||||||
// TODO Auto-generated method stub
|
Nonce found = manager.find(Nonce.class, nonce.getId());
|
||||||
|
|
||||||
|
if (found != null) {
|
||||||
|
manager.remove(found);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Nonce reporitory remove: Nonce with id " + nonce.getId() + " could not be found.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public Nonce save(Nonce nonce) {
|
public Nonce save(Nonce nonce) {
|
||||||
// TODO Auto-generated method stub
|
return saveOrUpdate(nonce.getId(), manager, nonce);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public Collection<Nonce> getAll() {
|
public Collection<Nonce> getAll() {
|
||||||
// TODO Auto-generated method stub
|
TypedQuery<Nonce> query = manager.createNamedQuery("Nonce.getAll", Nonce.class);
|
||||||
return null;
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public Collection<Nonce> getExpired() {
|
public Collection<Nonce> getExpired() {
|
||||||
// TODO Auto-generated method stub
|
TypedQuery<Nonce> query = manager.createNamedQuery("Nonce.getExpired", Nonce.class);
|
||||||
return null;
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public Collection<Nonce> getByClientId(String clientId) {
|
public Collection<Nonce> getByClientId(String clientId) {
|
||||||
// TODO Auto-generated method stub
|
TypedQuery<Nonce> query = manager.createNamedQuery("Nonce.getByClientId", Nonce.class);
|
||||||
return null;
|
query.setParameter("clientId", clientId);
|
||||||
|
|
||||||
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,44 +3,64 @@ package org.mitre.openid.connect.service.impl;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.mitre.openid.connect.model.Nonce;
|
import org.mitre.openid.connect.model.Nonce;
|
||||||
|
import org.mitre.openid.connect.repository.NonceRepository;
|
||||||
import org.mitre.openid.connect.service.NonceService;
|
import org.mitre.openid.connect.service.NonceService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
public class DefaultNonceService implements NonceService {
|
public class DefaultNonceService implements NonceService {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(NonceService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
NonceRepository repository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Nonce getById(Long id) {
|
public Nonce getById(Long id) {
|
||||||
// TODO Auto-generated method stub
|
return repository.getById(id);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(Nonce nonce) {
|
public void remove(Nonce nonce) {
|
||||||
// TODO Auto-generated method stub
|
repository.remove(nonce);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Nonce save(Nonce nonce) {
|
public Nonce save(Nonce nonce) {
|
||||||
// TODO Auto-generated method stub
|
return repository.save(nonce);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Nonce> getAll() {
|
public Collection<Nonce> getAll() {
|
||||||
// TODO Auto-generated method stub
|
return repository.getAll();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Nonce> getExpired() {
|
public Collection<Nonce> getExpired() {
|
||||||
// TODO Auto-generated method stub
|
return repository.getExpired();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Nonce> getByClientId(String clientId) {
|
public Collection<Nonce> getByClientId(String clientId) {
|
||||||
// TODO Auto-generated method stub
|
return repository.getByClientId(clientId);
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Scheduled(fixedRate = 5 * 60 * 1000) // schedule this task every five minutes
|
||||||
|
public void clearExpiredNonces() {
|
||||||
|
|
||||||
|
logger.info("Clearing expired nonces");
|
||||||
|
|
||||||
|
Collection<Nonce> expired = repository.getExpired();
|
||||||
|
logger.info("Found " + expired.size() + " expired nonces");
|
||||||
|
|
||||||
|
for (Nonce nonce : expired) {
|
||||||
|
remove(nonce);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue