Skip to content

Commit c71ae66

Browse files
billwertscottaddie
andauthored
Fix for broker scenario (#39284)
* Fix for broker scenario In the case where the user requests signing in with the default account, fall back to the UI if it doesn't get one. * rename api * add samples and readme * remove parameter * remove block in async path * Update sdk/identity/azure-identity-broker/README.md Co-authored-by: Scott Addie <[email protected]> * Update sdk/identity/azure-identity-broker/CHANGELOG.md Co-authored-by: Scott Addie <[email protected]> * fix incorrect exception being thrown * pr feedback * fixup javadoc * fix sample * update readme --------- Co-authored-by: Scott Addie <[email protected]>
1 parent 85a2b1b commit c71ae66

File tree

8 files changed

+72
-32
lines changed

8 files changed

+72
-32
lines changed

sdk/identity/azure-identity-broker-samples/src/samples/java/com/azure/identity/broker/JavaDocCodeSnippets.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ public void configureCredentialForWindows() {
4040
// END: com.azure.identity.broker.interactivebrowserbrokercredentialbuilder.useinteractivebrowserbroker.windows
4141
}
4242

43+
public void configureCredentialForDefaultAccount() {
44+
// BEGIN: com.azure.identity.broker.interactivebrowserbrokercredentialbuilder.useinteractivebrowserbroker.defaultaccount
45+
InteractiveBrowserCredential cred = new InteractiveBrowserBrokerCredentialBuilder()
46+
.useDefaultBrokerAccount()
47+
.build();
48+
// END: com.azure.identity.broker.interactivebrowserbrokercredentialbuilder.useinteractivebrowserbroker.defaultaccount
49+
}
50+
4351
private long getWindowHandle() {
4452
return 0;
4553
}

sdk/identity/azure-identity-broker/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Features Added
66

7+
- Added support for using the default broker account
8+
79
### Breaking Changes
810

911
### Bugs Fixed

sdk/identity/azure-identity-broker/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ InteractiveBrowserCredential cred = new InteractiveBrowserBrokerCredentialBuilde
8989
.build();
9090
```
9191

92+
#### Use the default account for sign-in
93+
94+
When this option is enabled, the credential will attempt to silently use the default broker account. If using the default account fails, the credential will fall back to interactive authentication.
95+
96+
```java com.azure.identity.broker.interactivebrowserbrokercredentialbuilder.useinteractivebrowserbroker.defaultaccount
97+
InteractiveBrowserCredential cred = new InteractiveBrowserBrokerCredentialBuilder()
98+
.useDefaultBrokerAccount()
99+
.build();
100+
```
101+
92102
#### Obtain a window handle
93103

94104
##### JavaFX

sdk/identity/azure-identity-broker/src/main/java/com/azure/identity/broker/InteractiveBrowserBrokerCredentialBuilder.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,13 @@ public InteractiveBrowserBrokerCredentialBuilder enableLegacyMsaPassthrough() {
6262
}
6363

6464
/**
65-
* Enables automatically using the signed-in user's account for brokered authentication instead of
66-
* of prompting the user with a login dialog.
65+
* Enables automatically using the default broker account for authentication instead
66+
* of prompting the user with an account picker.
6767
*
68-
* @param useOperatingSystemAccount Boolean value to determine if the operating system account should be used.
69-
* @return An updated instance of this builder with useOperatingSystemAccount set.
68+
* @return An updated instance of this builder with useDefaultBrokerAccount set.
7069
*/
71-
public InteractiveBrowserCredentialBuilder useOperatingSystemAccount(boolean useOperatingSystemAccount) {
72-
CredentialBuilderBaseHelper.getClientOptions(this).
73-
setUseOperatingSystemAccount(useOperatingSystemAccount);
70+
public InteractiveBrowserCredentialBuilder useDefaultBrokerAccount() {
71+
CredentialBuilderBaseHelper.getClientOptions(this).setUseDefaultBrokerAccount(true);
7472
return this;
7573
}
7674

sdk/identity/azure-identity-broker/src/test/java/com/azure/identity/broker/InteractiveBrowserBrokerCredentialBuilderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,10 @@ void proxyOptions() {
242242
}
243243

244244
@Test
245-
void setUseOperatingSystemAccount() {
245+
void setDefaultBrokerAccount() {
246246
assertDoesNotThrow(() -> {
247247
InteractiveBrowserBrokerCredentialBuilder builder = new InteractiveBrowserBrokerCredentialBuilder();
248-
builder.useOperatingSystemAccount(true);
248+
builder.useDefaultBrokerAccount();
249249
builder.build();
250250
});
251251
}

sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -823,24 +823,36 @@ public Mono<MsalToken> authenticateWithBrowserInteraction(TokenRequestContext re
823823
return Mono.error(LOGGER.logExceptionAsError(new RuntimeException(e)));
824824
}
825825

826-
if (options.isBrokerEnabled() && options.useOperatingSystemAccount()) {
827-
return getPublicClientInstance(request).getValue().flatMap(pc ->
828-
Mono.fromFuture(() ->
829-
acquireTokenFromPublicClientSilently(request, pc, null, false)).
830-
map(MsalToken::new));
831-
} else {
832-
826+
// If the broker is enabled, try to get the token for the default account by passing
827+
// a null account to MSAL. If that fails, show the dialog.
828+
829+
return getPublicClientInstance(request).getValue().flatMap(pc -> {
830+
if (options.isBrokerEnabled() && options.useDefaultBrokerAccount()) {
831+
return Mono.fromFuture(() ->
832+
acquireTokenFromPublicClientSilently(request, pc, null, false))
833+
// The error case here represents the silent acquisition failing. There's nothing actionable and
834+
// in this case the fallback path of showing the dialog will capture any meaningful error and share it.
835+
.onErrorResume(e -> Mono.empty());
836+
} else {
837+
return Mono.empty();
838+
}
839+
})
840+
.switchIfEmpty(Mono.defer(() -> {
833841
InteractiveRequestParameters.InteractiveRequestParametersBuilder builder =
834842
buildInteractiveRequestParameters(request, loginHint, redirectUri);
835843

836844
SynchronizedAccessor<PublicClientApplication> publicClient = getPublicClientInstance(request);
837845

838-
Mono<IAuthenticationResult> acquireToken = publicClient.getValue()
846+
return publicClient.getValue()
839847
.flatMap(pc -> Mono.fromFuture(() -> pc.acquireToken(builder.build())));
840848

841-
return acquireToken.onErrorMap(t -> new ClientAuthenticationException(
842-
"Failed to acquire token with Interactive Browser Authentication.", null, t)).map(MsalToken::new);
843-
}
849+
}))
850+
// If we're already throwing a ClientAuthenticationException we don't need to wrap it again.
851+
.onErrorMap(t -> !(t instanceof ClientAuthenticationException),
852+
t -> {
853+
throw new ClientAuthenticationException("Failed to acquire token with Interactive Browser Authentication.", null, t);
854+
})
855+
.map(MsalToken::new);
844856
}
845857

846858
/**

sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientOptions.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public final class IdentityClientOptions implements Cloneable {
7979
private long brokerWindowHandle;
8080
private boolean brokerEnabled;
8181
private boolean enableMsaPassthrough;
82-
private boolean useOperatingSystemAccount;
82+
private boolean useDefaultBrokerAccount;
8383

8484
/**
8585
* Creates an instance of IdentityClientOptions with default settings.
@@ -784,11 +784,11 @@ public IdentityClientOptions setEnableLegacyMsaPassthrough(boolean enableMsaPass
784784

785785
/**
786786
* Sets whether to use the logged-in user's account for broker authentication.
787-
* @param useOperatingSystemAccount
787+
* @param useDefaultBrokerAccount
788788
* @return the updated client options
789789
*/
790-
public IdentityClientOptions setUseOperatingSystemAccount(boolean useOperatingSystemAccount) {
791-
this.useOperatingSystemAccount = useOperatingSystemAccount;
790+
public IdentityClientOptions setUseDefaultBrokerAccount(boolean useDefaultBrokerAccount) {
791+
this.useDefaultBrokerAccount = useDefaultBrokerAccount;
792792
return this;
793793
}
794794

@@ -804,8 +804,8 @@ public boolean isMsaPassthroughEnabled() {
804804
* Gets the status whether to use the logged-in user's account for broker authentication.
805805
* @return the flag indicating if the logged-in user's account should be used for broker authentication.
806806
*/
807-
public boolean useOperatingSystemAccount() {
808-
return this.useOperatingSystemAccount;
807+
public boolean useDefaultBrokerAccount() {
808+
return this.useDefaultBrokerAccount;
809809
}
810810

811811
public IdentityClientOptions clone() {

sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentitySyncClient.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -337,12 +337,21 @@ public MsalToken authenticateWithBrowserInteraction(TokenRequestContext request,
337337
}
338338
PublicClientApplication pc = getPublicClientInstance(request).getValue();
339339

340-
if (options.isBrokerEnabled() && options.useOperatingSystemAccount()) {
341-
return acquireTokenFromPublicClientSilently(request,
342-
pc,
343-
null,
344-
false);
345-
} else {
340+
// If the broker is enabled, try to get the token for the default account by passing
341+
// a null account to MSAL. If that fails, show the dialog.
342+
MsalToken token = null;
343+
if (options.isBrokerEnabled() && options.useDefaultBrokerAccount()) {
344+
try {
345+
token = acquireTokenFromPublicClientSilently(request,
346+
pc,
347+
null,
348+
false);
349+
} catch (Exception e) {
350+
// The error case here represents the silent acquisition failing. There's nothing actionable and
351+
// in this case the fallback path of showing the dialog will capture any meaningful error and share it.
352+
}
353+
}
354+
if (token == null) {
346355
InteractiveRequestParameters.InteractiveRequestParametersBuilder builder =
347356
buildInteractiveRequestParameters(request, loginHint, redirectUri);
348357

@@ -353,6 +362,7 @@ public MsalToken authenticateWithBrowserInteraction(TokenRequestContext request,
353362
"Failed to acquire token with Interactive Browser Authentication.", null, e));
354363
}
355364
}
365+
return token;
356366
}
357367

358368
/**

0 commit comments

Comments
 (0)