1 // Copyright 2021 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink.jwt; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 22 import java.time.Instant; 23 import org.junit.Test; 24 import org.junit.runner.RunWith; 25 import org.junit.runners.JUnit4; 26 27 /** Unit tests for VerifiedJwt */ 28 @RunWith(JUnit4.class) 29 public final class VerifiedJwtTest { 30 @Test emptyToken_getMethodsShouldThrow()31 public void emptyToken_getMethodsShouldThrow() throws Exception { 32 VerifiedJwt emptyToken = new VerifiedJwt(RawJwt.newBuilder().withoutExpiration().build()); 33 34 assertThrows(JwtInvalidException.class, emptyToken::getIssuer); 35 assertThrows(JwtInvalidException.class, emptyToken::getSubject); 36 assertThrows(JwtInvalidException.class, emptyToken::getAudiences); 37 assertThrows(JwtInvalidException.class, emptyToken::getJwtId); 38 assertThrows(JwtInvalidException.class, emptyToken::getExpiration); 39 assertThrows(JwtInvalidException.class, emptyToken::getNotBefore); 40 assertThrows(JwtInvalidException.class, emptyToken::getIssuedAt); 41 assertThrows(JwtInvalidException.class, () -> emptyToken.getBooleanClaim("claim")); 42 assertThrows(JwtInvalidException.class, () -> emptyToken.getStringClaim("claim")); 43 assertThrows(JwtInvalidException.class, () -> emptyToken.getNumberClaim("claim")); 44 assertThrows(JwtInvalidException.class, () -> emptyToken.getJsonArrayClaim("claim")); 45 assertThrows(JwtInvalidException.class, () -> emptyToken.getJsonObjectClaim("claim")); 46 } 47 48 @Test emptyToken_hasMethodsShouldReturnFalse()49 public void emptyToken_hasMethodsShouldReturnFalse() throws Exception { 50 RawJwt emptyToken = RawJwt.newBuilder().withoutExpiration().build(); 51 assertThat(emptyToken.hasIssuer()).isFalse(); 52 assertThat(emptyToken.hasSubject()).isFalse(); 53 assertThat(emptyToken.hasAudiences()).isFalse(); 54 assertThat(emptyToken.hasJwtId()).isFalse(); 55 assertThat(emptyToken.hasExpiration()).isFalse(); 56 assertThat(emptyToken.hasNotBefore()).isFalse(); 57 assertThat(emptyToken.hasIssuedAt()).isFalse(); 58 assertThat(emptyToken.hasBooleanClaim("claim")).isFalse(); 59 assertThat(emptyToken.hasNumberClaim("claim")).isFalse(); 60 assertThat(emptyToken.hasStringClaim("claim")).isFalse(); 61 assertThat(emptyToken.hasJsonArrayClaim("claim")).isFalse(); 62 assertThat(emptyToken.hasJsonObjectClaim("claim")).isFalse(); 63 } 64 65 @Test emptyToken_isNullClaimReturnFalse()66 public void emptyToken_isNullClaimReturnFalse() throws Exception { 67 RawJwt emptyToken = RawJwt.newBuilder().withoutExpiration().build(); 68 assertThat(emptyToken.isNullClaim("claim")).isFalse(); 69 } 70 71 @Test getIssuer_success()72 public void getIssuer_success() throws Exception { 73 RawJwt rawToken = RawJwt.newBuilder().setIssuer("foo").withoutExpiration().build(); 74 VerifiedJwt token = new VerifiedJwt(rawToken); 75 76 assertThat(token.hasIssuer()).isTrue(); 77 assertThat(token.getIssuer()).isEqualTo("foo"); 78 } 79 80 @Test getSubject_success()81 public void getSubject_success() throws Exception { 82 RawJwt rawToken = RawJwt.newBuilder().setSubject("foo").withoutExpiration().build(); 83 VerifiedJwt token = new VerifiedJwt(rawToken); 84 85 assertThat(token.hasSubject()).isTrue(); 86 assertThat(token.getSubject()).isEqualTo("foo"); 87 } 88 89 @Test getAudiences_success()90 public void getAudiences_success() throws Exception { 91 RawJwt rawToken = RawJwt.newBuilder().addAudience("foo").withoutExpiration().build(); 92 VerifiedJwt token = new VerifiedJwt(rawToken); 93 94 assertThat(token.hasAudiences()).isTrue(); 95 assertThat(token.getAudiences()).containsExactly("foo"); 96 } 97 98 @Test getMultipleAudiences_success()99 public void getMultipleAudiences_success() throws Exception { 100 RawJwt rawToken = 101 RawJwt.newBuilder().addAudience("foo").addAudience("bar").withoutExpiration().build(); 102 VerifiedJwt token = new VerifiedJwt(rawToken); 103 104 assertThat(token.hasAudiences()).isTrue(); 105 assertThat(token.getAudiences()).containsExactly("foo", "bar"); 106 } 107 108 @Test getJwtId_success()109 public void getJwtId_success() throws Exception { 110 RawJwt rawToken = RawJwt.newBuilder().setJwtId("foo").withoutExpiration().build(); 111 VerifiedJwt token = new VerifiedJwt(rawToken); 112 113 assertThat(token.hasJwtId()).isTrue(); 114 assertThat(token.getJwtId()).isEqualTo("foo"); 115 } 116 117 @Test getExpiration_success()118 public void getExpiration_success() throws Exception { 119 RawJwt rawToken = RawJwt.newBuilder().setExpiration(Instant.ofEpochSecond(1234567)).build(); 120 VerifiedJwt token = new VerifiedJwt(rawToken); 121 122 assertThat(token.hasExpiration()).isTrue(); 123 assertThat(token.getExpiration()).isEqualTo(Instant.ofEpochSecond(1234567)); 124 } 125 126 @Test getNotBefore_success()127 public void getNotBefore_success() throws Exception { 128 RawJwt rawToken = 129 RawJwt.newBuilder() 130 .setNotBefore(Instant.ofEpochSecond(1234567)) 131 .withoutExpiration() 132 .build(); 133 VerifiedJwt token = new VerifiedJwt(rawToken); 134 135 assertThat(token.hasNotBefore()).isTrue(); 136 assertThat(token.getNotBefore()).isEqualTo(Instant.ofEpochSecond(1234567)); 137 } 138 139 @Test getIssuedAt_success()140 public void getIssuedAt_success() throws Exception { 141 RawJwt rawToken = 142 RawJwt.newBuilder().setIssuedAt(Instant.ofEpochSecond(1234567)).withoutExpiration().build(); 143 VerifiedJwt token = new VerifiedJwt(rawToken); 144 145 assertThat(token.hasIssuedAt()).isTrue(); 146 assertThat(token.getIssuedAt()).isEqualTo(Instant.ofEpochSecond(1234567)); 147 } 148 149 @Test getRegisteredClaim_shouldThrow()150 public void getRegisteredClaim_shouldThrow() throws Exception { 151 RawJwt rawToken = 152 RawJwt.newBuilder() 153 .setExpiration(Instant.ofEpochSecond(1234567)) 154 .setIssuer("issuer") 155 .setSubject("subject") 156 .addAudience("audience") 157 .setIssuedAt(Instant.ofEpochSecond(2345678)) 158 .setNotBefore(Instant.ofEpochSecond(3456789)) 159 .setJwtId("id") 160 .build(); 161 VerifiedJwt token = new VerifiedJwt(rawToken); 162 163 assertThrows( 164 IllegalArgumentException.class, () -> token.getNumberClaim("exp")); 165 assertThrows(IllegalArgumentException.class, () -> token.getStringClaim("iss")); 166 assertThrows( 167 IllegalArgumentException.class, () -> token.getStringClaim("sub")); 168 assertThrows( 169 IllegalArgumentException.class, () -> token.getJsonArrayClaim("aud")); 170 assertThrows( 171 IllegalArgumentException.class, () -> token.getNumberClaim("iat")); 172 assertThrows(IllegalArgumentException.class, () -> token.getStringClaim("jti")); 173 assertThrows( 174 IllegalArgumentException.class, () -> token.getNumberClaim("nbf")); 175 } 176 177 @Test getNotRegisteredSimpleClaims_success()178 public void getNotRegisteredSimpleClaims_success() throws Exception { 179 RawJwt rawToken = 180 RawJwt.newBuilder() 181 .addStringClaim("string", "issuer") 182 .addNumberClaim("int", 123) 183 .addBooleanClaim("bool", true) 184 .addNumberClaim("double", 123.456) 185 .withoutExpiration() 186 .build(); 187 VerifiedJwt token = new VerifiedJwt(rawToken); 188 189 assertThat(token.hasBooleanClaim("bool")).isTrue(); 190 assertThat(token.getBooleanClaim("bool")).isTrue(); 191 assertThat(token.hasStringClaim("string")).isTrue(); 192 assertThat(token.getStringClaim("string")).isEqualTo("issuer"); 193 assertThat(token.hasNumberClaim("int")).isTrue(); 194 assertThat(token.getNumberClaim("int")).isEqualTo(123.0); 195 assertThat(token.hasNumberClaim("double")).isTrue(); 196 assertThat(token.getNumberClaim("double")).isEqualTo(123.456); 197 } 198 199 @Test getNullClaim_success()200 public void getNullClaim_success() throws Exception { 201 RawJwt rawToken = 202 RawJwt.newBuilder() 203 .addNullClaim("null_object") 204 .addStringClaim("null_string", "null") 205 .withoutExpiration() 206 .build(); 207 VerifiedJwt token = new VerifiedJwt(rawToken); 208 assertThat(token.hasStringClaim("null_object")).isFalse(); 209 assertThat(token.isNullClaim("null_object")).isTrue(); 210 assertThat(token.hasStringClaim("null_string")).isTrue(); 211 assertThat(token.isNullClaim("null_string")).isFalse(); 212 assertThat(token.hasStringClaim("unknown_claim")).isFalse(); 213 assertThat(token.isNullClaim("unknown_claim")).isFalse(); 214 } 215 216 @Test getNotRegisteredJsonArrayClaim_success()217 public void getNotRegisteredJsonArrayClaim_success() throws Exception { 218 RawJwt rawToken = 219 RawJwt.newBuilder() 220 .setJwtId("id") 221 .addJsonArrayClaim("collection", "[true, 123, 123.456, \"value\", [1,2]]") 222 .withoutExpiration() 223 .build(); 224 VerifiedJwt token = new VerifiedJwt(rawToken); 225 assertThat(token.hasJsonArrayClaim("collection")).isTrue(); 226 assertThat(token.getJsonArrayClaim("collection")) 227 .isEqualTo("[true,123,123.456,\"value\",[1,2]]"); 228 } 229 230 @Test getNotRegisteredJsonObjectClaim_success()231 public void getNotRegisteredJsonObjectClaim_success() throws Exception { 232 RawJwt rawToken = 233 RawJwt.newBuilder() 234 .setJwtId("id") 235 .addJsonObjectClaim("obj", "{\"obj1\": {\"obj2\": {\"42\": [42]}}}") 236 .withoutExpiration() 237 .build(); 238 VerifiedJwt token = new VerifiedJwt(rawToken); 239 assertThat(token.getJwtId()).isEqualTo("id"); 240 assertThat(token.hasJsonObjectClaim("obj")).isTrue(); 241 assertThat(token.getJsonObjectClaim("obj")) 242 .isEqualTo("{\"obj1\":{\"obj2\":{\"42\":[42]}}}"); 243 } 244 245 @Test customClaimNames_success()246 public void customClaimNames_success() throws Exception { 247 RawJwt rawToken = 248 RawJwt.newBuilder() 249 .setIssuer("issuer") 250 .setExpiration(Instant.ofEpochSecond(1234567)) 251 .addStringClaim("string", "value") 252 .addBooleanClaim("boolean", true) 253 .addNumberClaim("number", 123.456) 254 .addNullClaim("nothing") 255 .build(); 256 VerifiedJwt token = new VerifiedJwt(rawToken); 257 assertThat(token.customClaimNames()).containsExactly("string", "boolean", "number", "nothing"); 258 } 259 260 @Test customClaimNames_empty()261 public void customClaimNames_empty() throws Exception { 262 RawJwt rawToken = RawJwt.newBuilder().withoutExpiration().build(); 263 VerifiedJwt token = new VerifiedJwt(rawToken); 264 assertThat(token.customClaimNames()).isEmpty(); 265 } 266 267 @Test toString_success()268 public void toString_success() throws Exception { 269 RawJwt rawToken = 270 RawJwt.newBuilder().setTypeHeader("type").setExpiration(Instant.ofEpochSecond(42)).build(); 271 VerifiedJwt token = new VerifiedJwt(rawToken); 272 assertThat(token.toString()) 273 .isEqualTo("verified{{\"typ\":\"type\"}.{\"exp\":42}}"); 274 } 275 } 276