Added a ConfigurationPropertiesBean.java to hold configuration properties. Fixed up CheckIDEndpoint.java a bit - it works, but is outputting the wrong thing.

pull/59/head
Amanda Anganes 2012-03-22 13:43:30 -04:00
parent c59d3fe963
commit ae9b5e792a
10 changed files with 186 additions and 38 deletions

View File

@ -1,18 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/> <classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>
<attribute name="org.eclipse.jst.component.nondependency" value=""/> <attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="owner.project.facets" value="java"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View File

@ -33,9 +33,13 @@ public abstract class AbstractJwtSigner implements JwtSigner {
/** /**
* Ensures that the 'alg' of the given JWT matches the {@link #algorithm} of this signer * Ensures that the 'alg' of the given JWT matches the {@link #algorithm} of this signer
* and signs the jwt.
*
* @param jwt the jwt to sign
* @return the signed jwt
*/ */
@Override @Override
public void sign(Jwt jwt) { public Jwt sign(Jwt jwt) {
if (!Objects.equal(algorithm, jwt.getHeader().getAlgorithm())) { if (!Objects.equal(algorithm, jwt.getHeader().getAlgorithm())) {
// algorithm type doesn't match // algorithm type doesn't match
// TODO: should this be an error or should we just fix it in the incoming jwt? // TODO: should this be an error or should we just fix it in the incoming jwt?
@ -46,6 +50,8 @@ public abstract class AbstractJwtSigner implements JwtSigner {
String sig = generateSignature(jwt.getSignatureBase()); String sig = generateSignature(jwt.getSignatureBase());
jwt.setSignature(sig); jwt.setSignature(sig);
return jwt;
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@ -4,7 +4,7 @@ import org.mitre.jwt.model.Jwt;
public interface JwtSigner { public interface JwtSigner {
public void sign(Jwt jwt); public Jwt sign(Jwt jwt);
public boolean verify(String jwtString); public boolean verify(String jwtString);

View File

@ -45,4 +45,28 @@ public interface JwtSigningAndValidationService {
* @return true if the signature is valid, false if not * @return true if the signature is valid, false if not
*/ */
public boolean validateSignature(String jwtString); public boolean validateSignature(String jwtString);
/**
* Called to sign a jwt for a client that hasn't registered a preferred signing algorithm.
* Use the default algorithm to sign.
*
* @param jwt the jwt to sign
* @return the signed jwt
*/
public Jwt signJwt(Jwt jwt);
/**
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
* in the JWT spec, section 6. I.E., "HS256" means HMAC with SHA-256 and corresponds to our HmacSigner class.
*
* @param jwt the jwt to sign
* @param alg the name of the algorithm to use, as specified in JWS s.6
* @return the signed jwt
*/
//TODO: implement later; only need signJwt(Jwt jwt) for now
//public Jwt signJwt(Jwt jwt, String alg);
/**
* TODO: method to sign a jwt using a specified algorithm and a key id
*/
} }

View File

@ -15,11 +15,15 @@ import org.mitre.jwt.signer.JwtSigner;
import org.mitre.jwt.signer.impl.EcdsaSigner; import org.mitre.jwt.signer.impl.EcdsaSigner;
import org.mitre.jwt.signer.impl.RsaSigner; import org.mitre.jwt.signer.impl.RsaSigner;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService; import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
public class JwtSigningAndValidationServiceDefault implements public class JwtSigningAndValidationServiceDefault implements
JwtSigningAndValidationService, InitializingBean { JwtSigningAndValidationService, InitializingBean {
@Autowired
private ConfigurationPropertiesBean configBean;
private List<? extends JwtSigner> signers = new ArrayList<JwtSigner>(); private List<? extends JwtSigner> signers = new ArrayList<JwtSigner>();
@ -153,7 +157,9 @@ public class JwtSigningAndValidationServiceDefault implements
@Override @Override
public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer) { public boolean validateIssuedJwt(Jwt jwt, String expectedIssuer) {
if (jwt.getClaims().getIssuer() == expectedIssuer) String iss = jwt.getClaims().getIssuer();
if (iss.equals(expectedIssuer))
return true; return true;
return false; return false;
@ -176,4 +182,29 @@ public class JwtSigningAndValidationServiceDefault implements
return false; return false;
} }
@Override
public Jwt signJwt(Jwt jwt) {
String signerId = configBean.getDefaultJwtSigner();
//JwtSigner signer = map.get(signerId);
//signer.sign(jwt);
return null;
}
/**
* @return the configBean
*/
public ConfigurationPropertiesBean getConfigBean() {
return configBean;
}
/**
* @param configBean the configBean to set
*/
public void setConfigBean(ConfigurationPropertiesBean configBean) {
this.configBean = configBean;
}
} }

View File

@ -0,0 +1,45 @@
package org.mitre.openid.connect.config;
/**
* Bean to hold configuration information that must be injected into various parts
* of our application. Set all of the properties here, and autowire a reference
* to this bean if you need access to any configuration properties.
*
* @author AANGANES
*
*/
public class ConfigurationPropertiesBean {
private String issuer;
private String defaultJwtSigner;
public ConfigurationPropertiesBean() {
}
/**
* @return the defaultJwtSigner
*/
public String getDefaultJwtSigner() {
return defaultJwtSigner;
}
public void setDefaultJwtSigner(String signer) {
defaultJwtSigner = signer;
}
/**
* @return the baseUrl
*/
public String getIssuer() {
return issuer;
}
/**
* @param iss the issuer to set
*/
public void setIssuer(String iss) {
issuer = iss;
}
}

View File

@ -7,9 +7,11 @@ import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.oauth2.model.OAuth2AccessTokenEntity; import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
import org.mitre.oauth2.service.OAuth2TokenEntityService; import org.mitre.oauth2.service.OAuth2TokenEntityService;
import org.mitre.oauth2.service.impl.DefaultOAuth2ProviderTokenService; import org.mitre.oauth2.service.impl.DefaultOAuth2ProviderTokenService;
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
import org.mitre.openid.connect.model.IdToken; import org.mitre.openid.connect.model.IdToken;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -48,7 +50,8 @@ public class ConnectAuthCodeTokenGranter implements TokenGranter {
@Autowired @Autowired
private ClientCredentialsChecker clientCredentialsChecker; private ClientCredentialsChecker clientCredentialsChecker;
private String issuer; @Autowired
private ConfigurationPropertiesBean configBean;
//TODO: Do we need to modify/update this? //TODO: Do we need to modify/update this?
@Autowired @Autowired
@ -57,6 +60,9 @@ public class ConnectAuthCodeTokenGranter implements TokenGranter {
@Autowired @Autowired
private IdTokenGeneratorService idTokenService; private IdTokenGeneratorService idTokenService;
@Autowired
private JwtSigningAndValidationService jwtService;
/** /**
* Default empty constructor * Default empty constructor
*/ */
@ -141,7 +147,7 @@ public class ConnectAuthCodeTokenGranter implements TokenGranter {
//TODO: need to get base url, but Utility.findBaseUrl() needs access to a request object, which we don't have //TODO: need to get base url, but Utility.findBaseUrl() needs access to a request object, which we don't have
//See github issue #1 //See github issue #1
token.getJwt().getClaims().setIssuer(issuer); token.getJwt().getClaims().setIssuer(configBean.getIssuer());
token.getJwt().getClaims().setIssuedAt(new Date()); token.getJwt().getClaims().setIssuedAt(new Date());
// handle expiration // handle expiration
@ -156,13 +162,19 @@ public class ConnectAuthCodeTokenGranter implements TokenGranter {
String userId = userAuth.getName(); String userId = userAuth.getName();
//TODO: need to get base url, but Utility.findBaseUrl() needs access to a request object, which we don't have IdToken idToken = idTokenService.generateIdToken(userId, configBean.getIssuer());
//See github issue #1
IdToken idToken = idTokenService.generateIdToken(userId, issuer);
idToken.getClaims().setAudience(clientId); idToken.getClaims().setAudience(clientId);
idToken.getClaims().setIssuedAt(new Date()); idToken.getClaims().setIssuedAt(new Date());
idToken.getClaims().setIssuer(configBean.getIssuer());
// TODO: expiration? other fields? // TODO: expiration? other fields?
//Sign
//TODO: check client to see if they have a preferred alg, attempt to use that
//TODO: uncomment line below once RsaSigner bean has been set up and added to the configBean
//idToken = (IdToken) jwtService.signJwt(idToken);
token.setIdToken(idToken); token.setIdToken(idToken);
} }
@ -207,18 +219,28 @@ public class ConnectAuthCodeTokenGranter implements TokenGranter {
this.tokenServices = tokenServices; this.tokenServices = tokenServices;
} }
/** public ConfigurationPropertiesBean getConfigBean() {
* @return the issuer return configBean;
*/
public String getIssuer() {
return issuer;
} }
/** public void setConfigBean(ConfigurationPropertiesBean configBean) {
* @param issuer the issuer to set this.configBean = configBean;
*/ }
public void setIssuer(String issuer) {
this.issuer = issuer; public IdTokenGeneratorService getIdTokenService() {
return idTokenService;
}
public void setIdTokenService(IdTokenGeneratorService idTokenService) {
this.idTokenService = idTokenService;
}
public JwtSigningAndValidationService getJwtService() {
return jwtService;
}
public void setJwtService(JwtSigningAndValidationService jwtService) {
this.jwtService = jwtService;
} }
} }

View File

@ -3,6 +3,7 @@ package org.mitre.openid.connect.web;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService; import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
import org.mitre.openid.connect.exception.ExpiredTokenException; import org.mitre.openid.connect.exception.ExpiredTokenException;
import org.mitre.openid.connect.exception.InvalidJwtIssuerException; import org.mitre.openid.connect.exception.InvalidJwtIssuerException;
import org.mitre.openid.connect.exception.InvalidJwtSignatureException; import org.mitre.openid.connect.exception.InvalidJwtSignatureException;
@ -20,6 +21,9 @@ public class CheckIDEndpoint {
@Autowired @Autowired
JwtSigningAndValidationService jwtSignerService; JwtSigningAndValidationService jwtSignerService;
@Autowired
private ConfigurationPropertiesBean configBean;
@RequestMapping("/checkid") @RequestMapping("/checkid")
public ModelAndView checkID(@RequestParam("id_token") String tokenString, ModelAndView mav, HttpServletRequest request) { public ModelAndView checkID(@RequestParam("id_token") String tokenString, ModelAndView mav, HttpServletRequest request) {
@ -38,11 +42,27 @@ public class CheckIDEndpoint {
} }
// check the issuer (sanity check) // check the issuer (sanity check)
if (!jwtSignerService.validateIssuedJwt(token, Utility.findBaseUrl(request))) { if (!jwtSignerService.validateIssuedJwt(token, configBean.getIssuer())) {
throw new InvalidJwtIssuerException(); // TODO: create a view for this exception throw new InvalidJwtIssuerException(); // TODO: create a view for this exception
} }
return new ModelAndView("jsonIdTokenView", "checkId", token); // TODO: create a view for this return new ModelAndView("jsonIdTokenView", "checkId", token); // TODO: create a view for this
} }
public JwtSigningAndValidationService getJwtSignerService() {
return jwtSignerService;
}
public void setJwtSignerService(JwtSigningAndValidationService jwtSignerService) {
this.jwtSignerService = jwtSignerService;
}
public ConfigurationPropertiesBean getConfigBean() {
return configBean;
}
public void setConfigBean(ConfigurationPropertiesBean configBean) {
this.configBean = configBean;
}
} }

View File

@ -41,8 +41,8 @@
<beans:bean id="jsonSwdResponseView" class="org.mitre.swd.view.SwdResponse" /> <beans:bean id="jsonSwdResponseView" class="org.mitre.swd.view.SwdResponse" />
<beans:bean id="jwkKeyList" class="org.mitre.openid.connect.view.JwkKeyListView" /> <beans:bean id="jwkKeyList" class="org.mitre.openid.connect.view.JwkKeyListView" />
<!-- <beans:bean id="jsonUserInfoView" class="org.mitre.openid.connect.view.JSONUserInfoView"/> --> <beans:bean id="jsonUserInfoView" class="org.mitre.openid.connect.view.JSONUserInfoView"/>
<!-- <beans:bean id="jsonIdTokenView" class="org.mitre.openid.connect.view.JSONIdTokenView"/> --> <beans:bean id="jsonIdTokenView" class="org.mitre.openid.connect.view.JSONIdTokenView"/>
<beans:import resource="controllers.xml" /> <beans:import resource="controllers.xml" />
@ -53,8 +53,5 @@
<oauth:authorization-code authorization-code-services-ref="authCodeServices"/> <oauth:authorization-code authorization-code-services-ref="authCodeServices"/>
</oauth:authorization-server> </oauth:authorization-server>
<beans:bean id="connectAuthCodeTokenGranter" class="org.mitre.openid.connect.token.ConnectAuthCodeTokenGranter">
<beans:property name="issuer" value="http://localhost/" />
</beans:bean>
</beans:beans> </beans:beans>

View File

@ -81,6 +81,16 @@
<property name="showSql" value="true" /> <property name="showSql" value="true" />
</bean> </bean>
<!-- TODO: get signer set up -->
<!-- <bean id="rsaSigner1" class="org.mitre.jwt.signer.impl.RsaSigner"/> -->
<bean id="configBean" class="org.mitre.openid.connect.config.ConfigurationPropertiesBean">
<property name="issuer" value="http://localhost/" />
<!-- TODO: plug in default signer -->
<!-- <property name="defaultJwtSigner" value="rsaSigner1"/> -->
</bean>
<!-- Map our custom exception classes to named views --> <!-- Map our custom exception classes to named views -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings"> <property name="exceptionMappings">