Removed nonce service

pull/477/head
Amanda Anganes 2013-08-02 10:56:28 -04:00
parent d4fbb4f599
commit 2f711c88a7
8 changed files with 1 additions and 697 deletions

View File

@ -1,139 +0,0 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.model;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
@Entity
@Table(name="client_nonce")
@NamedQueries({
@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.getExpired", query = "select n from Nonce n where n.expireDate is not null and n.expireDate < current_timestamp")
})
public class 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 Date useDate; //the date this Nonce was used
private Date expireDate; //the date after which this Nonce should be removed from the database
/**
* @return the id
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long 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
*/
@Basic
@Column(name="client_id")
public String getClientId() {
return clientId;
}
/**
* @param clientId the clientId to set
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return the useDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="use_date")
public Date getUseDate() {
return useDate;
}
/**
* @param useDate the useDate to set
*/
public void setUseDate(Date useDate) {
this.useDate = useDate;
}
/**
* @return the expireDate
*/
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name="expire_date")
public Date getExpireDate() {
return expireDate;
}
/**
* @param expireDate the expireDate to set
*/
public void setExpireDate(Date expireDate) {
this.expireDate = expireDate;
}
}

View File

@ -1,77 +0,0 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.repository;
import java.util.Collection;
import org.mitre.openid.connect.model.Nonce;
/**
*
* Nonce repository interface.
*
* @author Amanda Anganes
*
*/
public interface NonceRepository {
/**
* Return the nonce with the given ID
*
* @param id the ID of the nonce to find
* @return the nonce, if found
*/
public Nonce getById(Long id);
/**
* Remove the given Nonce from the database
*
* @param nonce the Nonce to remove
*/
public void remove(Nonce nonce);
/**
* Save a new Nonce in the database
*
* @param nonce the Nonce to save
* @return the saved Nonce
*/
public Nonce save(Nonce nonce);
/**
* Return all nonces stored in the database
*
* @return the set of nonces
*/
public Collection<Nonce> getAll();
/**
* Return all expired nonces stored in the database
*
* @return the set of expired nonces
*/
public Collection<Nonce> getExpired();
/**
* Return the set of nonces registered to the given client ID
*
* @param clientId the client ID
* @return the set of nonces registered to the client
*/
public Collection<Nonce> getByClientId(String clientId);
}

View File

@ -1,102 +0,0 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.service;
import java.util.Collection;
import org.mitre.openid.connect.model.Nonce;
/**
*
* Nonce service interface
*
* @author Amanda Anganes
*
*/
public interface NonceService {
/**
* Create a new nonce.
*
* @param clientId the ID of the client
* @param value the value of the Nonce
* @return the saved Nonce
*/
public Nonce create(String clientId, String value);
/**
* Check whether a given nonce value has been previously used and stored
* by the client.
*
* @param clientId the ID of the client
* @param value the value of the nonce
* @return true if the nonce has already been used, false otherwise
*/
public boolean alreadyUsed(String clientId, String value);
/**
* Return the nonce with the given ID
*
* @param id the ID of the nonce to find
* @return the nonce, if found
*/
public Nonce getById(Long id);
/**
* Remove the given Nonce from the database
*
* @param nonce the Nonce to remove
*/
public void remove(Nonce nonce);
/**
* Save a new Nonce in the database
*
* @param nonce the Nonce to save
* @return the saved Nonce
*/
public Nonce save(Nonce nonce);
/**
* Return all nonces stored in the database
*
* @return the set of nonces
*/
public Collection<Nonce> getAll();
/**
* Return all expired nonces stored in the database
*
* @return the set of expired nonces
*/
public Collection<Nonce> getExpired();
/**
* Return the set of nonces registered to the given client ID
*
* @param clientId the client ID
* @return the set of nonces registered to the client
*/
public Collection<Nonce> getByClientId(String clientId);
/**
* Clear expired nonces from the database
*/
void clearExpiredNonces();
}

View File

