Skip to content

Commit 085a46f

Browse files
author
Justin Dahmubed
committed
Added Risc token
1 parent 08f9dc0 commit 085a46f

6 files changed

Lines changed: 722 additions & 0 deletions

File tree

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
package com.auth0.jwt.creators;
2+
3+
import com.auth0.jwt.algorithms.Algorithm;
4+
import com.auth0.jwt.exceptions.JWTCreationException;
5+
import com.auth0.jwt.impl.PublicClaims;
6+
import com.auth0.jwt.interfaces.Verification;
7+
import com.auth0.jwt.jwts.JWT;
8+
9+
import java.util.Date;
10+
import java.util.HashMap;
11+
import java.util.HashSet;
12+
import java.util.Set;
13+
14+
/**
15+
* The RiscJwtCreator class holds the sign method to generate a complete Risc JWT (with Signature) from a given Header and Payload content.
16+
*/
17+
public class RiscJwtCreator {
18+
19+
protected JWTCreator.Builder jwt;
20+
protected HashMap<String, Boolean> addedClaims;
21+
protected Set<String> publicClaims;
22+
23+
public RiscJwtCreator() {
24+
jwt = JWT.create();
25+
addedClaims = new HashMap<String, Boolean>() {{
26+
put("Jti", false);
27+
put("Issuer", false);
28+
put("Subject", false);
29+
put("Iat", false);
30+
}};
31+
publicClaims = new HashSet<String>() {{
32+
add(PublicClaims.ISSUER);
33+
add(PublicClaims.SUBJECT);
34+
add(PublicClaims.EXPIRES_AT);
35+
add(PublicClaims.NOT_BEFORE);
36+
add(PublicClaims.ISSUED_AT);
37+
add(PublicClaims.JWT_ID);
38+
add(PublicClaims.AUDIENCE);
39+
}};
40+
}
41+
42+
/**
43+
* Require a specific JWT Id ("jti") claim.
44+
*
45+
* @param jwtId the required Id value
46+
* @return this same Verification instance.
47+
*/
48+
public RiscJwtCreator withJWTId(String jwtId) {
49+
jwt.withJWTId(jwtId);
50+
addedClaims.put("Jti", true);
51+
return this;
52+
}
53+
54+
/**
55+
* Add a specific Issuer ("issuer") claim to the Payload.
56+
* Allows for multiple issuers
57+
*
58+
* @param issuer the Issuer value.
59+
* @return this same Builder instance.
60+
*/
61+
public RiscJwtCreator withIssuer(String... issuer) {
62+
jwt.withIssuer(issuer);
63+
addedClaims.put("Issuer", true);
64+
return this;
65+
}
66+
67+
/**
68+
* Add a specific Subject ("subject") claim to the Payload.
69+
* Allows for multiple subjects
70+
*
71+
* @param subject the Subject value.
72+
* @return this same Builder instance.
73+
*/
74+
public RiscJwtCreator withSubject(String... subject) {
75+
jwt.withSubject(subject);
76+
addedClaims.put("Subject", true);
77+
return this;
78+
}
79+
80+
/**
81+
* Add a specific Audience ("audience") claim to the Payload.
82+
* Allows for multiple audience
83+
*
84+
* @param audience the Audience value.
85+
* @return this same Builder instance.
86+
*/
87+
public RiscJwtCreator withAudience(String... audience) {
88+
jwt.withAudience(audience);
89+
return this;
90+
}
91+
92+
/**
93+
* Add a specific Issued At ("iat") claim to the Payload.
94+
*
95+
* @param iat the Issued At value.
96+
* @return this same Builder instance.
97+
*/
98+
public RiscJwtCreator withIat(Date iat) {
99+
jwt.withIssuedAt(iat);
100+
addedClaims.put("Iat", true);
101+
return this;
102+
}
103+
104+
/**
105+
* Add a specific Expires At ("exp") claim to the Payload.
106+
*
107+
* @param exp the Expires At value.
108+
* @return this same Builder instance.
109+
*/
110+
public RiscJwtCreator withExp(Date exp) {
111+
jwt.withExpiresAt(exp);
112+
return this;
113+
}
114+
115+
/**
116+
* Add a specific Note Before ("nbf") claim to the Payload.
117+
*
118+
* @param nbf the nbf value.
119+
* @return this same Builder instance.
120+
*/
121+
public RiscJwtCreator withNbf(Date nbf) {
122+
jwt.withNotBefore(nbf);
123+
return this;
124+
}
125+
126+
/**
127+
* Require a specific Claim value.
128+
*
129+
* @param name the Claim's name.
130+
* @param value the Claim's value.
131+
* @return this same Verification instance.
132+
* @throws IllegalArgumentException if the name is null.
133+
*/
134+
public RiscJwtCreator withNonStandardClaim(String name, String value) {
135+
jwt.withNonStandardClaim(name, value);
136+
return this;
137+
}
138+
139+
/**
140+
* Add a custom Claim value.
141+
*
142+
* @param name the Claim's name.
143+
* @param value the Claim's value.
144+
* @return this same Builder instance.
145+
* @throws IllegalArgumentException if the name is null.
146+
*/
147+
public RiscJwtCreator withNonStandardClaim(String name, Boolean value) throws IllegalArgumentException {
148+
jwt.withNonStandardClaim(name, value);
149+
return this;
150+
}
151+
152+
/**
153+
* Add a custom Claim value.
154+
*
155+
* @param name the Claim's name.
156+
* @param value the Claim's value.
157+
* @return this same Builder instance.
158+
* @throws IllegalArgumentException if the name is null.
159+
*/
160+
public RiscJwtCreator withNonStandardClaim(String name, Integer value) throws IllegalArgumentException {
161+
jwt.withNonStandardClaim(name, value);
162+
return this;
163+
}
164+
165+
/**
166+
* Add a custom Claim value.
167+
*
168+
* @param name the Claim's name.
169+
* @param value the Claim's value.
170+
* @return this same Builder instance.
171+
* @throws IllegalArgumentException if the name is null.
172+
*/
173+
public RiscJwtCreator withNonStandardClaim(String name, Long value) throws IllegalArgumentException {
174+
jwt.withNonStandardClaim(name, value);
175+
return this;
176+
}
177+
178+
/**
179+
* Add a custom Claim value.
180+
*
181+
* @param name the Claim's name.
182+
* @param value the Claim's value.
183+
* @return this same Builder instance.
184+
* @throws IllegalArgumentException if the name is null.
185+
*/
186+
public RiscJwtCreator withNonStandardClaim(String name, Double value) throws IllegalArgumentException {
187+
jwt.withNonStandardClaim(name, value);
188+
return this;
189+
}
190+
191+
/**
192+
* Add a custom Claim value.
193+
*
194+
* @param name the Claim's name.
195+
* @param value the Claim's value.
196+
* @return this same Builder instance.
197+
* @throws IllegalArgumentException if the name is null.
198+
*/
199+
public RiscJwtCreator withNonStandardClaim(String name, Date value) throws IllegalArgumentException {
200+
jwt.withNonStandardClaim(name, value);
201+
return this;
202+
}
203+
204+
/**
205+
* Require a specific Array Claim to contain at least the given items.
206+
*
207+
* @param name the Claim's name.
208+
* @param items the items the Claim must contain.
209+
* @return this same Verification instance.
210+
* @throws IllegalArgumentException if the name is null.
211+
*/
212+
public RiscJwtCreator withArrayClaim(String name, String... items) throws IllegalArgumentException {
213+
jwt.withArrayClaim(name, items);
214+
if(publicClaims.contains(name))
215+
addedClaims.put(name, true);
216+
return this;
217+
}
218+
219+
/**
220+
* Developer explicitly specifies whether they want to accept
221+
* NONE algorithms or not.
222+
*
223+
* @param isNoneAlgorithmAllowed
224+
* @return
225+
*/
226+
public RiscJwtCreator setIsNoneAlgorithmAllowed(boolean isNoneAlgorithmAllowed) {
227+
jwt.setIsNoneAlgorithmAllowed(isNoneAlgorithmAllowed);
228+
return this;
229+
}
230+
231+
/**
232+
* Creates a new JWT and signs it with the given algorithm.
233+
*
234+
* @param algorithm used to sign the JWT
235+
* @return a new JWT token
236+
* @throws IllegalAccessException if the developer didn't want NONE algorithm to be allowed and it was passed in
237+
* @throws IllegalArgumentException if the provided algorithm is null.
238+
* @throws JWTCreationException if the claims could not be converted to a valid JSON or there was a problem with the signing key.
239+
*/
240+
public String sign(Algorithm algorithm) throws Exception {
241+
if(!jwt.getIsNoneAlgorithmAllowed() && algorithm.equals(Algorithm.none())) {
242+
throw new IllegalAccessException("None algorithm isn't allowed");
243+
}
244+
String JWS = jwt.sign(algorithm);
245+
verifyClaims();
246+
return JWS;
247+
}
248+
249+
/**
250+
* Verifies that all the standard claims were provided
251+
* @throws Exception if all the standard claims weren't provided
252+
*/
253+
private void verifyClaims() throws Exception {
254+
for(String claim : addedClaims.keySet())
255+
if(!addedClaims.get(claim))
256+
throw new Exception("Standard claim: " + claim + " has not been set");
257+
}
258+
259+
public static RiscJwtCreator build() {
260+
return new RiscJwtCreator();
261+
}
262+
}

