diff --git a/server/src/main/java/org/mitre/jwt/service/JwtSigningAndValidationService.java b/server/src/main/java/org/mitre/jwt/service/JwtSigningAndValidationService.java new file mode 100644 index 000000000..969cb6831 --- /dev/null +++ b/server/src/main/java/org/mitre/jwt/service/JwtSigningAndValidationService.java @@ -0,0 +1,37 @@ +package org.mitre.jwt.service; + +import java.security.PublicKey; +import java.util.List; + +import org.mitre.jwt.model.Jwt; + +public interface JwtSigningAndValidationService { + + /** + * Returns all public keys this service is configured with. + * @return + */ + public List getAllPublicKeys(); + + /** + * Checks the signature of the given JWT against all configured signers, returns true if at least one of the signers validates it. + * @param jwtString the string representation of the JWT as sent on the wire + * @return true if the signature is valid, false if not + */ + public boolean validateSignature(String jwtString); + + /** + * Checks to see if this JWT has been issued by us + * @param jwt the JWT to check the issuer of + * @return true if the JWT was issued by this AS, false if not + */ + public boolean validateIssuedJwt(Jwt jwt); + + + /** + * Check to see if this JWT has expired or not + * @param jwt the JWT to check + * @return true if this JWT has an expiration and it has passed, false if the JWT has no expiration or it has an expiration and the expiration has not passed + */ + public boolean isJwtExpired(Jwt jwt); +} diff --git a/server/src/main/java/org/mitre/openid/connect/exception/ExpiredTokenException.java b/server/src/main/java/org/mitre/openid/connect/exception/ExpiredTokenException.java new file mode 100644 index 000000000..8e1bc075d --- /dev/null +++ b/server/src/main/java/org/mitre/openid/connect/exception/ExpiredTokenException.java @@ -0,0 +1,5 @@ +package org.mitre.openid.connect.exception; + +public class ExpiredTokenException extends RuntimeException { + +} diff --git a/server/src/main/java/org/mitre/openid/connect/exception/InvalidJwtIssuerException.java b/server/src/main/java/org/mitre/openid/connect/exception/InvalidJwtIssuerException.java new file mode 100644 index 000000000..b7b625bb1 --- /dev/null +++ b/server/src/main/java/org/mitre/openid/connect/exception/InvalidJwtIssuerException.java @@ -0,0 +1,5 @@ +package org.mitre.openid.connect.exception; + +public class InvalidJwtIssuerException extends RuntimeException { + +} diff --git a/server/src/main/java/org/mitre/openid/connect/exception/InvalidJwtSignatureException.java b/server/src/main/java/org/mitre/openid/connect/exception/InvalidJwtSignatureException.java new file mode 100644 index 000000000..4b613bf6d --- /dev/null +++ b/server/src/main/java/org/mitre/openid/connect/exception/InvalidJwtSignatureException.java @@ -0,0 +1,5 @@ +package org.mitre.openid.connect.exception; + +public class InvalidJwtSignatureException extends RuntimeException { + +} diff --git a/server/src/main/java/org/mitre/openid/connect/exception/empty.txt b/server/src/main/java/org/mitre/openid/connect/exception/empty.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java b/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java index 3e778add3..c5b87ab50 100644 --- a/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java +++ b/server/src/main/java/org/mitre/openid/connect/web/CheckIDEndpoint.java @@ -1,7 +1,12 @@ package org.mitre.openid.connect.web; +import org.mitre.jwt.service.JwtSigningAndValidationService; +import org.mitre.openid.connect.exception.ExpiredTokenException; +import org.mitre.openid.connect.exception.InvalidJwtIssuerException; +import org.mitre.openid.connect.exception.InvalidJwtSignatureException; import org.mitre.openid.connect.model.IdToken; import org.mitre.openid.connect.model.IdTokenClaims; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -10,17 +15,33 @@ import org.springframework.web.servlet.ModelAndView; @Controller public class CheckIDEndpoint { + @Autowired + JwtSigningAndValidationService jwtSignerService; @RequestMapping("/checkid") public ModelAndView checkID(@RequestParam("id_token") String tokenString, ModelAndView mav) { + if (!jwtSignerService.validateSignature(tokenString)) { + // can't validate + throw new InvalidJwtSignatureException(); // TODO: attach a view to this exception + } + + // it's a valid signature, parse the token IdToken token = IdToken.parse(tokenString); + // check the expiration + if (jwtSignerService.isJwtExpired(token)) { + // token has expired + throw new ExpiredTokenException(); // TODO create a view for this exception + } + // check the issuer (sanity check) + if (!jwtSignerService.validateIssuedJwt(token)) { + throw new InvalidJwtIssuerException(); // TODO: create a view for this exception + } - - return new ModelAndView("jsonIdTokenView", "checkId", token); + return new ModelAndView("jsonIdTokenView", "checkId", token); // TODO: create a view for this } } diff --git a/server/src/main/java/org/mitre/openid/connect/web/JsonWebKeyEndpoint.java b/server/src/main/java/org/mitre/openid/connect/web/JsonWebKeyEndpoint.java new file mode 100644 index 000000000..838f4fed4 --- /dev/null +++ b/server/src/main/java/org/mitre/openid/connect/web/JsonWebKeyEndpoint.java @@ -0,0 +1,28 @@ +package org.mitre.openid.connect.web; + +import java.security.PublicKey; +import java.util.List; + +import org.mitre.jwt.service.JwtSigningAndValidationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class JsonWebKeyEndpoint { + + @Autowired + JwtSigningAndValidationService jwtService; + + @RequestMapping("/jwk") + public ModelAndView getJwk() { + + List keys = jwtService.getAllPublicKeys(); + + // TODO: check if keys are empty, return a 404 here? + + return new ModelAndView("jwkView", "keys", keys); // TODO: make a view + } + +}