Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 69 additions & 66 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,66 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>edu.uoc.elc.lti</groupId>
<artifactId>lti-1.3-jwt</artifactId>
<version>0.0.2</version>
<packaging>jar</packaging>

<name>lti-1.3-jwt</name>
<description>Library with JWT implementations of LTI's JWT interfaces</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>edu.uoc.elc.lti</groupId>
<artifactId>lti-1.3-core</artifactId>
<version>0.0.2</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
<version>0.6.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>edu.uoc.elc.lti</groupId>
<artifactId>lti-1.3-jwt</artifactId>
<version>0.0.2</version>
<packaging>jar</packaging>

<name>lti-1.3-jwt</name>
<description>Library with JWT implementations of LTI's JWT interfaces</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>edu.uoc.elc.lti</groupId>
<artifactId>lti-1.3-core</artifactId>
<version>0.0.2</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>jwks-rsa</artifactId>
<version>0.6.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
119 changes: 60 additions & 59 deletions src/main/java/edu/uoc/lti/jwt/AlgorithmFactory.java
Original file line number Diff line number Diff line change
@@ -1,59 +1,60 @@
package edu.uoc.lti.jwt;

import lombok.Getter;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;

import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
* @author [email protected]
*/
public class AlgorithmFactory {
private final RSAPublicKey publicKey;
@Getter
private final RSAPrivateKey privateKey;

public AlgorithmFactory(String publicKey, String privateKey) {
KeyFactory kf;
try {
kf = KeyFactory.getInstance("RSA");
byte[] encodedPb = Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec keySpecPb = new X509EncodedKeySpec(encodedPb);
this.publicKey = (RSAPublicKey) kf.generatePublic(keySpecPb);

DerInputStream derReader = new DerInputStream(Base64.getDecoder().decode(privateKey));

DerValue[] seq = derReader.getSequence(0);

if (seq.length < 9) {
throw new GeneralSecurityException("Could not parse a PKCS1 private key.");
}

// skip version seq[0];
BigInteger modulus = seq[1].getBigInteger();
BigInteger publicExp = seq[2].getBigInteger();
BigInteger privateExp = seq[3].getBigInteger();
BigInteger prime1 = seq[4].getBigInteger();
BigInteger prime2 = seq[5].getBigInteger();
BigInteger exp1 = seq[6].getBigInteger();
BigInteger exp2 = seq[7].getBigInteger();
BigInteger crtCoef = seq[8].getBigInteger();

RSAPrivateCrtKeySpec keySpecPv = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);

this.privateKey = (RSAPrivateKey) kf.generatePrivate(keySpecPv);

} catch (GeneralSecurityException | IOException e) {
throw new BadToolProviderConfigurationException(e);
}
}
}
package edu.uoc.lti.jwt;

import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import lombok.Getter;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;

/**
* @author [email protected]
*/
@Getter
public class AlgorithmFactory {
private final RSAPublicKey publicKey;
private final RSAPrivateKey privateKey;

public AlgorithmFactory(String publicKey, String privateKey) {
KeyFactory kf;
try {
kf = KeyFactory.getInstance("RSA");
byte[] encodedPb = Base64.getDecoder().decode(publicKey);
X509EncodedKeySpec keySpecPb = new X509EncodedKeySpec(encodedPb);
this.publicKey = (RSAPublicKey) kf.generatePublic(keySpecPb);

DerInputStream derReader = new DerInputStream(Base64.getDecoder().decode(privateKey));

DerValue[] seq = derReader.getSequence(0);

if (seq.length < 9) {
throw new GeneralSecurityException("Could not parse a PKCS1 private key.");
}

// skip version seq[0];
BigInteger modulus = seq[1].getBigInteger();
BigInteger publicExp = seq[2].getBigInteger();
BigInteger privateExp = seq[3].getBigInteger();
BigInteger prime1 = seq[4].getBigInteger();
BigInteger prime2 = seq[5].getBigInteger();
BigInteger exp1 = seq[6].getBigInteger();
BigInteger exp2 = seq[7].getBigInteger();
BigInteger crtCoef = seq[8].getBigInteger();

RSAPrivateCrtKeySpec keySpecPv = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2,
exp1, exp2, crtCoef);

this.privateKey = (RSAPrivateKey) kf.generatePrivate(keySpecPv);

} catch (GeneralSecurityException | IOException e) {
throw new BadToolProviderConfigurationException(e);
}
}
}
87 changes: 44 additions & 43 deletions src/main/java/edu/uoc/lti/jwt/LtiSigningKeyResolver.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
package edu.uoc.lti.jwt;

import com.auth0.jwk.Jwk;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.SigningKeyResolverAdapter;
import lombok.RequiredArgsConstructor;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.Key;

/**
* @author [email protected]
*/
@RequiredArgsConstructor
public class LtiSigningKeyResolver extends SigningKeyResolverAdapter {
private final String keysetUrl;

@Override
public Key resolveSigningKey(JwsHeader header, Claims claims) {
String keyId = header.getKeyId();

if (keyId == null) {
return null;
}

Key key = null;
try {
JwkProvider provider = new UrlJwkProvider(new URL(keysetUrl));
Jwk jwk = provider.get(keyId);
key = jwk.getPublicKey();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (JwkException e) {
e.printStackTrace();
}
return key;
}
}
package edu.uoc.lti.jwt;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.Key;

import com.auth0.jwk.Jwk;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwsHeader;
import io.jsonwebtoken.SigningKeyResolverAdapter;
import lombok.RequiredArgsConstructor;
import lombok.extern.java.Log;

/**
* @author [email protected]
*/
@Log
@RequiredArgsConstructor
public class LtiSigningKeyResolver extends SigningKeyResolverAdapter {
private final String keysetUrl;

@Override
public Key resolveSigningKey(JwsHeader header, Claims claims) {
String keyId = header.getKeyId();

if (keyId == null) {
return null;
}

Key key = null;
try {
JwkProvider provider = new UrlJwkProvider(new URL(keysetUrl));
Jwk jwk = provider.get(keyId);
key = jwk.getPublicKey();
} catch (MalformedURLException | JwkException e) {
log.warning("Signing key cannot be resolved: " + e.getMessage());
}
return key;
}
}
4 changes: 2 additions & 2 deletions src/main/java/edu/uoc/lti/jwt/claims/JWSClaimAccessor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package edu.uoc.lti.jwt.claims;

import java.util.Date;

import com.fasterxml.jackson.databind.ObjectMapper;

import edu.uoc.lti.claims.ClaimAccessor;
Expand All @@ -9,8 +11,6 @@
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;

import java.util.Date;

/**
* @author [email protected]
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package edu.uoc.lti.jwt.client;

import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor;

import java.util.Date;
import java.util.UUID;

import edu.uoc.lti.clientcredentials.ClientCredentialsRequest;
import edu.uoc.lti.clientcredentials.ClientCredentialsTokenBuilder;
import edu.uoc.lti.jwt.AlgorithmFactory;
import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor;

/**
* @author [email protected]
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/edu/uoc/lti/jwt/deeplink/JWSTokenBuilder.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package edu.uoc.lti.jwt.deeplink;

import java.util.Date;

import edu.uoc.lti.ResponseMessageTypeEnum;
import edu.uoc.lti.claims.ClaimsEnum;
import edu.uoc.lti.deeplink.DeepLinkingResponse;
import edu.uoc.lti.deeplink.DeepLinkingTokenBuilder;
import edu.uoc.lti.jwt.AlgorithmFactory;
import edu.uoc.lti.ResponseMessageTypeEnum;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor;

import java.util.Date;

/**
* @author [email protected]
*/
Expand Down