diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/NonceService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/NonceService.java index 07a6332b4..093fd2063 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/NonceService.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/NonceService.java @@ -14,7 +14,25 @@ import org.mitre.openid.connect.model.Nonce; */ 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 * diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/NonceReuseException.java b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/NonceReuseException.java index abe02aaa4..619271b0e 100644 --- a/openid-connect-server/src/main/java/org/mitre/oauth2/exception/NonceReuseException.java +++ b/openid-connect-server/src/main/java/org/mitre/oauth2/exception/NonceReuseException.java @@ -1,14 +1,13 @@ package org.mitre.oauth2.exception; -import org.mitre.openid.connect.model.Nonce; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; public class NonceReuseException extends OAuth2Exception { private static final long serialVersionUID = 1L; - public NonceReuseException(String clientId, Nonce alreadyUsed) { - super("Client " + clientId + " attempted to use reuse nonce " + alreadyUsed.getValue()); + public NonceReuseException(String clientId, String nonce) { + super("Client " + clientId + " attempted to use reuse nonce " + nonce); } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/ConnectAuthorizationRequestManager.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/ConnectAuthorizationRequestManager.java index a9a4d426f..ecc12d3e3 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/ConnectAuthorizationRequestManager.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/ConnectAuthorizationRequestManager.java @@ -1,17 +1,13 @@ package org.mitre.openid.connect; import java.text.ParseException; -import java.util.Collection; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import net.minidev.json.JSONObject; -import org.joda.time.DateTime; -import org.joda.time.Period; import org.mitre.jwt.signer.service.JwtSigningAndValidationService; import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService; import org.mitre.oauth2.exception.NonceReuseException; @@ -21,11 +17,10 @@ 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.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationServiceException; -import org.springframework.security.core.Authentication; 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.exceptions.InvalidScopeException; import org.springframework.security.oauth2.common.util.OAuth2Utils; @@ -40,7 +35,7 @@ import com.nimbusds.jose.util.JSONObjectUtils; import com.nimbusds.jwt.SignedJWT; @Component("authorizationRequestManager") -public class ConnectAuthorizationRequestManager implements AuthorizationRequestManager, InitializingBean { +public class ConnectAuthorizationRequestManager implements AuthorizationRequestManager { private static Logger logger = LoggerFactory.getLogger(ConnectAuthorizationRequestManager.class); @@ -52,8 +47,6 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM @Autowired private JWKSetSigningAndValidationServiceCacheService validators; - - private Period nonceStorageDuration; /** * Constructor with arguments @@ -72,15 +65,6 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM public ConnectAuthorizationRequestManager() { } - - /** - * Make sure that the nonce storage duration was set - */ - public void afterPropertiesSet() throws Exception { - if (nonceStorageDuration == null) { - logger.error("Nonce storage duration must be set!"); - } - } @Override public AuthorizationRequest createAuthorizationRequest(Map inputParams) { @@ -100,28 +84,15 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM //to the auth endpoint. Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - if (requestNonce != null && principal != null && principal instanceof Authentication) { + if (requestNonce != null && principal != null && principal instanceof User) { - //Check request nonce for reuse - Collection clientNonces = nonceService.getByClientId(client.getClientId()); - for (Nonce nonce : clientNonces) { - String nonceVal = nonce.getValue(); - if (nonceVal.equals(requestNonce)) { - throw new NonceReuseException(client.getClientId(), nonce); - } + if (!nonceService.alreadyUsed(clientId, requestNonce)) { + Nonce nonce = nonceService.create(clientId, requestNonce); + nonceService.save(nonce); + } + else { + throw new NonceReuseException(client.getClientId(), requestNonce); } - - //Store nonce - Nonce nonce = new Nonce(); - nonce.setClientId(client.getClientId()); - nonce.setValue(requestNonce); - DateTime now = new DateTime(new Date()); - nonce.setUseDate(now.toDate()); - DateTime expDate = now.plus(nonceStorageDuration); - Date expirationJdkDate = expDate.toDate(); - nonce.setExpireDate(expirationJdkDate); - - nonceService.save(nonce); } @@ -263,20 +234,5 @@ public class ConnectAuthorizationRequestManager implements AuthorizationRequestM } } } - - /** - * @return the nonceStorageDuration - */ - public Period getNonceStorageDuration() { - return nonceStorageDuration; - } - - /** - * @param nonceStorageDuration the nonceStorageDuration to set - */ - public void setNonceStorageDuration(Period nonceStorageDuration) { - this.nonceStorageDuration = nonceStorageDuration; - } - } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultNonceService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultNonceService.java index 4e75e0e61..b29d54082 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultNonceService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultNonceService.java @@ -1,23 +1,67 @@ package org.mitre.openid.connect.service.impl; import java.util.Collection; +import java.util.Date; +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.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @Service("defaultNonceService") -public class DefaultNonceService implements NonceService { +public class DefaultNonceService implements NonceService, InitializingBean { private static Logger logger = LoggerFactory.getLogger(NonceService.class); @Autowired - NonceRepository repository; + private NonceRepository repository; + + @Autowired + private Period nonceStorageDuration; + + /** + * Make sure that the nonce storage duration was set + */ + public void afterPropertiesSet() throws Exception { + if (nonceStorageDuration == null) { + logger.error("Nonce storage duration must be set!"); + } + } + + @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 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) { @@ -63,4 +107,21 @@ public class DefaultNonceService implements NonceService { } } + 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; + } + + } diff --git a/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml b/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml index b7a4052cb..621ae6ec9 100644 --- a/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml +++ b/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml @@ -145,9 +145,7 @@ - - - +