1 package com.atlassian.asap.service.core.impl; 2 3 import com.atlassian.asap.api.Jwt; 4 import com.atlassian.asap.api.client.http.AuthorizationHeaderGenerator; 5 import com.atlassian.asap.api.exception.CannotRetrieveKeyException; 6 import com.atlassian.asap.api.exception.InvalidTokenException; 7 import com.atlassian.asap.core.exception.MissingRequiredClaimException; 8 import com.atlassian.asap.service.core.spi.AsapConfiguration; 9 import org.junit.Before; 10 import org.junit.Rule; 11 import org.junit.Test; 12 import org.junit.rules.ExpectedException; 13 import org.mockito.ArgumentCaptor; 14 import org.mockito.Captor; 15 import org.mockito.InjectMocks; 16 import org.mockito.Mock; 17 import org.mockito.junit.MockitoJUnit; 18 import org.mockito.junit.MockitoRule; 19 20 import javax.json.Json; 21 import javax.json.JsonObject; 22 import javax.json.JsonValue; 23 import java.time.Duration; 24 import java.util.Optional; 25 26 import static com.atlassian.asap.service.core.impl.JwtMatcher.jwtMatcher; 27 import static org.hamcrest.Matchers.endsWith; 28 import static org.hamcrest.Matchers.is; 29 import static org.junit.Assert.assertThat; 30 import static org.mockito.Mockito.when; 31 32 @SuppressWarnings("NullableProblems") 33 public class AuthorizationBuilderImplTest { 34 private static final String ISSUER = "harry"; 35 private static final String KEY_ID = "harry/key"; 36 private static final String AUDIENCE1 = "hogwarts"; 37 private static final String AUDIENCE2 = "dursleys"; 38 private static final String SUBJECT = "ron"; 39 private static final String TOKEN = "token"; 40 41 @Rule 42 public final MockitoRule mockitoRule = MockitoJUnit.rule(); 43 @Rule 44 public final ExpectedException thrown = ExpectedException.none(); 45 46 @Mock 47 private AsapConfiguration config; 48 @Mock 49 private AuthorizationHeaderGenerator generator; 50 @Captor 51 private ArgumentCaptor<Jwt> jwtCaptor; 52 53 @InjectMocks 54 private AuthorizationBuilderImpl builder; 55 56 @Before 57 public void setUp() throws CannotRetrieveKeyException, InvalidTokenException { 58 when(config.issuer()).thenReturn(ISSUER); 59 when(config.keyId()).thenReturn(KEY_ID); 60 when(config.audience()).thenReturn(AUDIENCE1); 61 when(generator.generateAuthorizationHeader(jwtCaptor.capture())).thenReturn(TOKEN); 62 } 63 64 @Test 65 public void audienceMayNotBeEmpty() throws Exception { 66 thrown.expect(MissingRequiredClaimException.class); 67 thrown.expectMessage(endsWith(": aud")); 68 builder.build(); 69 } 70 71 @Test 72 public void defaultsWithSingleAudience() throws Exception { 73 assertThat(builder.audience(AUDIENCE1).build(), is(TOKEN)); 74 assertThat(jwtCaptor.getValue(), jwtMatcher() 75 .issuer(ISSUER) 76 .keyId(KEY_ID) 77 .subject(Optional.empty()) 78 .audience(AUDIENCE1)); 79 } 80 81 @Test 82 public void withModifiedValues() throws Exception { 83 final Duration duration = Duration.ofSeconds(42L); 84 85 assertThat(builder.audience(AUDIENCE1, AUDIENCE2) 86 .subject(Optional.of(SUBJECT)) 87 .expiration(Optional.of(duration)) 88 .build(), is(TOKEN)); 89 90 assertThat(jwtCaptor.getValue(), jwtMatcher() 91 .issuer(ISSUER) 92 .keyId(KEY_ID) 93 .subject(Optional.of(SUBJECT)) 94 .expiration(duration) 95 .audience(AUDIENCE1, AUDIENCE2)); 96 } 97 98 @Test 99 public void withCustomClaims() throws Exception { 100 final JsonObject nestedObject = Json.createObjectBuilder() 101 .add("nifty", JsonValue.NULL) 102 .build(); 103 final JsonObject customClaims = Json.createObjectBuilder() 104 .add("hello", "world") 105 .add("number", 42) 106 .add("nested", nestedObject) 107 .build(); 108 109 assertThat(builder.audience(AUDIENCE1) 110 .customClaims(Optional.of(customClaims)) 111 .build(), is(TOKEN)); 112 assertThat(jwtCaptor.getValue(), jwtMatcher() 113 .issuer(ISSUER) 114 .keyId(KEY_ID) 115 .customClaim("hello", customClaims.getJsonString("hello")) 116 .customClaim("number", customClaims.getJsonNumber("number")) 117 .customClaim("nested", nestedObject)); 118 } 119 }