Merge pull request #137 from patriot1burke/master
factor out jwt/jose/jws
This commit is contained in:
commit
6fe9a03997
70 changed files with 3243 additions and 378 deletions
71
core-jaxrs/pom.xml
Executable file
71
core-jaxrs/pom.xml
Executable file
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0"?>
|
||||
<project>
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-alpha-1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<name>Keycloak Core JAX-RS</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jackson-provider</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -66,7 +66,7 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter {
|
|||
|
||||
|
||||
try {
|
||||
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
|
||||
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm());
|
||||
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, token, resourceMetadata);
|
||||
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
|
||||
String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null;
|
17
core/pom.xml
17
core/pom.xml
|
@ -14,23 +14,18 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.keycloak;
|
||||
|
||||
import org.jboss.resteasy.util.Base64;
|
||||
|
||||
import org.keycloak.util.Base64;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package org.keycloak;
|
||||
|
||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -13,11 +12,6 @@ import java.security.PublicKey;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RSATokenVerifier {
|
||||
public static SkeletonKeyToken verifyToken(String tokenString, ResourceMetadata metadata) throws VerificationException {
|
||||
PublicKey realmKey = metadata.getRealmKey();
|
||||
String realm = metadata.getRealm();
|
||||
return verifyToken(tokenString, realmKey, realm);
|
||||
}
|
||||
|
||||
public static SkeletonKeyToken verifyToken(String tokenString, PublicKey realmKey, String realm) throws VerificationException {
|
||||
JWSInput input = new JWSInput(tokenString);
|
||||
|
@ -31,7 +25,7 @@ public class RSATokenVerifier {
|
|||
|
||||
SkeletonKeyToken token = null;
|
||||
try {
|
||||
token = JsonSerialization.fromBytes(SkeletonKeyToken.class, input.getContent());
|
||||
token = input.readJsonContent(SkeletonKeyToken.class);
|
||||
} catch (IOException e) {
|
||||
throw new VerificationException(e);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
*/
|
||||
public class TokenIdGenerator {
|
||||
private static final AtomicLong counter = new AtomicLong();
|
||||
|
||||
public static String generateId() {
|
||||
return UUID.randomUUID().toString() + "-" + System.currentTimeMillis();
|
||||
}
|
||||
|
|
18
core/src/main/java/org/keycloak/jose/jws/Algorithm.java
Executable file
18
core/src/main/java/org/keycloak/jose/jws/Algorithm.java
Executable file
|
@ -0,0 +1,18 @@
|
|||
package org.keycloak.jose.jws;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public enum Algorithm {
|
||||
none,
|
||||
HS256,
|
||||
HS384,
|
||||
HS512,
|
||||
RS256,
|
||||
RS384,
|
||||
RS512,
|
||||
ES256,
|
||||
ES384,
|
||||
ES512
|
||||
}
|
138
core/src/main/java/org/keycloak/jose/jws/JWSBuilder.java
Executable file
138
core/src/main/java/org/keycloak/jose/jws/JWSBuilder.java
Executable file
|
@ -0,0 +1,138 @@
|
|||
package org.keycloak.jose.jws;
|
||||
|
||||
import org.keycloak.jose.jws.crypto.HMACProvider;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.util.Base64Url;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.PrivateKey;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JWSBuilder {
|
||||
String type;
|
||||
String contentType;
|
||||
byte[] contentBytes;
|
||||
|
||||
public JWSBuilder type(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JWSBuilder contentType(String type) {
|
||||
this.contentType = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EncodingBuilder content(byte[] bytes) {
|
||||
this.contentBytes = bytes;
|
||||
return new EncodingBuilder();
|
||||
}
|
||||
|
||||
public EncodingBuilder jsonContent(Object object) {
|
||||
try {
|
||||
this.contentBytes = JsonSerialization.writeValueAsBytes(object);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new EncodingBuilder();
|
||||
}
|
||||
|
||||
|
||||
protected String encodeHeader(Algorithm alg) {
|
||||
StringBuilder builder = new StringBuilder("{");
|
||||
builder.append("\"alg\":\"").append(alg.toString()).append("\"");
|
||||
|
||||
if (type != null) builder.append(",\"typ\" : \"").append(type).append("\"");
|
||||
if (contentType != null) builder.append(",\"cty\":\"").append(contentType).append("\"");
|
||||
builder.append("}");
|
||||
try {
|
||||
return Base64Url.encode(builder.toString().getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String encode(Algorithm alg, byte[] data, byte[] signature) {
|
||||
StringBuffer encoding = new StringBuffer();
|
||||
encoding.append(encodeHeader(alg));
|
||||
encoding.append('.');
|
||||
encoding.append(Base64Url.encode(data));
|
||||
encoding.append('.');
|
||||
if (alg != Algorithm.none) {
|
||||
encoding.append(Base64Url.encode(signature));
|
||||
}
|
||||
return encoding.toString();
|
||||
}
|
||||
|
||||
protected byte[] marshalContent() {
|
||||
return contentBytes;
|
||||
}
|
||||
|
||||
public class EncodingBuilder {
|
||||
public String none() {
|
||||
byte[] data = marshalContent();
|
||||
return encode(Algorithm.none, data, null);
|
||||
}
|
||||
|
||||
public String rsa256(PrivateKey privateKey) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = RSAProvider.sign(data, Algorithm.RS256, privateKey);
|
||||
return encode(Algorithm.RS256, data, signature);
|
||||
}
|
||||
|
||||
public String rsa384(PrivateKey privateKey) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = RSAProvider.sign(data, Algorithm.RS384, privateKey);
|
||||
return encode(Algorithm.RS384, data, signature);
|
||||
}
|
||||
|
||||
public String rsa512(PrivateKey privateKey) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = RSAProvider.sign(data, Algorithm.RS512, privateKey);
|
||||
return encode(Algorithm.RS512, data, signature);
|
||||
}
|
||||
|
||||
|
||||
public String hmac256(byte[] sharedSecret) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS256, sharedSecret);
|
||||
return encode(Algorithm.HS256, data, signature);
|
||||
}
|
||||
|
||||
public String hmac384(byte[] sharedSecret) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS384, sharedSecret);
|
||||
return encode(Algorithm.HS384, data, signature);
|
||||
}
|
||||
|
||||
public String hmac512(byte[] sharedSecret) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS512, sharedSecret);
|
||||
return encode(Algorithm.HS512, data, signature);
|
||||
}
|
||||
|
||||
public String hmac256(SecretKey sharedSecret) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS256, sharedSecret);
|
||||
return encode(Algorithm.HS256, data, signature);
|
||||
}
|
||||
|
||||
public String hmac384(SecretKey sharedSecret) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS384, sharedSecret);
|
||||
return encode(Algorithm.HS384, data, signature);
|
||||
}
|
||||
|
||||
public String hmac512(SecretKey sharedSecret) {
|
||||
byte[] data = marshalContent();
|
||||
byte[] signature = HMACProvider.sign(data, Algorithm.HS512, sharedSecret);
|
||||
return encode(Algorithm.HS512, data, signature);
|
||||
}
|
||||
}
|
||||
}
|
64
core/src/main/java/org/keycloak/jose/jws/JWSHeader.java
Executable file
64
core/src/main/java/org/keycloak/jose/jws/JWSHeader.java
Executable file
|
@ -0,0 +1,64 @@
|
|||
package org.keycloak.jose.jws;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JWSHeader implements Serializable {
|
||||
@JsonProperty("alg")
|
||||
private Algorithm algorithm;
|
||||
|
||||
@JsonProperty("typ")
|
||||
private String type;
|
||||
|
||||
@JsonProperty("cty")
|
||||
private String contentType;
|
||||
|
||||
public JWSHeader() {
|
||||
}
|
||||
|
||||
public JWSHeader(Algorithm algorithm, String type, String contentType) {
|
||||
this.algorithm = algorithm;
|
||||
this.type = type;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public Algorithm getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
|
||||
private static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
static {
|
||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
try {
|
||||
return mapper.writeValueAsString(this);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
82
core/src/main/java/org/keycloak/jose/jws/JWSInput.java
Executable file
82
core/src/main/java/org/keycloak/jose/jws/JWSInput.java
Executable file
|
@ -0,0 +1,82 @@
|
|||
package org.keycloak.jose.jws;
|
||||
|
||||
import org.keycloak.util.Base64Url;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JWSInput {
|
||||
String wireString;
|
||||
String encodedHeader;
|
||||
String encodedContent;
|
||||
String encodedSignature;
|
||||
JWSHeader header;
|
||||
byte[] content;
|
||||
byte[] signature;
|
||||
|
||||
|
||||
public JWSInput(String wire) {
|
||||
this.wireString = wire;
|
||||
String[] parts = wire.split("\\.");
|
||||
if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
|
||||
encodedHeader = parts[0];
|
||||
encodedContent = parts[1];
|
||||
try {
|
||||
content = Base64Url.decode(encodedContent);
|
||||
if (parts.length > 2) {
|
||||
encodedSignature = parts[2];
|
||||
signature = Base64Url.decode(encodedSignature);
|
||||
|
||||
}
|
||||
byte[] headerBytes = Base64Url.decode(encodedHeader);
|
||||
header = JsonSerialization.readValue(headerBytes, JWSHeader.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getWireString() {
|
||||
return wireString;
|
||||
}
|
||||
|
||||
public String getEncodedHeader() {
|
||||
return encodedHeader;
|
||||
}
|
||||
|
||||
public String getEncodedContent() {
|
||||
return encodedContent;
|
||||
}
|
||||
|
||||
public String getEncodedSignature() {
|
||||
return encodedSignature;
|
||||
}
|
||||
|
||||
public JWSHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public <T> T readJsonContent(Class<T> type) throws IOException {
|
||||
return JsonSerialization.readValue(content, type);
|
||||
}
|
||||
|
||||
public String readContentAsString() {
|
||||
try {
|
||||
return new String(content, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
86
core/src/main/java/org/keycloak/jose/jws/crypto/HMACProvider.java
Executable file
86
core/src/main/java/org/keycloak/jose/jws/crypto/HMACProvider.java
Executable file
|
@ -0,0 +1,86 @@
|
|||
package org.keycloak.jose.jws.crypto;
|
||||
|
||||
|
||||
import org.keycloak.jose.jws.Algorithm;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.util.Base64Url;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class HMACProvider {
|
||||
public static String getJavaAlgorithm(Algorithm alg) {
|
||||
switch (alg) {
|
||||
case HS256:
|
||||
return "HMACSHA256";
|
||||
case HS384:
|
||||
return "HMACSHA384";
|
||||
case HS512:
|
||||
return "HMACSHA512";
|
||||
default:
|
||||
throw new IllegalArgumentException("Not a MAC Algorithm");
|
||||
}
|
||||
}
|
||||
|
||||
public static Mac getMAC(final Algorithm alg) {
|
||||
|
||||
try {
|
||||
return Mac.getInstance(getJavaAlgorithm(alg));
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
|
||||
throw new RuntimeException("Unsupported HMAC algorithm: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] sign(byte[] data, Algorithm algorithm, byte[] sharedSecret) {
|
||||
try {
|
||||
Mac mac = getMAC(algorithm);
|
||||
mac.init(new SecretKeySpec(sharedSecret, mac.getAlgorithm()));
|
||||
mac.update(data);
|
||||
return mac.doFinal();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] sign(byte[] data, Algorithm algorithm, SecretKey key) {
|
||||
try {
|
||||
Mac mac = getMAC(algorithm);
|
||||
mac.init(key);
|
||||
mac.update(data);
|
||||
return mac.doFinal();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verify(JWSInput input, SecretKey key) {
|
||||
try {
|
||||
byte[] signature = sign(input.getContent(), input.getHeader().getAlgorithm(), key);
|
||||
String x = Base64Url.encode(signature);
|
||||
return x.equals(input.getEncodedSignature());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean verify(JWSInput input, byte[] sharedSecret) {
|
||||
try {
|
||||
byte[] signature = sign(input.getContent(), input.getHeader().getAlgorithm(), sharedSecret);
|
||||
String x = Base64Url.encode(signature);
|
||||
return x.equals(input.getEncodedSignature());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
61
core/src/main/java/org/keycloak/jose/jws/crypto/RSAProvider.java
Executable file
61
core/src/main/java/org/keycloak/jose/jws/crypto/RSAProvider.java
Executable file
|
@ -0,0 +1,61 @@
|
|||
package org.keycloak.jose.jws.crypto;
|
||||
|
||||
|
||||
import org.keycloak.jose.jws.Algorithm;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RSAProvider {
|
||||
public static String getJavaAlgorithm(Algorithm alg) {
|
||||
switch (alg) {
|
||||
case RS256:
|
||||
return "SHA256withRSA";
|
||||
case RS384:
|
||||
return "SHA384withRSA";
|
||||
case RS512:
|
||||
return "SHA512withRSA";
|
||||
default:
|
||||
throw new IllegalArgumentException("Not an RSA Algorithm");
|
||||
}
|
||||
}
|
||||
|
||||
public static Signature getSignature(Algorithm alg) {
|
||||
try {
|
||||
return Signature.getInstance(getJavaAlgorithm(alg));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] sign(byte[] data, Algorithm algorithm, PrivateKey privateKey) {
|
||||
try {
|
||||
Signature signature = getSignature(algorithm);
|
||||
signature.initSign(privateKey);
|
||||
signature.update(data);
|
||||
return signature.sign();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verify(JWSInput input, PublicKey publicKey) {
|
||||
try {
|
||||
Signature verifier = getSignature(input.getHeader().getAlgorithm());
|
||||
verifier.initVerify(publicKey);
|
||||
verifier.update(input.getContent());
|
||||
return verifier.verify(input.getSignature());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
136
core/src/main/java/org/keycloak/jwt/JsonWebToken.java
Executable file
136
core/src/main/java/org/keycloak/jwt/JsonWebToken.java
Executable file
|
@ -0,0 +1,136 @@
|
|||
package org.keycloak.jwt;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JsonWebToken implements Serializable {
|
||||
@JsonProperty("jti")
|
||||
protected String id;
|
||||
@JsonProperty("exp")
|
||||
protected long expiration;
|
||||
@JsonProperty("nbf")
|
||||
protected long notBefore;
|
||||
@JsonProperty("iat")
|
||||
protected long issuedAt;
|
||||
@JsonProperty("iss")
|
||||
protected String issuer;
|
||||
@JsonProperty("aud")
|
||||
protected String audience;
|
||||
@JsonProperty("prn")
|
||||
protected String principal;
|
||||
@JsonProperty("typ")
|
||||
protected String type;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public JsonWebToken id(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public long getExpiration() {
|
||||
return expiration;
|
||||
}
|
||||
|
||||
public JsonWebToken expiration(long expiration) {
|
||||
this.expiration = expiration;
|
||||
return this;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isExpired() {
|
||||
long time = System.currentTimeMillis() / 1000;
|
||||
return time > expiration;
|
||||
}
|
||||
|
||||
public long getNotBefore() {
|
||||
return notBefore;
|
||||
}
|
||||
|
||||
public JsonWebToken notBefore(long notBefore) {
|
||||
this.notBefore = notBefore;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isNotBefore() {
|
||||
return (System.currentTimeMillis() / 1000) >= notBefore;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the token is not expired and is not-before.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JsonIgnore
|
||||
public boolean isActive() {
|
||||
return (!isExpired() || expiration == 0) && (isNotBefore() || notBefore == 0);
|
||||
}
|
||||
|
||||
public long getIssuedAt() {
|
||||
return issuedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set issuedAt to the current time
|
||||
*/
|
||||
@JsonIgnore
|
||||
public JsonWebToken issuedNow() {
|
||||
issuedAt = System.currentTimeMillis() / 1000;
|
||||
return this;
|
||||
}
|
||||
|
||||
public JsonWebToken issuedAt(long issuedAt) {
|
||||
this.issuedAt = issuedAt;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public String getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
|
||||
public JsonWebToken issuer(String issuer) {
|
||||
this.issuer = issuer;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public String getAudience() {
|
||||
return audience;
|
||||
}
|
||||
|
||||
public JsonWebToken audience(String audience) {
|
||||
this.audience = audience;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
public JsonWebToken principal(String principal) {
|
||||
this.principal = principal;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public JsonWebToken type(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package org.keycloak.representations;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedHashMap;
|
||||
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
/**
|
||||
* Key is resource desired. Values are roles desired for that resource
|
||||
|
|
|
@ -2,7 +2,7 @@ package org.keycloak.representations;
|
|||
|
||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.jboss.resteasy.jwt.JsonWebToken;
|
||||
import org.keycloak.jwt.JsonWebToken;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
|
|
@ -2,8 +2,6 @@ package org.keycloak.representations.idm;
|
|||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package org.keycloak.representations.idm;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CredentialRepresentation {
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String TOTP = "totp";
|
||||
|
|
|
@ -19,7 +19,7 @@ public class MappingsRepresentation {
|
|||
this.realmMappings = realmMappings;
|
||||
}
|
||||
|
||||
public Map<String,ApplicationMappingsRepresentation> getApplicationMappings() {
|
||||
public Map<String, ApplicationMappingsRepresentation> getApplicationMappings() {
|
||||
return applicationMappings;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.representations.idm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
|
@ -41,8 +41,7 @@ public class AdminAction {
|
|||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isExpired()
|
||||
{
|
||||
public boolean isExpired() {
|
||||
long time = System.currentTimeMillis() / 1000;
|
||||
return time > expiration;
|
||||
}
|
||||
|
|
2091
core/src/main/java/org/keycloak/util/Base64.java
Executable file
2091
core/src/main/java/org/keycloak/util/Base64.java
Executable file
File diff suppressed because it is too large
Load diff
42
core/src/main/java/org/keycloak/util/Base64Url.java
Executable file
42
core/src/main/java/org/keycloak/util/Base64Url.java
Executable file
|
@ -0,0 +1,42 @@
|
|||
package org.keycloak.util;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Base64Url {
|
||||
public static String encode(byte[] bytes) {
|
||||
String s = Base64.encodeBytes(bytes);
|
||||
s = s.split("=")[0]; // Remove any trailing '='s
|
||||
s = s.replace('+', '-'); // 62nd char of encoding
|
||||
s = s.replace('/', '_'); // 63rd char of encoding
|
||||
return s;
|
||||
}
|
||||
|
||||
public static byte[] decode(String s) {
|
||||
s = s.replace('-', '+'); // 62nd char of encoding
|
||||
s = s.replace('_', '/'); // 63rd char of encoding
|
||||
switch (s.length() % 4) // Pad with trailing '='s
|
||||
{
|
||||
case 0:
|
||||
break; // No pad chars in this case
|
||||
case 2:
|
||||
s += "==";
|
||||
break; // Two pad chars
|
||||
case 3:
|
||||
s += "=";
|
||||
break; // One pad char
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Illegal base64url string!");
|
||||
}
|
||||
try {
|
||||
return Base64.decode(s);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
45
core/src/main/java/org/keycloak/util/JsonSerialization.java
Executable file
45
core/src/main/java/org/keycloak/util/JsonSerialization.java
Executable file
|
@ -0,0 +1,45 @@
|
|||
package org.keycloak.util;
|
||||
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Any class that extends JsonWebToken will use NON_DEFAULT inclusion
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JsonSerialization {
|
||||
public static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
static {
|
||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
|
||||
}
|
||||
|
||||
public static String writeValueAsString(Object obj) throws IOException {
|
||||
return mapper.writeValueAsString(obj);
|
||||
}
|
||||
|
||||
public static byte[] writeValueAsBytes(Object obj) throws IOException {
|
||||
return mapper.writeValueAsBytes(obj);
|
||||
}
|
||||
|
||||
public static <T> T readValue(byte[] bytes, Class<T> type) throws IOException {
|
||||
return mapper.readValue(bytes, type);
|
||||
}
|
||||
|
||||
public static <T> T readValue(String bytes, Class<T> type) throws IOException {
|
||||
return mapper.readValue(bytes, type);
|
||||
}
|
||||
|
||||
public static <T> T readValue(InputStream bytes, Class<T> type) throws IOException {
|
||||
return mapper.readValue(bytes, type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
105
core/src/main/java/org/keycloak/util/MultivaluedHashMap.java
Executable file
105
core/src/main/java/org/keycloak/util/MultivaluedHashMap.java
Executable file
|
@ -0,0 +1,105 @@
|
|||
package org.keycloak.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MultivaluedHashMap<K, V> extends HashMap<K, List<V>>
|
||||
{
|
||||
public void putSingle(K key, V value)
|
||||
{
|
||||
List<V> list = new ArrayList<V>();
|
||||
list.add(value);
|
||||
put(key, list);
|
||||
}
|
||||
|
||||
public void addAll(K key, V... newValues)
|
||||
{
|
||||
for (V value : newValues)
|
||||
{
|
||||
add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAll(K key, List<V> valueList)
|
||||
{
|
||||
for (V value : valueList)
|
||||
{
|
||||
add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void addFirst(K key, V value)
|
||||
{
|
||||
List<V> list = get(key);
|
||||
if (list == null)
|
||||
{
|
||||
add(key, value);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
list.add(0, value);
|
||||
}
|
||||
}
|
||||
public final void add(K key, V value)
|
||||
{
|
||||
getList(key).add(value);
|
||||
}
|
||||
|
||||
|
||||
public final void addMultiple(K key, Collection<V> values)
|
||||
{
|
||||
getList(key).addAll(values);
|
||||
}
|
||||
|
||||
public V getFirst(K key)
|
||||
{
|
||||
List<V> list = get(key);
|
||||
return list == null ? null : list.get(0);
|
||||
}
|
||||
|
||||
public final List<V> getList(K key)
|
||||
{
|
||||
List<V> list = get(key);
|
||||
if (list == null)
|
||||
put(key, list = new ArrayList<V>());
|
||||
return list;
|
||||
}
|
||||
|
||||
public void addAll(MultivaluedHashMap<K, V> other)
|
||||
{
|
||||
for (Map.Entry<K, List<V>> entry : other.entrySet())
|
||||
{
|
||||
getList(entry.getKey()).addAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equalsIgnoreValueOrder(MultivaluedHashMap<K, V> omap) {
|
||||
if (this == omap) {
|
||||
return true;
|
||||
}
|
||||
if (!keySet().equals(omap.keySet())) {
|
||||
return false;
|
||||
}
|
||||
for (Map.Entry<K, List<V>> e : entrySet()) {
|
||||
List<V> olist = omap.get(e.getKey());
|
||||
if (e.getValue().size() != olist.size()) {
|
||||
return false;
|
||||
}
|
||||
for (V v : e.getValue()) {
|
||||
if (!olist.contains(v)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -4,11 +4,10 @@ import junit.framework.Assert;
|
|||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMWriter;
|
||||
import org.bouncycastle.x509.X509V1CertificateGenerator;
|
||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
@ -30,94 +29,80 @@ import java.util.Date;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RSAVerifierTest
|
||||
{
|
||||
private static X509Certificate[] idpCertificates;
|
||||
private static KeyPair idpPair;
|
||||
private static KeyPair badPair;
|
||||
private static KeyPair clientPair;
|
||||
private static X509Certificate[] clientCertificateChain;
|
||||
private ResourceMetadata metadata;
|
||||
private SkeletonKeyToken token;
|
||||
public class RSAVerifierTest {
|
||||
private static X509Certificate[] idpCertificates;
|
||||
private static KeyPair idpPair;
|
||||
private static KeyPair badPair;
|
||||
private static KeyPair clientPair;
|
||||
private static X509Certificate[] clientCertificateChain;
|
||||
private SkeletonKeyToken token;
|
||||
|
||||
static
|
||||
{
|
||||
if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
static {
|
||||
if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
public static X509Certificate generateTestCertificate(String subject, String issuer, KeyPair pair) throws InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException
|
||||
{
|
||||
public static X509Certificate generateTestCertificate(String subject, String issuer, KeyPair pair) throws InvalidKeyException,
|
||||
NoSuchProviderException, SignatureException {
|
||||
|
||||
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
|
||||
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
|
||||
|
||||
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
|
||||
certGen.setIssuerDN(new X500Principal(issuer));
|
||||
certGen.setNotBefore(new Date(System.currentTimeMillis() - 10000));
|
||||
certGen.setNotAfter(new Date(System.currentTimeMillis() + 10000));
|
||||
certGen.setSubjectDN(new X500Principal(subject));
|
||||
certGen.setPublicKey(pair.getPublic());
|
||||
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
|
||||
certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
|
||||
certGen.setIssuerDN(new X500Principal(issuer));
|
||||
certGen.setNotBefore(new Date(System.currentTimeMillis() - 10000));
|
||||
certGen.setNotAfter(new Date(System.currentTimeMillis() + 10000));
|
||||
certGen.setSubjectDN(new X500Principal(subject));
|
||||
certGen.setPublicKey(pair.getPublic());
|
||||
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
|
||||
|
||||
return certGen.generateX509Certificate(pair.getPrivate(), "BC");
|
||||
}
|
||||
return certGen.generateX509Certificate(pair.getPrivate(), "BC");
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setupCerts() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException
|
||||
{
|
||||
badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
idpPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
idpCertificates = new X509Certificate[]{generateTestCertificate("CN=IDP", "CN=IDP", idpPair)};
|
||||
clientPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
clientCertificateChain = new X509Certificate[]{generateTestCertificate("CN=Client", "CN=IDP", idpPair)};
|
||||
}
|
||||
@BeforeClass
|
||||
public static void setupCerts() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException {
|
||||
badPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
idpPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
idpCertificates = new X509Certificate[]{generateTestCertificate("CN=IDP", "CN=IDP", idpPair)};
|
||||
clientPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
clientCertificateChain = new X509Certificate[]{generateTestCertificate("CN=Client", "CN=IDP", idpPair)};
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initTest()
|
||||
{
|
||||
metadata = new ResourceMetadata();
|
||||
metadata.setResourceName("service");
|
||||
metadata.setRealm("domain");
|
||||
metadata.setRealmKey(idpPair.getPublic());
|
||||
@Before
|
||||
public void initTest() {
|
||||
|
||||
token = new SkeletonKeyToken();
|
||||
token.principal("CN=Client")
|
||||
.audience("domain")
|
||||
.addAccess("service").addRole("admin");
|
||||
}
|
||||
token = new SkeletonKeyToken();
|
||||
token.principal("CN=Client")
|
||||
.audience("domain")
|
||||
.addAccess("service").addRole("admin");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPemWriter() throws Exception
|
||||
{
|
||||
PublicKey realmPublicKey = idpPair.getPublic();
|
||||
StringWriter sw = new StringWriter();
|
||||
PEMWriter writer = new PEMWriter(sw);
|
||||
try
|
||||
{
|
||||
writer.writeObject(realmPublicKey);
|
||||
writer.flush();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println(sw.toString());
|
||||
}
|
||||
@Test
|
||||
public void testPemWriter() throws Exception {
|
||||
PublicKey realmPublicKey = idpPair.getPublic();
|
||||
StringWriter sw = new StringWriter();
|
||||
PEMWriter writer = new PEMWriter(sw);
|
||||
try {
|
||||
writer.writeObject(realmPublicKey);
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.out.println(sw.toString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimpleVerification() throws Exception
|
||||
{
|
||||
@Test
|
||||
public void testSimpleVerification() throws Exception {
|
||||
String encoded = new JWSBuilder()
|
||||
.jsonContent(token)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
SkeletonKeyToken token = verifySkeletonKeyToken(encoded);
|
||||
Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
|
||||
Assert.assertEquals("CN=Client", token.getPrincipal());
|
||||
}
|
||||
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
SkeletonKeyToken token = RSATokenVerifier.verifyToken(encoded, metadata);
|
||||
Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
|
||||
Assert.assertEquals("CN=Client", token.getPrincipal());
|
||||
}
|
||||
private SkeletonKeyToken verifySkeletonKeyToken(String encoded) throws VerificationException {
|
||||
return RSATokenVerifier.verifyToken(encoded, idpPair.getPublic(), "domain");
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
|
@ -143,137 +128,105 @@ public class RSAVerifierTest
|
|||
*/
|
||||
|
||||
|
||||
@Test
|
||||
public void testBadSignature() throws Exception
|
||||
{
|
||||
@Test
|
||||
public void testBadSignature() throws Exception {
|
||||
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
String encoded = new JWSBuilder()
|
||||
.jsonContent(token)
|
||||
.rsa256(badPair.getPrivate());
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.rsa256(badPair.getPrivate());
|
||||
SkeletonKeyToken v = null;
|
||||
try {
|
||||
v = verifySkeletonKeyToken(encoded);
|
||||
Assert.fail();
|
||||
} catch (VerificationException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonKeyToken v = null;
|
||||
try
|
||||
{
|
||||
v = RSATokenVerifier.verifyToken(encoded, metadata);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (VerificationException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testNotBeforeGood() throws Exception {
|
||||
token.notBefore((System.currentTimeMillis() / 1000) - 100);
|
||||
|
||||
@Test
|
||||
public void testNotBeforeGood() throws Exception
|
||||
{
|
||||
token.notBefore((System.currentTimeMillis()/1000) - 100);
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
String encoded = new JWSBuilder()
|
||||
.jsonContent(token)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
SkeletonKeyToken v = null;
|
||||
try {
|
||||
v = verifySkeletonKeyToken(encoded);
|
||||
} catch (VerificationException ignored) {
|
||||
throw ignored;
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonKeyToken v = null;
|
||||
try
|
||||
{
|
||||
v = RSATokenVerifier.verifyToken(encoded, metadata);
|
||||
}
|
||||
catch (VerificationException ignored)
|
||||
{
|
||||
throw ignored;
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testNotBeforeBad() throws Exception {
|
||||
token.notBefore((System.currentTimeMillis() / 1000) + 100);
|
||||
|
||||
@Test
|
||||
public void testNotBeforeBad() throws Exception
|
||||
{
|
||||
token.notBefore((System.currentTimeMillis()/1000) + 100);
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
String encoded = new JWSBuilder()
|
||||
.jsonContent(token)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
SkeletonKeyToken v = null;
|
||||
try {
|
||||
v = verifySkeletonKeyToken(encoded);
|
||||
Assert.fail();
|
||||
} catch (VerificationException ignored) {
|
||||
System.out.println(ignored.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonKeyToken v = null;
|
||||
try
|
||||
{
|
||||
v = RSATokenVerifier.verifyToken(encoded, metadata);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (VerificationException ignored)
|
||||
{
|
||||
System.out.println(ignored.getMessage());
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testExpirationGood() throws Exception {
|
||||
token.expiration((System.currentTimeMillis() / 1000) + 100);
|
||||
|
||||
@Test
|
||||
public void testExpirationGood() throws Exception
|
||||
{
|
||||
token.expiration((System.currentTimeMillis()/1000) + 100);
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
String encoded = new JWSBuilder()
|
||||
.jsonContent(token)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
SkeletonKeyToken v = null;
|
||||
try {
|
||||
v = verifySkeletonKeyToken(encoded);
|
||||
} catch (VerificationException ignored) {
|
||||
throw ignored;
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonKeyToken v = null;
|
||||
try
|
||||
{
|
||||
v = RSATokenVerifier.verifyToken(encoded, metadata);
|
||||
}
|
||||
catch (VerificationException ignored)
|
||||
{
|
||||
throw ignored;
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testExpirationBad() throws Exception {
|
||||
token.expiration((System.currentTimeMillis() / 1000) - 100);
|
||||
|
||||
@Test
|
||||
public void testExpirationBad() throws Exception
|
||||
{
|
||||
token.expiration((System.currentTimeMillis()/1000) - 100);
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
String encoded = new JWSBuilder()
|
||||
.jsonContent(token)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
SkeletonKeyToken v = null;
|
||||
try {
|
||||
v = verifySkeletonKeyToken(encoded);
|
||||
Assert.fail();
|
||||
} catch (VerificationException ignored) {
|
||||
System.out.println(ignored.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonKeyToken v = null;
|
||||
try
|
||||
{
|
||||
v = RSATokenVerifier.verifyToken(encoded, metadata);
|
||||
Assert.fail();
|
||||
}
|
||||
catch (VerificationException ignored)
|
||||
{
|
||||
System.out.println(ignored.getMessage());
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testTokenAuth() throws Exception {
|
||||
token = new SkeletonKeyToken();
|
||||
token.principal("CN=Client")
|
||||
.audience("domain")
|
||||
.addAccess("service").addRole("admin").verifyCaller(true);
|
||||
|
||||
@Test
|
||||
public void testTokenAuth() throws Exception
|
||||
{
|
||||
token = new SkeletonKeyToken();
|
||||
token.principal("CN=Client")
|
||||
.audience("domain")
|
||||
.addAccess("service").addRole("admin").verifyCaller(true);
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
|
||||
SkeletonKeyToken v = null;
|
||||
try
|
||||
{
|
||||
v = RSATokenVerifier.verifyToken(encoded, metadata);
|
||||
}
|
||||
catch (VerificationException ignored)
|
||||
{
|
||||
System.out.println(ignored.getMessage());
|
||||
}
|
||||
}
|
||||
String encoded = new JWSBuilder()
|
||||
.jsonContent(token)
|
||||
.rsa256(idpPair.getPrivate());
|
||||
|
||||
SkeletonKeyToken v = null;
|
||||
try {
|
||||
v = verifySkeletonKeyToken(encoded);
|
||||
} catch (VerificationException ignored) {
|
||||
System.out.println(ignored.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package org.keycloak;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.representations.SkeletonKeyScope;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
||||
|
@ -26,7 +26,7 @@ public class SkeletonKeyTokenTest
|
|||
scope2.add("one", "admin");
|
||||
scope2.add("one", "buyer");
|
||||
scope2.add("two", "seller");
|
||||
String json = JsonSerialization.toString(scope2, true);
|
||||
String json = JsonSerialization.writeValueAsString(scope2);
|
||||
System.out.println(json);
|
||||
|
||||
|
||||
|
@ -40,10 +40,10 @@ public class SkeletonKeyTokenTest
|
|||
token.addAccess("foo").addRole("admin");
|
||||
token.addAccess("bar").addRole("user");
|
||||
|
||||
String json = JsonSerialization.toString(token, true);
|
||||
String json = JsonSerialization.writeValueAsString(token);
|
||||
System.out.println(json);
|
||||
|
||||
token = JsonSerialization.fromString(SkeletonKeyToken.class, json);
|
||||
token = JsonSerialization.readValue(json, SkeletonKeyToken.class);
|
||||
Assert.assertEquals("111", token.getId());
|
||||
SkeletonKeyToken.Access foo = token.getResourceAccess("foo");
|
||||
Assert.assertNotNull(foo);
|
||||
|
@ -60,18 +60,16 @@ public class SkeletonKeyTokenTest
|
|||
token.addAccess("bar").addRole("user");
|
||||
|
||||
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
byte[] tokenBytes = JsonSerialization.toByteArray(token, true);
|
||||
|
||||
String encoded = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.jsonContent(token)
|
||||
.rsa256(keyPair.getPrivate());
|
||||
|
||||
System.out.println(encoded);
|
||||
|
||||
JWSInput input = new JWSInput(encoded);
|
||||
byte[] content = input.getContent();
|
||||
|
||||
token = JsonSerialization.fromBytes(SkeletonKeyToken.class, content);
|
||||
token = input.readJsonContent(SkeletonKeyToken.class);
|
||||
Assert.assertEquals("111", token.getId());
|
||||
Assert.assertTrue(RSAProvider.verify(input, keyPair.getPublic()));
|
||||
}
|
||||
|
|
|
@ -38,6 +38,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<module name="org.bouncycastle"/>
|
||||
<module name="org.jboss.resteasy.resteasy-jaxrs" services="import"/>
|
||||
<module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/>
|
||||
<module name="org.jboss.resteasy.jose-jwt" />
|
||||
</dependencies>
|
||||
</deployment>
|
||||
</jboss-deployment-structure>
|
|
@ -34,6 +34,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
<!-- This allows you to define additional dependencies, it is the same as using the Dependencies: manifest attribute -->
|
||||
<dependencies>
|
||||
<module name="org.bouncycastle"/>
|
||||
<module name="org.jboss.resteasy.jose-jwt" />
|
||||
</dependencies>
|
||||
</deployment>
|
||||
</jboss-deployment-structure>
|
|
@ -38,6 +38,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<module name="org.bouncycastle"/>
|
||||
<module name="org.jboss.resteasy.resteasy-jaxrs" services="import"/>
|
||||
<module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/>
|
||||
<module name="org.jboss.resteasy.jose-jwt" />
|
||||
</dependencies>
|
||||
</deployment>
|
||||
</jboss-deployment-structure>
|
|
@ -15,11 +15,20 @@
|
|||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-services</artifactId>
|
||||
|
@ -120,11 +129,6 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- resteasy -->
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<version>${resteasy.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.keycloak.example.demo;
|
||||
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -10,7 +10,6 @@ import org.keycloak.services.resources.KeycloakApplication;
|
|||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.core.Context;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
/**
|
||||
|
@ -39,17 +38,8 @@ public class DemoApplication extends KeycloakApplication {
|
|||
public static RealmRepresentation loadJson(String path)
|
||||
{
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int c;
|
||||
try {
|
||||
while ( (c = is.read()) != -1)
|
||||
{
|
||||
os.write(c);
|
||||
}
|
||||
byte[] bytes = os.toByteArray();
|
||||
//System.out.println(new String(bytes));
|
||||
|
||||
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
|
||||
return JsonSerialization.readValue(is, RealmRepresentation.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
5
examples/as7-eap-demo/third-party/pom.xml
vendored
5
examples/as7-eap-demo/third-party/pom.xml
vendored
|
@ -31,6 +31,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
|
|
|
@ -36,6 +36,16 @@
|
|||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package org.keycloak;
|
||||
package org.keycloak.adapters;
|
||||
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
|
||||
import javax.ws.rs.core.Form;
|
||||
import javax.ws.rs.core.UriBuilder;
|
|
@ -31,11 +31,6 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
|
|
|
@ -72,7 +72,7 @@ public class CatalinaBearerTokenAuthenticator {
|
|||
tokenString = split[1];
|
||||
|
||||
try {
|
||||
token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
|
||||
token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm());
|
||||
} catch (VerificationException e) {
|
||||
log.error("Failed to verify token", e);
|
||||
challengeResponse(response, "invalid_token", e.getMessage());
|
||||
|
|
|
@ -13,19 +13,19 @@ import org.apache.catalina.core.StandardContext;
|
|||
import org.apache.catalina.deploy.LoginConfig;
|
||||
import org.apache.catalina.realm.GenericPrincipal;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeyPrincipal;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.as7.config.CatalinaAdapterConfigLoader;
|
||||
import org.keycloak.adapters.as7.config.RealmConfigurationLoader;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.keycloak.representations.idm.admin.LogoutAction;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -148,7 +148,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
|||
protected void remoteLogout(JWSInput token, HttpServletResponse response) throws IOException {
|
||||
try {
|
||||
log.debug("->> remoteLogout: ");
|
||||
LogoutAction action = JsonSerialization.fromBytes(LogoutAction.class, token.getContent());
|
||||
LogoutAction action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
|
||||
if (action.isExpired()) {
|
||||
log.warn("admin request failed, expired token");
|
||||
response.sendError(400, "Expired token");
|
||||
|
|
|
@ -2,7 +2,7 @@ package org.keycloak.adapters.as7;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
@ -256,7 +256,7 @@ public class ServletOAuthLogin {
|
|||
|
||||
tokenString = tokenResponse.getToken();
|
||||
try {
|
||||
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata());
|
||||
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata().getRealmKey(), realmInfo.getMetadata().getRealm());
|
||||
log.debug("Token Verification succeeded!");
|
||||
} catch (VerificationException e) {
|
||||
log.error("failed verification of token");
|
||||
|
|
|
@ -4,7 +4,7 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
|||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
import org.keycloak.adapters.config.AdapterConfigLoader;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
|
|
@ -31,11 +31,6 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
|
|
|
@ -78,7 +78,7 @@ public class BearerTokenAuthenticator {
|
|||
}
|
||||
|
||||
try {
|
||||
token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
|
||||
token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm());
|
||||
} catch (VerificationException e) {
|
||||
log.error("Failed to verify token", e);
|
||||
challenge = challengeResponse(exchange, "invalid_token", e.getMessage());
|
||||
|
|
|
@ -6,7 +6,7 @@ import io.undertow.security.idm.Account;
|
|||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.AttachmentKey;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeyPrincipal;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
|
|
|
@ -8,7 +8,7 @@ import io.undertow.server.handlers.CookieImpl;
|
|||
import io.undertow.util.Headers;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
@ -269,7 +269,7 @@ public class OAuthAuthenticator {
|
|||
|
||||
tokenString = tokenResponse.getToken();
|
||||
try {
|
||||
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata());
|
||||
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata().getRealmKey(), realmInfo.getMetadata().getRealm());
|
||||
log.debug("Token Verification succeeded!");
|
||||
} catch (VerificationException e) {
|
||||
log.error("failed verification of token");
|
||||
|
|
|
@ -4,7 +4,7 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
|||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
import org.keycloak.adapters.config.AdapterConfigLoader;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.keycloak.adapters.undertow;
|
|||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.servlet.api.ConfidentialPortManager;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
|
|
|
@ -2,7 +2,7 @@ package org.keycloak.adapters.undertow;
|
|||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.servlet.api.ConfidentialPortManager;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.RealmConfiguration;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
|
5
pom.xml
5
pom.xml
|
@ -74,6 +74,7 @@
|
|||
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>core-jaxrs</module>
|
||||
<module>model</module>
|
||||
<module>services</module>
|
||||
<module>integration</module>
|
||||
|
@ -117,12 +118,12 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
<artifactId>resteasy-jackson-provider</artifactId>
|
||||
<version>${resteasy.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
<version>${resteasy.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-admin-ui</artifactId>
|
||||
|
@ -103,6 +98,16 @@
|
|||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.keycloak.server;
|
||||
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
|
@ -11,7 +11,6 @@ import org.keycloak.services.resources.KeycloakApplication;
|
|||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.core.Context;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
@ -63,13 +62,7 @@ public class KeycloakServerApplication extends KeycloakApplication {
|
|||
|
||||
private static <T> T loadJson(InputStream is, Class<T> type) {
|
||||
try {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int c;
|
||||
while ((c = is.read()) != -1) {
|
||||
os.write(c);
|
||||
}
|
||||
byte[] bytes = os.toByteArray();
|
||||
return JsonSerialization.fromBytes(type, bytes);
|
||||
return JsonSerialization.readValue(is, type);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to parse json", e);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-model-api</artifactId>
|
||||
|
@ -92,11 +98,6 @@
|
|||
<artifactId>resteasy-crypto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-multipart-provider</artifactId>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package org.keycloak.services.managers;
|
||||
|
||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RequiredCredentialModel;
|
||||
|
@ -85,14 +84,8 @@ public class AuthenticationManager {
|
|||
}
|
||||
|
||||
protected String encodeToken(RealmModel realm, Object token) {
|
||||
byte[] tokenBytes = null;
|
||||
try {
|
||||
tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String encodedToken = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.jsonContent(token)
|
||||
.rsa256(realm.getPrivateKey());
|
||||
return encodedToken;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package org.keycloak.services.managers;
|
||||
|
||||
import org.jboss.resteasy.jose.Base64Url;
|
||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -11,6 +10,7 @@ import org.keycloak.models.RoleModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.SkeletonKeyScope;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.keycloak.util.Base64Url;
|
||||
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import java.io.IOException;
|
||||
|
@ -149,7 +149,7 @@ public class TokenManager {
|
|||
public String encodeScope(SkeletonKeyScope scope) {
|
||||
String token = null;
|
||||
try {
|
||||
token = JsonSerialization.toString(scope, false);
|
||||
token = JsonSerialization.writeValueAsString(scope);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ public class TokenManager {
|
|||
SkeletonKeyScope scope = null;
|
||||
byte[] bytes = Base64Url.decode(scopeParam);
|
||||
try {
|
||||
scope = JsonSerialization.fromBytes(SkeletonKeyScope.class, bytes);
|
||||
scope = JsonSerialization.readValue(bytes, SkeletonKeyScope.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -204,14 +204,8 @@ public class TokenManager {
|
|||
|
||||
|
||||
public String encodeToken(RealmModel realm, Object token) {
|
||||
byte[] tokenBytes = null;
|
||||
try {
|
||||
tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String encodedToken = new JWSBuilder()
|
||||
.content(tokenBytes)
|
||||
.jsonContent(token)
|
||||
.rsa256(realm.getPrivateKey());
|
||||
return encodedToken;
|
||||
}
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
*/
|
||||
package org.keycloak.services.resources;
|
||||
|
||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.AbstractOAuthClient;
|
||||
import org.keycloak.jaxrs.JaxrsOAuthClient;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.models.utils.TimeBasedOTP;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
@ -295,7 +295,7 @@ public class AccountService {
|
|||
}
|
||||
String path = new JaxrsOAuthClient().checkStateCookie(uriInfo, headers);
|
||||
|
||||
JWSInput input = new JWSInput(code, providers);
|
||||
JWSInput input = new JWSInput(code);
|
||||
boolean verifiedCode = false;
|
||||
try {
|
||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||
|
@ -306,7 +306,7 @@ public class AccountService {
|
|||
logger.debug("unverified access code");
|
||||
throw new BadRequestException();
|
||||
}
|
||||
String key = input.readContent(String.class);
|
||||
String key = input.readContentAsString();
|
||||
AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
|
||||
if (accessCode == null) {
|
||||
logger.debug("bad access code");
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
*/
|
||||
package org.keycloak.services.resources;
|
||||
|
||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
@ -321,7 +321,7 @@ public class RequiredActionsService {
|
|||
return null;
|
||||
}
|
||||
|
||||
JWSInput input = new JWSInput(code, providers);
|
||||
JWSInput input = new JWSInput(code);
|
||||
boolean verifiedCode = false;
|
||||
try {
|
||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||
|
@ -335,7 +335,7 @@ public class RequiredActionsService {
|
|||
return null;
|
||||
}
|
||||
|
||||
String key = input.readContent(String.class);
|
||||
String key = input.readContentAsString();
|
||||
AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key);
|
||||
if (accessCodeEntry == null) {
|
||||
logger.debug("getAccessCodeEntry access code entry null");
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package org.keycloak.services.resources;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.NotImplementedYetException;
|
||||
import org.keycloak.AbstractOAuthClient;
|
||||
import org.keycloak.jaxrs.JaxrsOAuthClient;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -257,7 +257,7 @@ public class SaasService {
|
|||
}
|
||||
String path = new JaxrsOAuthClient().checkStateCookie(uriInfo, headers);
|
||||
|
||||
JWSInput input = new JWSInput(code, providers);
|
||||
JWSInput input = new JWSInput(code);
|
||||
boolean verifiedCode = false;
|
||||
try {
|
||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||
|
@ -268,7 +268,7 @@ public class SaasService {
|
|||
logger.debug("unverified access code");
|
||||
throw new BadRequestException();
|
||||
}
|
||||
String key = input.readContent(String.class);
|
||||
String key = input.readContentAsString();
|
||||
AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
|
||||
if (accessCode == null) {
|
||||
logger.debug("bad access code");
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package org.keycloak.services.resources;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -406,7 +405,7 @@ public class TokenService {
|
|||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||
}
|
||||
|
||||
JWSInput input = new JWSInput(code, providers);
|
||||
JWSInput input = new JWSInput(code);
|
||||
boolean verifiedCode = false;
|
||||
try {
|
||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||
|
@ -420,7 +419,7 @@ public class TokenService {
|
|||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||
.build();
|
||||
}
|
||||
String key = input.readContent(String.class);
|
||||
String key = input.readContentAsString();
|
||||
AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
|
||||
if (accessCode == null) {
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
|
@ -457,13 +456,7 @@ public class TokenService {
|
|||
}
|
||||
|
||||
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
|
||||
byte[] tokenBytes = null;
|
||||
try {
|
||||
tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String encodedToken = new JWSBuilder().content(tokenBytes).rsa256(privateKey);
|
||||
String encodedToken = new JWSBuilder().jsonContent(token).rsa256(privateKey);
|
||||
|
||||
return accessTokenResponse(token, encodedToken);
|
||||
}
|
||||
|
@ -589,7 +582,7 @@ public class TokenService {
|
|||
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
||||
|
||||
String code = formData.getFirst("code");
|
||||
JWSInput input = new JWSInput(code, providers);
|
||||
JWSInput input = new JWSInput(code);
|
||||
boolean verifiedCode = false;
|
||||
try {
|
||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||
|
@ -599,7 +592,7 @@ public class TokenService {
|
|||
if (!verifiedCode) {
|
||||
return oauth.forwardToSecurityFailure("Illegal access code.");
|
||||
}
|
||||
String key = input.readContent(String.class);
|
||||
String key = input.readContentAsString();
|
||||
AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key);
|
||||
if (accessCodeEntry == null) {
|
||||
return oauth.forwardToSecurityFailure("Unknown access code.");
|
||||
|
|
|
@ -4,12 +4,12 @@ import io.undertow.servlet.Servlets;
|
|||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.FilterInfo;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.keycloak.SkeletonKeyContextResolver;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.filters.KeycloakSessionServletFilter;
|
||||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
|
@ -65,6 +65,6 @@ public class AbstractKeycloakServerTest {
|
|||
byte[] bytes = os.toByteArray();
|
||||
System.out.println(new String(bytes));
|
||||
|
||||
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
|
||||
return JsonSerialization.readValue(bytes, RealmRepresentation.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-services</artifactId>
|
||||
|
@ -149,11 +154,11 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
<artifactId>resteasy-multipart-provider</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-multipart-provider</artifactId>
|
||||
<artifactId>resteasy-jackson-provider</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
|
|
|
@ -33,10 +33,10 @@ import io.undertow.servlet.Servlets;
|
|||
import io.undertow.servlet.api.DefaultServletConfig;
|
||||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.FilterInfo;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.logging.Logger;
|
||||
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
@ -49,15 +49,11 @@ import org.keycloak.services.managers.RealmManager;
|
|||
import org.keycloak.services.resources.KeycloakApplication;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
@ -100,13 +96,7 @@ public class KeycloakServer {
|
|||
|
||||
private static <T> T loadJson(InputStream is, Class<T> type) {
|
||||
try {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
int c;
|
||||
while ((c = is.read()) != -1) {
|
||||
os.write(c);
|
||||
}
|
||||
byte[] bytes = os.toByteArray();
|
||||
return JsonSerialization.fromBytes(type, bytes);
|
||||
return JsonSerialization.readValue(is, type);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to parse json", e);
|
||||
}
|
||||
|
|
|
@ -30,15 +30,15 @@ import org.apache.http.client.methods.HttpPost;
|
|||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.jboss.resteasy.jose.Base64Url;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.jboss.resteasy.security.PemUtils;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Assert;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.representations.SkeletonKeyScope;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.keycloak.util.Base64Url;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
|
@ -200,7 +200,7 @@ public class OAuthClient {
|
|||
if (scope != null) {
|
||||
try {
|
||||
|
||||
b.queryParam("scope", Base64Url.encode(JsonSerialization.toByteArray(scope, false)));
|
||||
b.queryParam("scope", Base64Url.encode(JsonSerialization.writeValueAsBytes(scope)));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to serialize scope", e);
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ package org.keycloak.testsuite.rule;
|
|||
|
||||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.ServletInfo;
|
||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -93,7 +93,7 @@ public class KeycloakRule extends ExternalResource {
|
|||
os.write(c);
|
||||
}
|
||||
byte[] bytes = os.toByteArray();
|
||||
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
|
||||
return JsonSerialization.readValue(bytes, RealmRepresentation.class);
|
||||
}
|
||||
|
||||
public void configure(KeycloakSetup configurer) {
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-services</artifactId>
|
||||
|
|
Loading…
Reference in a new issue