lib/src/main/java/com/auth0/jwt/interfaces/Verification.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,8 @@ Verification createVerifierForImplicit(List<String> issuer,
5555
Verification createVerifierForAccess(List<String> issuer,
5656
List<String> audience, long expLeeway, long iatLeeway);
5757

58+
Verification createVerifierForRisc(String jti, List<String> issuer,
59+
List<String> audience, long iatLeeway, long expLeeway, long nbf);
60+
5861
JWT build();
5962
}

lib/src/main/java/com/auth0/jwt/jwts/JWT.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ public Verification withNbf(long nbf) {
102102
throw new UnsupportedOperationException("you shouldn't be calling this method");
103103
}
104104

105+
@Override
106+
public Verification createVerifierForRisc(String jti, List<String> issuer,
107+
List<String> audience, long iatLeeway, long expLeeway, long nbf) {
108+
throw new UnsupportedOperationException("you shouldn't be calling this method");
109+
}
110+
105111
@Override
106112
public Verification createVerifierForScoped(String scope, List<String> issuer, List<String> audience, long expLeeway, long iatLeeway) {
107113
throw new UnsupportedOperationException("you shouldn't be calling this method");
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.auth0.jwt.jwts;
2+
3+
import com.auth0.jwt.ClockImpl;
4+
import com.auth0.jwt.algorithms.Algorithm;
5+
import com.auth0.jwt.interfaces.Clock;
6+
import com.auth0.jwt.interfaces.Verification;
7+
8+
import java.util.List;
9+
10+
public class RiscJWT extends JWT.BaseVerification implements Verification {
11+
12+
RiscJWT(Algorithm algorithm) throws IllegalArgumentException {
13+
super(algorithm);
14+
}
15+
16+
/**
17+
* Create Verification object for verification purposes
18+
* @param jti
19+
* @param issuer
20+
* @param audience
21+
* @param iatLeeway
22+
* @param expLeeway
23+
* @return
24+
*/
25+
public Verification createVerifierForRisc(String jti, List<String> issuer,
26+
List<String> audience, long iatLeeway, long expLeeway, long nbf) {
27+
Verification verification = withJWTId(jti).withIssuer(issuer.toArray(new String[issuer.size()])).acceptIssuedAt(iatLeeway);
28+
29+
if(audience != null && !audience.isEmpty()) {
30+
verification.withAudience(audience.toArray(new String[audience.size()]));
31+
}
32+
33+
if(nbf >= 0) {
34+
verification.acceptNotBefore(iatLeeway);
35+
}
36+
37+
if(expLeeway >= 0) {
38+
verification.acceptExpiresAt(expLeeway);
39+
}
40+
41+
return verification;
42+
}
43+
44+
/**
45+
* Returns a {Verification} to be used to validate token signature.
46+
*
47+
* @param algorithm that will be used to verify the token's signature.
48+
* @return Verification
49+
* @throws IllegalArgumentException if the provided algorithm is null.
50+
*/
51+
public static Verification require(Algorithm algorithm) {
52+
return RiscJWT.init(algorithm);
53+
}
54+
55+
/**
56+
* Initialize a Verification instance using the given Algorithm.
57+
*
58+
* @param algorithm the Algorithm to use on the JWT verification.
59+
* @return a RiscJWT instance to configure.
60+
* @throws IllegalArgumentException if the provided algorithm is null.
61+
*/
62+
static Verification init(Algorithm algorithm) throws IllegalArgumentException {
63+
return new RiscJWT(algorithm);
64+
}
65+
66+
/**
67+
* Creates a new and reusable instance of the JWT with the configuration already provided.
68+
*
69+
* @return a new JWT instance.
70+
*/
71+
@Override
72+
public JWT build() {
73+
return this.build(new ClockImpl());
74+
}
75+
76+
/**
77+
* Creates a new and reusable instance of the JWT the configuration already provided.
78+
* ONLY FOR TEST PURPOSES.
79+
*
80+
* @param clock the instance that will handle the current time.
81+
* @return a new JWT instance with a custom Clock.
82+
*/
83+
public JWT build(Clock clock) {
84+
addLeewayToDateClaims();
85+
return new JWT(algorithm, claims, clock);
86+
}
87+
}

lib/src/test/java/com/auth0/jwt/JWTTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ public void testWithNbf() {
3333
JWT.require(Algorithm.none()).withNbf(5);
3434
}
3535

36+
@Test
37+
public void testCreateVerifierForRisc() {
38+
thrown.expect(UnsupportedOperationException.class);
39+
thrown.expectMessage("you shouldn't be calling this method");
40+
JWT.require(Algorithm.none()).createVerifierForRisc(null, null, null, 5, 5, 5);
41+
}
42+
3643
@Test
3744
public void testCreateVerifierForScoped() {
3845
thrown.expect(UnsupportedOperationException.class);

0 commit comments

Comments
 (0)