33
44package com .microsoft .aad .msal4j ;
55
6+ import java .util .Collections ;
7+ import java .util .HashMap ;
8+
69import org .junit .jupiter .api .Test ;
710import org .junit .jupiter .api .TestInstance ;
11+ import static org .junit .jupiter .api .Assertions .assertEquals ;
12+ import static org .junit .jupiter .api .Assertions .assertNotEquals ;
813import static org .junit .jupiter .api .Assertions .assertThrows ;
914import static org .junit .jupiter .api .Assertions .assertTrue ;
15+ import static org .mockito .ArgumentMatchers .any ;
16+ import static org .mockito .Mockito .mock ;
17+ import static org .mockito .Mockito .times ;
18+ import static org .mockito .Mockito .verify ;
19+ import static org .mockito .Mockito .when ;
1020
1121@ TestInstance (TestInstance .Lifecycle .PER_CLASS )
1222class ClientCredentialTest {
@@ -32,4 +42,69 @@ void testSecretNullAndEmpty() {
3242
3343 assertTrue (ex .getMessage ().contains ("clientSecret is null or empty" ));
3444 }
45+
46+ @ Test
47+ void OnBehalfOf_InternalCacheLookup_Success () throws Exception {
48+ DefaultHttpClient httpClientMock = mock (DefaultHttpClient .class );
49+
50+ when (httpClientMock .send (any (HttpRequest .class ))).thenReturn (TestHelper .expectedResponse (200 , TestHelper .getSuccessfulTokenResponse (new HashMap <>())));
51+
52+ ConfidentialClientApplication cca =
53+ ConfidentialClientApplication .builder ("clientId" , ClientCredentialFactory .createFromSecret ("password" ))
54+ .authority ("https://login.microsoftonline.com/tenant/" )
55+ .instanceDiscovery (false )
56+ .validateAuthority (false )
57+ .httpClient (httpClientMock )
58+ .build ();
59+
60+ ClientCredentialParameters parameters = ClientCredentialParameters .builder (Collections .singleton ("scopes" )).build ();
61+
62+ IAuthenticationResult result = cca .acquireToken (parameters ).get ();
63+ IAuthenticationResult result2 = cca .acquireToken (parameters ).get ();
64+
65+ //OBO flow should perform an internal cache lookup, so similar parameters should only cause one HTTP client call
66+ assertEquals (result .accessToken (), result2 .accessToken ());
67+ verify (httpClientMock , times (1 )).send (any ());
68+ }
69+
70+ @ Test
71+ void OnBehalfOf_TenantOverride () throws Exception {
72+ DefaultHttpClient httpClientMock = mock (DefaultHttpClient .class );
73+
74+ ConfidentialClientApplication cca =
75+ ConfidentialClientApplication .builder ("clientId" , ClientCredentialFactory .createFromSecret ("password" ))
76+ .authority ("https://login.microsoftonline.com/tenant" )
77+ .instanceDiscovery (false )
78+ .validateAuthority (false )
79+ .httpClient (httpClientMock )
80+ .build ();
81+
82+ HashMap <String , String > tokenResponseValues = new HashMap <>();
83+ tokenResponseValues .put ("access_token" , "accessTokenFirstCall" );
84+
85+ when (httpClientMock .send (any (HttpRequest .class ))).thenReturn (TestHelper .expectedResponse (200 , TestHelper .getSuccessfulTokenResponse (tokenResponseValues )));
86+ ClientCredentialParameters parameters = ClientCredentialParameters .builder (Collections .singleton ("scopes" )).build ();
87+
88+ //The two acquireToken calls have the same parameters...
89+ IAuthenticationResult resultAppLevelTenant = cca .acquireToken (parameters ).get ();
90+ IAuthenticationResult resultAppLevelTenantCached = cca .acquireToken (parameters ).get ();
91+ //...so only one token should be added to the cache, and the mocked HTTP client's "send" method should only have been called once
92+ assertEquals (1 , cca .tokenCache .accessTokens .size ());
93+ assertEquals (resultAppLevelTenant .accessToken (), resultAppLevelTenantCached .accessToken ());
94+ verify (httpClientMock , times (1 )).send (any ());
95+
96+ tokenResponseValues .put ("access_token" , "accessTokenSecondCall" );
97+
98+ when (httpClientMock .send (any (HttpRequest .class ))).thenReturn (TestHelper .expectedResponse (200 , TestHelper .getSuccessfulTokenResponse (tokenResponseValues )));
99+ parameters = ClientCredentialParameters .builder (Collections .singleton ("scopes" )).tenant ("otherTenant" ).build ();
100+
101+ //Overriding the tenant parameter in the request should lead to a new token call being made...
102+ IAuthenticationResult resultRequestLevelTenant = cca .acquireToken (parameters ).get ();
103+ IAuthenticationResult resultRequestLevelTenantCached = cca .acquireToken (parameters ).get ();
104+ //...which should be different from the original token, and thus the cache should have two tokens created from two HTTP calls
105+ assertEquals (2 , cca .tokenCache .accessTokens .size ());
106+ assertEquals (resultRequestLevelTenant .accessToken (), resultRequestLevelTenantCached .accessToken ());
107+ assertNotEquals (resultAppLevelTenant .accessToken (), resultRequestLevelTenant .accessToken ());
108+ verify (httpClientMock , times (2 )).send (any ());
109+ }
35110}
0 commit comments