@ -26,17 +26,12 @@ import net.minidev.json.JSONObject;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService;
import org.mitre.oauth2.exception.NonceReuseException;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.service.ClientDetailsEntityService;
import org.mitre.openid.connect.model.Nonce;
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.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
@ -53,8 +48,6 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory {
private static Logger logger = LoggerFactory.getLogger(ConnectOAuth2RequestFactory.class);
private NonceService nonceService;
private ClientDetailsEntityService clientDetailsService;
@Autowired
@ -67,10 +60,9 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory {
* @param nonceService
*/
@Autowired
public ConnectOAuth2RequestFactory(ClientDetailsEntityService clientDetailsService, NonceService nonceService) {
public ConnectOAuth2RequestFactory(ClientDetailsEntityService clientDetailsService) {
super(clientDetailsService);
this.clientDetailsService = clientDetailsService;
this.nonceService = nonceService;
}
@Override
@ -85,8 +77,6 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory {
client = clientDetailsService.loadClientByClientId(clientId);
}
String requestNonce = parameters.get("nonce");
AuthorizationRequest request = new AuthorizationRequest(parameters, Collections.<String, String> emptyMap(),
parameters.get(OAuth2Utils.CLIENT_ID),
OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)), null,
@ -94,23 +84,6 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory {
parameters.get(OAuth2Utils.REDIRECT_URI),
OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.RESPONSE_TYPE)));
//Only process if the user is authenticated. If the user is not authenticated yet, this
//code will be called a second time once the user is redirected from the login page back
//to the auth endpoint.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (requestNonce != null && principal != null && principal instanceof User) {
if (!nonceService.alreadyUsed(clientId, requestNonce)) {
Nonce nonce = nonceService.create(clientId, requestNonce);
nonceService.save(nonce);
}
else {
throw new NonceReuseException(client == null ? "unidentified client" : client.getClientId(), requestNonce);
}
}
Set<String> scopes = OAuth2Utils.parseParameterList(parameters.get("scope"));
if ((scopes == null || scopes.isEmpty()) && client != null) {
Set<String> clientScopes = client.getScope();

View File

@ -1,87 +0,0 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.repository.impl;
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.repository.NonceRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
@Repository
public class JpaNonceRepository implements NonceRepository {
@PersistenceContext
private EntityManager manager;
@Override
@Transactional
public Nonce getById(Long id) {
return manager.find(Nonce.class, id);
}
@Override
@Transactional
public void remove(Nonce nonce) {
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
@Transactional
public Nonce save(Nonce nonce) {
return saveOrUpdate(nonce.getId(), manager, nonce);
}
@Override
@Transactional
public Collection<Nonce> getAll() {
TypedQuery<Nonce> query = manager.createNamedQuery("Nonce.getAll", Nonce.class);
return query.getResultList();
}
@Override
@Transactional
public Collection<Nonce> getExpired() {
TypedQuery<Nonce> query = manager.createNamedQuery("Nonce.getExpired", Nonce.class);
return query.getResultList();
}
@Override
@Transactional
public Collection<Nonce> getByClientId(String clientId) {
TypedQuery<Nonce> query = manager.createNamedQuery("Nonce.getByClientId", Nonce.class);
query.setParameter("clientId", clientId);
return query.getResultList();
}
}

View File

@ -1,147 +0,0 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.service.impl;
import java.util.Collection;
import java.util.Date;
import javax.annotation.PostConstruct;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.mitre.openid.connect.model.Nonce;
import org.mitre.openid.connect.repository.NonceRepository;
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.stereotype.Service;
@Service("defaultNonceService")
public class DefaultNonceService implements NonceService {
private static Logger logger = LoggerFactory.getLogger(NonceService.class);
@Autowired
private NonceRepository repository;
@Autowired
private Period nonceStorageDuration;
/**
* Make sure that the nonce storage duration was set
*/
@PostConstruct
public void afterPropertiesSet() throws Exception {
if (nonceStorageDuration == null) {
logger.error("Nonce storage duration must be set!");
}
logger.info("Nonce Service ready to go");
}
@Override
public Nonce create(String clientId, String value) {
//Store nonce
Nonce nonce = new Nonce();
nonce.setClientId(clientId);
nonce.setValue(value);
DateTime now = new DateTime(new Date());
nonce.setUseDate(now.toDate());
DateTime expDate = now.plus(nonceStorageDuration);
Date expirationJdkDate = expDate.toDate();
nonce.setExpireDate(expirationJdkDate);
return nonce;
}
@Override
public boolean alreadyUsed(String clientId, String value) {
Collection<Nonce> clientNonces = getByClientId(clientId);
for (Nonce nonce : clientNonces) {
String nonceVal = nonce.getValue();
if (nonceVal.equals(value)) {
return true;
}
}
return false;
}
@Override
public Nonce getById(Long id) {
return repository.getById(id);
}
@Override
public void remove(Nonce nonce) {
repository.remove(nonce);
}
@Override
public Nonce save(Nonce nonce) {
return repository.save(nonce);
}
@Override
public Collection<Nonce> getAll() {
return repository.getAll();
}
@Override
public Collection<Nonce> getExpired() {
return repository.getExpired();
}
@Override
public Collection<Nonce> getByClientId(String clientId) {
return repository.getByClientId(clientId);
}
@Override
//We are eventually deleting this class, but if we weren't,
//this would have been moved to application-context.xml for easier configuration.
//@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);
}
}
public NonceRepository getRepository() {
return repository;
}
public void setRepository(NonceRepository repository) {
this.repository = repository;
}
public Period getNonceStorageDuration() {
return nonceStorageDuration;
}
public void setNonceStorageDuration(Period nonceStorageDuration) {
this.nonceStorageDuration = nonceStorageDuration;
}
}

