2727import java .net .URI ;
2828import java .net .URISyntaxException ;
2929import java .net .URL ;
30+ import java .util .Base64 ;
3031import java .util .Collections ;
3132import java .util .HashMap ;
33+ import java .util .concurrent .ExecutionException ;
3234
3335@ ExtendWith (MockitoExtension .class )
3436@ TestInstance (TestInstance .Lifecycle .PER_CLASS )
@@ -294,4 +296,44 @@ void testExecuteOAuth_Failure() throws SerializeException,
294296
295297 assertThrows (MsalException .class , request ::executeTokenRequest );
296298 }
299+
300+ @ Test
301+ void testBase64UrlEncoding () throws MalformedURLException , ExecutionException , InterruptedException {
302+ DefaultHttpClient httpClientMock = mock (DefaultHttpClient .class );
303+ ConfidentialClientApplication cca =
304+ ConfidentialClientApplication .builder ("clientId" , ClientCredentialFactory .createFromSecret ("password" ))
305+ .authority ("https://login.microsoftonline.com/tenant/" )
306+ .instanceDiscovery (false )
307+ .validateAuthority (false )
308+ .httpClient (httpClientMock )
309+ .build ();
310+
311+ //ID token payloads are parsed to get certain info to create Account and AccountCacheEntity objects, and the library must decode them using a Base64URL decoder.
312+ HashMap <String , String > tokenParameters = new HashMap <>();
313+ tokenParameters .put ("preferred_username" , "~nameWith~specialChars" );
314+ String encodedIDToken = TestHelper .createIdToken (tokenParameters );
315+ try {
316+ //TestHelper.createIdToken() should use Base64URL encoding, so first we prove that the encoded token it produces cannot be decoded with Base64 decoder
317+ Base64 .getDecoder ().decode (encodedIDToken .split ("\\ ." )[1 ]);
318+
319+ fail ("IllegalArgumentException was expected but not thrown." );
320+ } catch (IllegalArgumentException e ) {
321+ //Encoded token should have some "-" characters in it
322+ assertTrue (e .getMessage ().contains ("Illegal base64 character 2d" ));
323+ }
324+
325+ //Now, send that encoded token through the library's token request flow, which will decode it using a Base64URL decoder
326+ HashMap <String , String > responseParameters = new HashMap <>();
327+ responseParameters .put ("id_token" , encodedIDToken );
328+ responseParameters .put ("access_token" , "token" );
329+ TestHelper .createTokenRequestMock (httpClientMock , TestHelper .getSuccessfulTokenResponse (responseParameters ), 200 );
330+
331+ OnBehalfOfParameters parameters = OnBehalfOfParameters .builder (Collections .singleton ("someScopes" ), new UserAssertion (TestHelper .signedAssertion )).build ();
332+ IAuthenticationResult result = cca .acquireToken (parameters ).get ();
333+
334+ //Ensure that the name was successfully parsed out of the encoded ID token
335+ assertNotNull (result .idToken ());
336+ assertNotNull (result .account ());
337+ assertEquals ("~nameWith~specialChars" , result .account ().username ());
338+ }
297339}
0 commit comments