diff --git a/msal4j-brokers/pom.xml b/msal4j-brokers/pom.xml index 4e2140ce..060d756e 100644 --- a/msal4j-brokers/pom.xml +++ b/msal4j-brokers/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.microsoft.azure msal4j-brokers - 1.0.0-beta + 0.0.1 jar msal4j-brokers @@ -26,15 +26,11 @@ UTF-8 + com.microsoft.azure msal4j - 1.13.4 - - - com.microsoft.azure - javamsalruntime - 0.13.4 + 1.13.2 org.projectlombok @@ -42,23 +38,6 @@ 1.18.6 provided - - org.testng - testng - 7.1.0 - test - - - org.slf4j - slf4j-api - 1.7.36 - - - ch.qos.logback - logback-classic - 1.2.3 - test - @@ -81,6 +60,7 @@ + ${project.build.directory}/delombok org.projectlombok diff --git a/msal4j-brokers/src/main/java/com/microsoft/aad/msal4jbrokers/MSALRuntimeBroker.java b/msal4j-brokers/src/main/java/com/microsoft/aad/msal4jbrokers/MSALRuntimeBroker.java new file mode 100644 index 00000000..598b83ac --- /dev/null +++ b/msal4j-brokers/src/main/java/com/microsoft/aad/msal4jbrokers/MSALRuntimeBroker.java @@ -0,0 +1,31 @@ +package com.microsoft.aad.msal4jbrokers; + +import com.microsoft.aad.msal4j.*; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.CompletableFuture; + +@Slf4j +public class MSALRuntimeBroker implements IBroker { + + @Override + public IAuthenticationResult acquireToken(PublicClientApplication application, SilentParameters requestParameters) { + log.debug("Should not call this API if msal runtime init failed"); + throw new MsalClientException("Broker implementation missing", "missing_broker"); + } + + @Override + public IAuthenticationResult acquireToken(PublicClientApplication application, InteractiveRequestParameters requestParameters) { + throw new MsalClientException("Broker implementation missing", "missing_broker"); + } + + @Override + public IAuthenticationResult acquireToken(PublicClientApplication application, UserNamePasswordParameters requestParameters) { + throw new MsalClientException("Broker implementation missing", "missing_broker"); + } + + @Override + public CompletableFuture removeAccount(IAccount account) { + throw new MsalClientException("Broker implementation missing", "missing_broker"); + } +} diff --git a/msal4j-brokers/src/main/java/com/microsoft/aad/msal4jbrokers/MsalRuntimeBroker.java b/msal4j-brokers/src/main/java/com/microsoft/aad/msal4jbrokers/MsalRuntimeBroker.java deleted file mode 100644 index 68000997..00000000 --- a/msal4j-brokers/src/main/java/com/microsoft/aad/msal4jbrokers/MsalRuntimeBroker.java +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.microsoft.aad.msal4jbrokers; - -import com.microsoft.aad.msal4j.IAuthenticationResult; -import com.microsoft.aad.msal4j.IBroker; -import com.microsoft.aad.msal4j.InteractiveRequestParameters; -import com.microsoft.aad.msal4j.PublicClientApplication; -import com.microsoft.aad.msal4j.SilentParameters; -import com.microsoft.aad.msal4j.UserNamePasswordParameters; -import com.microsoft.aad.msal4j.MsalClientException; -import com.microsoft.aad.msal4j.AuthenticationErrorCode; -import com.microsoft.aad.msal4j.IAccount; -import com.microsoft.azure.javamsalruntime.Account; -import com.microsoft.azure.javamsalruntime.AuthParameters; -import com.microsoft.azure.javamsalruntime.AuthResult; -import com.microsoft.azure.javamsalruntime.MsalInteropException; -import com.microsoft.azure.javamsalruntime.MsalRuntimeInterop; -import com.microsoft.azure.javamsalruntime.ReadAccountResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -public class MsalRuntimeBroker implements IBroker { - private static final Logger LOG = LoggerFactory.getLogger(MsalRuntimeBroker.class); - - private static MsalRuntimeInterop interop; - - static { - try { - //MsalRuntimeInterop performs various initialization steps in a similar static block, - // so when an MsalRuntimeBroker is created this will cause the interop layer to initialize - interop = new MsalRuntimeInterop(); - } catch (MsalInteropException e) { - throw new MsalClientException(String.format("Could not initialize MSALRuntime: %s", e.getErrorMessage()), AuthenticationErrorCode.MSALRUNTIME_INTEROP_ERROR); - } - } - - @Override - public CompletableFuture acquireToken(PublicClientApplication application, SilentParameters parameters) { - Account accountResult = null; - - //If request has an account ID, MSALRuntime likely has data cached for that account that we can retrieve - if (parameters.account() != null) { - try { - accountResult = ((ReadAccountResult) interop.readAccountById(parameters.account().homeAccountId(), application.correlationId()).get()).getAccount(); - } catch (InterruptedException | ExecutionException ex) { - throw new MsalClientException(String.format("MSALRuntime async operation interrupted when waiting for result: %s", ex.getMessage()), AuthenticationErrorCode.MSALRUNTIME_INTEROP_ERROR); - } - } - - try { - AuthParameters authParameters = new AuthParameters - .AuthParametersBuilder(application.clientId(), - application.authority(), - String.join(" ", parameters.scopes())) - .build(); - - if (accountResult == null) { - return interop.signInSilently(authParameters, application.correlationId()) - .thenCompose(acctResult -> interop.acquireTokenSilently(authParameters, application.correlationId(), ((AuthResult) acctResult).getAccount())) - .thenApply(authResult -> parseBrokerAuthResult( - application.authority(), - ((AuthResult) authResult).getIdToken(), - ((AuthResult) authResult).getAccessToken(), - ((AuthResult) authResult).getAccount().getAccountId(), - ((AuthResult) authResult).getAccount().getClientInfo(), - ((AuthResult) authResult).getAccessTokenExpirationTime())); - } else { - return interop.acquireTokenSilently(authParameters, application.correlationId(), accountResult) - .thenApply(authResult -> parseBrokerAuthResult(application.authority(), - ((AuthResult) authResult).getIdToken(), - ((AuthResult) authResult).getAccessToken(), - ((AuthResult) authResult).getAccount().getAccountId(), - ((AuthResult) authResult).getAccount().getClientInfo(), - ((AuthResult) authResult).getAccessTokenExpirationTime()) - - ); - } - } catch (MsalInteropException interopException) { - throw new MsalClientException(interopException.getErrorMessage(), AuthenticationErrorCode.MSALRUNTIME_INTEROP_ERROR); - } - } - - @Override - public CompletableFuture acquireToken(PublicClientApplication application, InteractiveRequestParameters parameters) { - try { - AuthParameters authParameters = new AuthParameters - .AuthParametersBuilder(application.clientId(), - application.authority(), - String.join(" ", parameters.scopes())) - .build(); - - return interop.signInInteractively(parameters.windowHandle(), authParameters, application.correlationId(), parameters.loginHint()) - .thenCompose(acctResult -> interop.acquireTokenInteractively(parameters.windowHandle(), authParameters, application.correlationId(), ((AuthResult) acctResult).getAccount())) - .thenApply(authResult -> parseBrokerAuthResult( - application.authority(), - ((AuthResult) authResult).getIdToken(), - ((AuthResult) authResult).getAccessToken(), - ((AuthResult) authResult).getAccount().getAccountId(), - ((AuthResult) authResult).getAccount().getClientInfo(), - ((AuthResult) authResult).getAccessTokenExpirationTime()) - ); - } catch (MsalInteropException interopException) { - throw new MsalClientException(interopException.getErrorMessage(), AuthenticationErrorCode.MSALRUNTIME_INTEROP_ERROR); - } - } - - /** - * @deprecated - */ - @Deprecated - @Override - public CompletableFuture acquireToken(PublicClientApplication application, UserNamePasswordParameters parameters) { - try { - AuthParameters authParameters = - new AuthParameters - .AuthParametersBuilder(application.clientId(), - application.authority(), - String.join(" ", parameters.scopes())) - .build(); - - authParameters.setUsernamePassword(parameters.username(), new String(parameters.password())); - - return interop.signInSilently(authParameters, application.correlationId()) - .thenCompose(acctResult -> interop.acquireTokenSilently(authParameters, application.correlationId(), ((AuthResult) acctResult).getAccount())) - .thenApply(authResult -> parseBrokerAuthResult( - application.authority(), - ((AuthResult) authResult).getIdToken(), - ((AuthResult) authResult).getAccessToken(), - ((AuthResult) authResult).getAccount().getAccountId(), - ((AuthResult) authResult).getAccount().getClientInfo(), - ((AuthResult) authResult).getAccessTokenExpirationTime())); - } catch (MsalInteropException interopException) { - throw new MsalClientException(interopException.getErrorMessage(), AuthenticationErrorCode.MSALRUNTIME_INTEROP_ERROR); - } - } - - @Override - public void removeAccount(PublicClientApplication application, IAccount msalJavaAccount) { - try { - Account msalRuntimeAccount = ((ReadAccountResult) interop.readAccountById(msalJavaAccount.homeAccountId(), application.correlationId()).get()).getAccount(); - - if (msalRuntimeAccount != null) { - interop.signOutSilently(application.clientId(), application.correlationId(), msalRuntimeAccount); - } - } catch (MsalInteropException interopException) { - throw new MsalClientException(interopException.getErrorMessage(), AuthenticationErrorCode.MSALRUNTIME_INTEROP_ERROR); - } catch (InterruptedException | ExecutionException ex) { - throw new MsalClientException(String.format("MSALRuntime async operation interrupted when waiting for result: %s", ex.getMessage()), AuthenticationErrorCode.MSALRUNTIME_INTEROP_ERROR); - } - } - - /** - * Calls MSALRuntime's startup API. If MSALRuntime started successfully, we can assume that the broker is available for use. - * - * If an exception is thrown when trying to start MSALRuntime, we assume that we cannot use the broker and will not make any more attempts to do so. - * - * @return boolean representing whether or not MSALRuntime started successfully - */ - @Override - public boolean isBrokerAvailable() { - try { - interop.startupMsalRuntime(); - - LOG.info("MSALRuntime started successfully. MSAL Java will use MSALRuntime in all supported broker flows."); - - return true; - } catch (MsalInteropException e) { - LOG.warn("Exception thrown when trying to start MSALRuntime: {}", e.getErrorMessage()); - LOG.warn("MSALRuntime could not be started. MSAL Java will fall back to non-broker flows."); - - return false; - } - } -} diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java index 1ea0232e..78f5260c 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java @@ -115,22 +115,9 @@ public class AuthenticationErrorCode { * A JWT parsing failure, indicating the JWT provided to MSAL is of invalid format. */ public final static String INVALID_JWT = "invalid_jwt"; - /** * Indicates that a Broker implementation is missing from the device, such as when an app developer * does not include one of our broker packages as a dependency in their project, or otherwise cannot - * be accessed by MSAL Java - */ + * be accessed by MSAL Java*/ public final static String MISSING_BROKER = "missing_broker"; - - /** - * Indicates an error from the MSAL Java/MSALRuntime interop layer used by the Java Brokers package, - * and will generally just be forwarding an error message from the interop layer or MSALRuntime itself - */ - public final static String MSALRUNTIME_INTEROP_ERROR = "interop_package_error"; - - /** - * Indicates an error in the MSAL Java Brokers package - */ - public final static String MSALJAVA_BROKERS_ERROR = "brokers_package_error"; } diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IBroker.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IBroker.java index 69906319..919a8092 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IBroker.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/IBroker.java @@ -3,80 +3,58 @@ package com.microsoft.aad.msal4j; -import com.nimbusds.jwt.JWTParser; - -import java.net.URL; +import java.util.Set; import java.util.concurrent.CompletableFuture; /** * Used to define the basic set of methods that all Brokers must implement * - * All methods are marked as default so they can be referenced by MSAL Java without an implementation, - * and most will simply throw an exception if not overridden by an IBroker implementation + * All methods are so they can be referenced by MSAL Java without an implementation, and by default simply throw an + * exception saying that a broker implementation is missing */ public interface IBroker { + /** + * checks if a IBroker implementation exists + */ + + default boolean isAvailable(){ + return false; + } /** * Acquire a token silently, i.e. without direct user interaction * * This may be accomplished by returning tokens from a token cache, using cached refresh tokens to get new tokens, * or via any authentication flow where a user is not prompted to enter credentials + * + * @param requestParameters MsalRequest object which contains everything needed for the broker implementation to make a request + * @return IBroker implementations will return an AuthenticationResult object */ - default CompletableFuture acquireToken(PublicClientApplication application, SilentParameters requestParameters) { + default IAuthenticationResult acquireToken(PublicClientApplication application, SilentParameters requestParameters) { throw new MsalClientException("Broker implementation missing", AuthenticationErrorCode.MISSING_BROKER); } /** * Acquire a token interactively, by prompting users to enter their credentials in some way + * + * @param requestParameters MsalRequest object which contains everything needed for the broker implementation to make a request + * @return IBroker implementations will return an AuthenticationResult object */ - default CompletableFuture acquireToken(PublicClientApplication application, InteractiveRequestParameters parameters) { + default IAuthenticationResult acquireToken(PublicClientApplication application, InteractiveRequestParameters requestParameters) { throw new MsalClientException("Broker implementation missing", AuthenticationErrorCode.MISSING_BROKER); } /** * Acquire a token silently, i.e. without direct user interaction, using username/password authentication + * + * @param requestParameters MsalRequest object which contains everything needed for the broker implementation to make a request + * @return IBroker implementations will return an AuthenticationResult object */ - default CompletableFuture acquireToken(PublicClientApplication application, UserNamePasswordParameters parameters) { + default IAuthenticationResult acquireToken(PublicClientApplication application, UserNamePasswordParameters requestParameters) { throw new MsalClientException("Broker implementation missing", AuthenticationErrorCode.MISSING_BROKER); } - default void removeAccount(PublicClientApplication application, IAccount account) throws MsalClientException { + default CompletableFuture removeAccount(IAccount account) { throw new MsalClientException("Broker implementation missing", AuthenticationErrorCode.MISSING_BROKER); } - - default boolean isBrokerAvailable() { - throw new MsalClientException("Broker implementation missing", AuthenticationErrorCode.MISSING_BROKER); - } - - /** - * MSAL Java's AuthenticationResult requires several package-private classes that a broker implementation can't access, - * so this helper method can be used to create AuthenticationResults from within the MSAL Java package - */ - default IAuthenticationResult parseBrokerAuthResult(String authority, String idToken, String accessToken, - String accountId, String clientInfo, - long accessTokenExpirationTime) { - - AuthenticationResult.AuthenticationResultBuilder builder = AuthenticationResult.builder(); - - try { - if (idToken != null) { - builder.idToken(idToken); - if (accountId!= null) { - String idTokenJson = - JWTParser.parse(idToken).getParsedParts()[1].decodeToString(); - //TODO: need to figure out if 'policy' field is relevant for brokers - builder.accountCacheEntity(AccountCacheEntity.create(clientInfo, - Authority.createAuthority(new URL(authority)), JsonHelper.convertJsonToObject(idTokenJson, - IdToken.class), null)); - } - } - if (accessToken != null) { - builder.accessToken(accessToken); - builder.expiresOn(accessTokenExpirationTime); - } - } catch (Exception e) { - throw new MsalClientException(String.format("Exception when converting broker result to MSAL Java AuthenticationResult: %s", e.getMessage()), AuthenticationErrorCode.MSALJAVA_BROKERS_ERROR); - } - return builder.build(); - } } \ No newline at end of file diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/InteractiveRequestParameters.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/InteractiveRequestParameters.java index a41d1832..acdb638a 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/InteractiveRequestParameters.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/InteractiveRequestParameters.java @@ -100,18 +100,6 @@ public class InteractiveRequestParameters implements IAcquireTokenParameters { */ private boolean instanceAware; - /** - * The parent window handle used to open UI elements with the correct parent - * - * - * For browser scenarios and Windows console applications, this value should not need to be set - * - * For Windows console applications, MSAL Java will attempt to discover the console's window handle if this parameter is not set - * - * For scenarios where MSAL Java is responsible for opening UI elements (such as when using MSALRuntime), this parameter is required and an exception will be thrown if not set - */ - private long windowHandle; - private static InteractiveRequestParametersBuilder builder() { return new InteractiveRequestParametersBuilder(); } diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/PublicClientApplication.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/PublicClientApplication.java index 11b19604..a7f18dda 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/PublicClientApplication.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/PublicClientApplication.java @@ -8,7 +8,6 @@ import com.nimbusds.oauth2.sdk.id.ClientID; import org.slf4j.LoggerFactory; -import java.net.MalformedURLException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; @@ -24,8 +23,6 @@ public class PublicClientApplication extends AbstractClientApplicationBase implements IPublicClientApplication { private final ClientAuthenticationPost clientAuthentication; - private IBroker broker; - private boolean brokerEnabled; @Override public CompletableFuture acquireToken(UserNamePasswordParameters parameters) { @@ -38,20 +35,12 @@ public CompletableFuture acquireToken(UserNamePasswordPar parameters, UserIdentifier.fromUpn(parameters.username())); - CompletableFuture future; - - if (brokerEnabled) { - future = broker.acquireToken(this, parameters); - } else { - UserNamePasswordRequest userNamePasswordRequest = - new UserNamePasswordRequest(parameters, - this, - context); - - future = this.executeRequest(userNamePasswordRequest); - } + UserNamePasswordRequest userNamePasswordRequest = + new UserNamePasswordRequest(parameters, + this, + context); - return future; + return this.executeRequest(userNamePasswordRequest); } @Override @@ -123,49 +112,17 @@ public CompletableFuture acquireToken(InteractiveRequestP this, context); - CompletableFuture future; - - if (brokerEnabled) { - future = broker.acquireToken(this, parameters); - } else { - future = executeRequest(interactiveRequest); - } - + CompletableFuture future = executeRequest(interactiveRequest); futureReference.set(future); - return future; } - @Override - public CompletableFuture acquireTokenSilently(SilentParameters parameters) throws MalformedURLException { - CompletableFuture future; - - if (brokerEnabled) { - future = broker.acquireToken(this, parameters); - } else { - future = super.acquireTokenSilently(parameters); - } - - return future; - } - - @Override - public CompletableFuture removeAccount(IAccount account) { - if (brokerEnabled) { - broker.removeAccount(this, account); - } - - return super.removeAccount(account); - } - private PublicClientApplication(Builder builder) { super(builder); validateNotBlank("clientId", clientId()); log = LoggerFactory.getLogger(PublicClientApplication.class); this.clientAuthentication = new ClientAuthenticationPost(ClientAuthenticationMethod.NONE, new ClientID(clientId())); - this.broker = builder.broker; - this.brokerEnabled = builder.brokerEnabled; } @Override @@ -189,22 +146,6 @@ private Builder(String clientId) { super(clientId); } - private IBroker broker = null; - private boolean brokerEnabled = false; - - /** - * Implementation of IBroker that will be used to retrieve tokens - *

- * Setting this will cause MSAL Java to use the given broker implementation to retrieve tokens from a broker (such as WAM/MSALRuntime) in flows that support it - */ - public PublicClientApplication.Builder broker(IBroker val) { - this.broker = val; - - this.brokerEnabled = this.broker.isBrokerAvailable(); - - return self(); - } - @Override public PublicClientApplication build() {