Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ExecutionException;

import static com.microsoft.aad.msal4j.TestConstants.KEYVAULT_DEFAULT_SCOPE;
Expand Down Expand Up @@ -178,9 +175,12 @@ public void acquireTokenSilent_ConfidentialClient_acquireTokenSilent(String envi
cfg = new Config(environment);

IConfidentialClientApplication cca = getConfidentialClientApplications();

//test that adding extra query parameters does not break the flow
Map<String, String> extraParameters = new HashMap<>();
extraParameters.put("test","test");
IAuthenticationResult result = cca.acquireToken(ClientCredentialParameters
.builder(Collections.singleton(cfg.graphDefaultScope()))
.extraQueryParameters(extraParameters)
.build())
.get();

Expand All @@ -191,6 +191,7 @@ public void acquireTokenSilent_ConfidentialClient_acquireTokenSilent(String envi

result = cca.acquireTokenSilently(SilentParameters
.builder(Collections.singleton(cfg.graphDefaultScope()))
.extraQueryParameters(extraParameters)
.build())
.get();

Expand Down Expand Up @@ -401,10 +402,13 @@ private IAuthenticationResult acquireTokenSilently(IPublicClientApplication pca,
}

private IAuthenticationResult acquireTokenUsernamePassword(User user, IPublicClientApplication pca, String scope) throws InterruptedException, ExecutionException {
Map<String, String> map = new HashMap<>();
map.put("test","test");
return pca.acquireToken(UserNamePasswordParameters.
builder(Collections.singleton(scope),
user.getUpn(),
user.getPassword().toCharArray())
.extraQueryParameters(map)
.build())
.get();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ private IAuthenticationResult acquireTokenInteractiveB2C(ConfidentialClientAppli
result = cca.acquireToken(AuthorizationCodeParameters
.builder(authCode, new URI(TestConstants.LOCALHOST + httpListener.port()))
.scopes(Collections.singleton(TestConstants.B2C_LAB_SCOPE))
.extraQueryParameters(new HashMap<>())
.build())
.get();
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Function;

import static com.microsoft.aad.msal4j.TestConstants.KEYVAULT_DEFAULT_SCOPE;
import static org.easymock.EasyMock.*;
Expand Down Expand Up @@ -261,6 +260,8 @@ public void testClientAssertion_acquireToken() throws Exception{
Assert.assertTrue(body.contains("client_assertion_type=" + URLEncoder.encode(JWTAuthentication.CLIENT_ASSERTION_TYPE, "utf-8")));
Assert.assertTrue(body.contains("scope=" + URLEncoder.encode("openid profile offline_access " + scope, "utf-8")));
Assert.assertTrue(body.contains("client_id=" + TestConfiguration.AAD_CLIENT_ID));
Assert.assertTrue(body.contains("test=test"));
Assert.assertTrue(body.contains("id_token_hint=token_hint_value"));
}

private ServiceBundle mockedServiceBundle(IHttpClient httpClientMock) {
Expand All @@ -274,7 +275,15 @@ private ServiceBundle mockedServiceBundle(IHttpClient httpClientMock) {
private ClientCredentialRequest getClientCredentialRequest(ConfidentialClientApplication app, String scope) {
Set<String> scopes = new HashSet<>();
scopes.add(scope);
ClientCredentialParameters clientCredentials = ClientCredentialParameters.builder(scopes).tenant(IdToken.TENANT_IDENTIFIER).build();

Map<String, String> extraQueryParameters = new HashMap<>();
extraQueryParameters.put("id_token_hint", "token_hint_value");
extraQueryParameters.put("test", "test");

ClientCredentialParameters clientCredentials = ClientCredentialParameters.builder(scopes)
.tenant(IdToken.TENANT_IDENTIFIER)
.extraQueryParameters(extraQueryParameters)
.build();
RequestContext requestContext = new RequestContext(
app,
PublicApi.ACQUIRE_TOKEN_FOR_CLIENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.testng.annotations.Test;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class TokenCacheIT {
Expand All @@ -32,10 +34,14 @@ public void singleAccountInCache_RemoveAccountTest() throws Exception {
// Check that cache is empty
Assert.assertEquals(pca.getAccounts().join().size(), 0);

Map<String, String> extraQueryParameters = new HashMap<>();
extraQueryParameters.put("test", "test");

pca.acquireToken(UserNamePasswordParameters.
builder(Collections.singleton(TestConstants.GRAPH_DEFAULT_SCOPE),
user.getUpn(),
user.getPassword().toCharArray())
.extraQueryParameters(extraQueryParameters)
.build())
.get();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public class AuthorizationCodeParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional query parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import lombok.Getter;
import lombok.NonNull;
import lombok.experimental.Accessors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.MalformedURLException;
import java.net.URL;
Expand Down Expand Up @@ -37,8 +39,12 @@ public class AuthorizationRequestUrlParameters {
//Unlike other prompts (which are sent as query parameters), admin consent has its own endpoint format
private static final String ADMIN_CONSENT_ENDPOINT = "https://login.microsoftonline.com/{tenant}/adminconsent";

Map<String, String> extraQueryParameters;

Map<String, List<String>> requestParameters = new HashMap<>();

Logger log = LoggerFactory.getLogger(AuthorizationRequestUrlParameters.class);

public static Builder builder(String redirectUri,
Set<String> scopes) {

Expand Down Expand Up @@ -152,6 +158,18 @@ private AuthorizationRequestUrlParameters(Builder builder) {
this.instanceAware = builder.instanceAware;
requestParameters.put("instance_aware", Collections.singletonList(String.valueOf(instanceAware)));
}

if(null != builder.extraQueryParameters && !builder.extraQueryParameters.isEmpty()){
this.extraQueryParameters = builder.extraQueryParameters;
for(Map.Entry<String, String> entry: this.extraQueryParameters.entrySet()){
String key = entry.getKey();
String value = entry.getValue();
if(requestParameters.containsKey(key)){
log.warn("A query parameter {} has been provided with values multiple times.", key);
}
requestParameters.put(key, Collections.singletonList(value));
}
}
}

URL createAuthorizationURL(Authority authority,
Expand Down Expand Up @@ -194,6 +212,7 @@ public static class Builder {
private Prompt prompt;
private String correlationId;
private boolean instanceAware;
private Map<String, String> extraQueryParameters;

public AuthorizationRequestUrlParameters build() {
return new AuthorizationRequestUrlParameters(this);
Expand Down Expand Up @@ -340,5 +359,14 @@ public Builder instanceAware(boolean val) {
this.instanceAware = val;
return self();
}

/**
* Query parameters that you can add to the request,
* in addition to the list of parameters already provided.
*/
public Builder extraQueryParameters(Map<String, String> val) {
this.extraQueryParameters = val;
return self();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public class ClientCredentialParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional query parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public class DeviceCodeFlowParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional query parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ interface IAcquireTokenParameters {

Map<String, String> extraHttpHeaders();
String tenant();

Map<String, String> extraQueryParameters();
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public class IntegratedWindowsAuthenticationParameters implements IAcquireTokenP
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,15 @@ private URL createAuthorizationUrl() {
.loginHint(interactiveRequestParameters.loginHint())
.domainHint(interactiveRequestParameters.domainHint())
.correlationId(publicClientApplication.correlationId())
.instanceAware(interactiveRequestParameters.instanceAware());
.instanceAware(interactiveRequestParameters.instanceAware())
.extraQueryParameters(interactiveRequestParameters.extraQueryParameters());

addPkceAndState(authorizationRequestUrlBuilder);
AuthorizationRequestUrlParameters authorizationRequestUrlParameters =
authorizationRequestUrlBuilder.build();

return publicClientApplication.getAuthorizationRequestUrl(
authorizationRequestUrlBuilder.build());
authorizationRequestUrlParameters);
}

private void addPkceAndState(AuthorizationRequestUrlParameters.Builder builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public class InteractiveRequestParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional query parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ public class OnBehalfOfParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public class RefreshTokenParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ public class SilentParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional query parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class TokenRequestExecutor {

AuthenticationResult executeTokenRequest() throws ParseException, IOException {

log.debug("Sending token request to: " + requestAuthority.canonicalAuthorityUrl());
log.debug("Sending token request to: {}", requestAuthority.canonicalAuthorityUrl());
OAuthHttpRequest oAuthHttpRequest = createOauthHttpRequest();
HTTPResponse oauthHttpResponse = oAuthHttpRequest.send();
return createAuthenticationResultFromOauthHttpResponse(oauthHttpResponse);
Expand Down Expand Up @@ -67,6 +67,15 @@ OAuthHttpRequest createOauthHttpRequest() throws SerializeException, MalformedUR
params.put("claims", Collections.singletonList(claimsRequest));
}

if(msalRequest.requestContext().apiParameters().extraQueryParameters() != null ){
for(String key: msalRequest.requestContext().apiParameters().extraQueryParameters().keySet()){
if(params.containsKey(key)){
log.warn("A query parameter {} has been provided with values multiple times.", key);
}
params.put(key, Collections.singletonList(msalRequest.requestContext().apiParameters().extraQueryParameters().get(key)));
}
}

oauthHttpRequest.setQuery(URLUtils.serializeParameters(params));

if (msalRequest.application().clientAuthentication() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public class UserNamePasswordParameters implements IAcquireTokenParameters {
*/
private Map<String, String> extraHttpHeaders;

/**
* Adds additional query parameters to the token request
*/
private Map<String, String> extraQueryParameters;

/**
* Overrides the tenant value in the authority URL for this request
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,20 @@ public void testBuilder_onlyRequiredParameters() throws UnsupportedEncodingExcep
String redirectUri = "http://localhost:8080";
Set<String> scope = Collections.singleton("scope");

Map<String, String> extraParameters = new HashMap<>();
extraParameters.put("id_token_hint", "test");
extraParameters.put("another_param", "some_value");

AuthorizationRequestUrlParameters parameters =
AuthorizationRequestUrlParameters
.builder(redirectUri, scope)
.extraQueryParameters(extraParameters)
.build();

Assert.assertEquals(parameters.responseMode(), ResponseMode.FORM_POST);
Assert.assertEquals(parameters.redirectUri(), redirectUri);
Assert.assertEquals(parameters.scopes().size(), 4);
Assert.assertEquals(parameters.extraQueryParameters.size(), 2);

Assert.assertNull(parameters.loginHint());
Assert.assertNull(parameters.codeChallenge());
Expand Down Expand Up @@ -58,6 +64,7 @@ public void testBuilder_onlyRequiredParameters() throws UnsupportedEncodingExcep
Assert.assertEquals(queryParameters.get("redirect_uri"), "http://localhost:8080");
Assert.assertEquals(queryParameters.get("client_id"), "client_id");
Assert.assertEquals(queryParameters.get("response_mode"), "form_post");
Assert.assertEquals(queryParameters.get("id_token_hint"),"test");
}

@Test(expectedExceptions = IllegalArgumentException.class)
Expand All @@ -71,6 +78,22 @@ public void testBuilder_invalidRequiredParameters() {
.build();
}

@Test
public void testBuilder_conflictingParameters() {
PublicClientApplication app = PublicClientApplication.builder("client_id").build();

String redirectUri = "http://localhost:8080";
Set<String> scope = Collections.singleton("scope");

Map<String, String> extraParameters = new HashMap<>();
extraParameters.put("scope", "scope");

AuthorizationRequestUrlParameters
.builder(redirectUri, scope)
.extraQueryParameters(extraParameters)
.build();
}

@Test
public void testBuilder_optionalParameters() throws UnsupportedEncodingException {
Set<String> clientCapabilities = new HashSet<>();
Expand Down