View File

@ -156,14 +156,6 @@
<property name="filterProcessesUrl" value="/revoke"/>
</bean>
<!-- A JodaTime Period for the nonce storage duration. Constructor takes (hours, minutes, seconds, milliseconds). -->
<bean id="nonceStorageDurationPeriod" class="org.joda.time.Period">
<constructor-arg type="int" index="0" value="24"/>
<constructor-arg type="int" index="1" value="0"/>
<constructor-arg type="int" index="2" value="0"/>
<constructor-arg type="int" index="3" value="0"/>
</bean>
<bean id="clientAssertiontokenEndpointFilter" class="org.mitre.openid.connect.assertion.JwtBearerClientAssertionTokenEndpointFilter">
<property name="authenticationManager" ref="clientAssertionAuthenticationManager" />
<property name="filterProcessesUrl" value="/token" />

View File

@ -1,109 +0,0 @@
/*******************************************************************************
* Copyright 2013 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.mitre.openid.connect.service.impl;
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mitre.openid.connect.model.Nonce;
import org.mitre.openid.connect.repository.NonceRepository;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import com.google.common.collect.Sets;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author wkim
*
*/
@RunWith(MockitoJUnitRunner.class)
public class TestDefaultNonceService {
// Test value for nonce storage duration time.
private Period nonceStorageDuration = new Period().withSeconds(1);
private String clientId = "123abc";
private String value1 = "n1";
private String value2 = "n2";
private String value3 = "n3";
@Mock
private NonceRepository repository;
@InjectMocks
private DefaultNonceService service = new DefaultNonceService();
@Before
public void prepare() {
Mockito.reset(repository);
service.setNonceStorageDuration(nonceStorageDuration);
}
/**
* Tests the correctness of created nonces.
*/
@Test
public void create() {
Date start = new Date(System.currentTimeMillis() - 100); // time skew of 100ms on either side
Nonce nonce = service.create(clientId, value1);
Date end = new Date(System.currentTimeMillis() + 100); // time skew of 100ms on either side
assertEquals(clientId, nonce.getClientId());
assertEquals(value1, nonce.getValue());
assertTrue(nonce.getUseDate().after(start) && nonce.getUseDate().before(end)); // make sure the date is within the right range (within 100ms on either side)
// Check expiration date.
assertEquals(new DateTime(nonce.getUseDate()).plus(nonceStorageDuration), new DateTime(nonce.getExpireDate()));
}
/**
* Verifies that if any nonce returned by the repository already has the value being checked for,
* then the service method returns true.
*
* Also checks a nonce value not returned by the repository to verify the method returns false in this case.
*/
@Test
public void alreadyUsed() {
Nonce nonce1 = service.create(clientId, value1);
Nonce nonce2 = service.create(clientId, value2);
Mockito.when(repository.getByClientId(clientId)).thenReturn(Sets.newHashSet(nonce1, nonce2));
assertTrue(service.alreadyUsed(clientId, value1));
assertTrue(service.alreadyUsed(clientId, value2));
assertFalse(service.alreadyUsed(clientId, value3));
}
}