Skip to content

Commit

Permalink
Merge pull request #26 from MicrosoftDocs/main
Browse files Browse the repository at this point in the history
Sync changes to prod
  • Loading branch information
cilwerner authored Aug 30, 2023
2 parents 1a2bb12 + a74820a commit ed652d4
Show file tree
Hide file tree
Showing 8 changed files with 406 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Validate content links](https://github.com/MicrosoftDocs/microsoft-authentication-library-java/actions/workflows/linkchecker.yml/badge.svg)](https://github.com/MicrosoftDocs/microsoft-authentication-library-java/actions/workflows/linkchecker.yml)

This is the documentation repository for Microsoft Authentication Library (MSAL) for .NET. If you are looking for the library, refer to [AzureAD/microsoft-authentication-library-for-java](https://github.com/AzureAD/microsoft-authentication-library-for-java).
This is the documentation repository for Microsoft Authentication Library (MSAL) for Java. If you are looking for the library, refer to [AzureAD/microsoft-authentication-library-for-java](https://github.com/AzureAD/microsoft-authentication-library-for-java).

## Contributions

Expand Down
10 changes: 7 additions & 3 deletions msal-java-articles/TOC.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,21 @@
- name: Service-to-service calls
href: advanced/service-to-service-calls.md
- name: Logging
href: /azure/active-directory/develop/msal-logging-java
href: advanced/msal-logging-java.md
- name: Exceptions
href: advanced/exceptions.md
- name: Token Cache
href: /azure/active-directory/develop/msal-java-token-cache-serialization
href: advanced/msal-java-token-cache-serialization.md
- name: Get and remove accounts from the token cache using MSAL4J
href: advanced/msal-java-get-remove-accounts-token-cache.md
- name: Claims Challenge
href: /azure/active-directory/develop/conditional-access-dev-guide
- name: Migrate from ADAL
href: /azure/active-directory/develop/migrate-adal-msal-java
href: advanced/migrate-adal-msal-java.md
- name: Using MSAL4J with B2C
href: advanced/aad-b2c.md
- name: Handle errors and exceptions in MSAL4J
href: advanced/msal-error-handling-java.md
- name: ADFS Support
href: advanced/support-for-adfs.md
- name: National Clouds
Expand Down
107 changes: 107 additions & 0 deletions msal-java-articles/advanced/migrate-adal-msal-java.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
title: ADAL to MSAL migration guide (MSAL4j)
description: Learn how to migrate your Azure Active Directory Authentication Library (ADAL) Java app to the Microsoft Authentication Library (MSAL).
---

# ADAL to MSAL migration guide for Java

This article highlights changes you need to make to migrate an application that uses the Azure Active Directory Authentication Library (ADAL) to the Microsoft Authentication Library (MSAL).

Both the Microsoft Authentication Library for Java (MSAL4J) and Azure AD Authentication Library for Java (ADAL4J) are used to authenticate Microsoft Entra ID entities and request tokens from Microsoft Entra ID. Until now, most developers have worked with Microsoft Entra ID developer platform (v1.0) to authenticate with various identities, such as work and school accounts, by requesting tokens using Azure AD Authentication Library (ADAL).

MSAL offers the following benefits:

- Because it uses the newer Microsoft identity platform, you can authenticate a broader set of Microsoft identities such as Microsoft Entra ID identities, Microsoft accounts, and social and local accounts through Microsoft Entra ID Business to Consumer (B2C).
- Your users will get the best single-sign-on experience.
- Your application can enable incremental consent, as well as support new features, such as Conditional Access.

MSAL for Java is the authentication library we recommend you use with the Microsoft identity platform. No new features will be implemented on ADAL4J. All efforts going forward are focused on improving MSAL.

You can learn more about MSAL and get started with an [overview of the Microsoft Authentication Library](../index.md).

## Scopes not resources

ADAL4J acquires tokens for resources whereas MSAL for Java acquires tokens for scopes. Many MSAL for Java classes require a scopes parameter. This parameter is a list of strings that declare the desired permissions and resources that are requested. See [Microsoft Graph's scopes](/graph/permissions-reference) to see example scopes.

You can add the `/.default` scope suffix to the resource to help migrate your apps from the ADAL to MSAL. For example, for the resource value of `https://graph.microsoft.com`, the equivalent scope value is `https://graph.microsoft.com/.default`. If the resource isn't in the URL form, but a resource ID of the form `XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX`, you can still use the scope value as `XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX/.default`.

For more details about the different types of scopes, refer
[Permissions and consent in the Microsoft identity platform](/azure/active-directory/develop/permissions-consent-overview) and the [Scopes for a Web API accepting v1.0 tokens](/azure/active-directory/develop/msal-v1-app-scopes) articles.

## Core classes

In ADAL4J, the `AuthenticationContext` class represents your connection to the Security Token Service (STS), or authorization server, through an Authority. However, MSAL for Java is designed around client applications. It provides two separate classes: `PublicClientApplication` and `ConfidentialClientApplication` to represent client applications. The latter, `ConfidentialClientApplication`, represents an application that is designed to securely maintain a secret such as an application identifier for a daemon app.

The following table shows how ADAL4J functions map to the new MSAL for Java functions:

| ADAL4J method| MSAL4J method|
|------|-------|
|acquireToken(String resource, ClientCredential credential, AuthenticationCallback callback) | <xref:com.microsoft.aad.msal4j.ClientCredentialParameters> |
|acquireToken(String resource, ClientAssertion assertion, AuthenticationCallback callback)| <xref:com.microsoft.aad.msal4j.ClientCredentialParameters> |
|acquireToken(String resource, AsymmetricKeyCredential credential, AuthenticationCallback callback)| <xref:com.microsoft.aad.msal4j.ClientCredentialParameters> |
|acquireToken(String resource, String clientId, String username, String password, AuthenticationCallback callback)| <xref:com.microsoft.aad.msal4j.UserNamePasswordParameters> |
|acquireToken(String resource, String clientId, String username, String password=null, AuthenticationCallback callback)|<xref:com.microsoft.aad.msal4j.IntegratedWindowsAuthenticationParameters> |
|acquireToken(String resource, UserAssertion userAssertion, ClientCredential credential, AuthenticationCallback callback)| <xref:com.microsoft.aad.msal4j.OnBehalfOfParameters> |
|acquireTokenByAuthorizationCode() | <xref:com.microsoft.aad.msal4j.AuthorizationCodeParameters> |
| acquireDeviceCode() and acquireTokenByDeviceCode()| <xref:com.microsoft.aad.msal4j.DeviceCodeFlowParameters> |
|acquireTokenByRefreshToken()| <xref:com.microsoft.aad.msal4j.SilentParameters> |

## IAccount instead of IUser

ADAL4J handled users. Although a user represents a single human or software agent, it can have one or more accounts in the Microsoft identity system. For example, a user may have several Microsoft Entra ID, Microsoft Entra ID B2C, or Microsoft personal accounts.

MSAL for Java defines the concept of Account via the `IAccount` interface. This is a breaking change from ADAL4J. It captures the fact that the same user can have several accounts, and perhaps even in different Microsoft Entra ID directories. MSAL for Java provides better information in guest scenarios because home account information is provided.

## Cache persistence

ADAL4J didn't have support for token cache. MSAL for Java adds a [token cache](/azure/active-directory/develop/msal-acquire-cache-tokens) to simplify managing token lifetimes by automatically refreshing expired tokens when possible and preventing unnecessary prompts for the user to provide credentials when possible.

## Common Authority

In v1.0, if you use the `https://login.microsoftonline.com/common` authority, users can sign in with any Microsoft Entra ID account (for any organization).

If you use the `https://login.microsoftonline.com/common` authority in v2.0, users can sign in with any Microsoft Entra ID organization, or even a Microsoft personal account (MSA). In MSAL for Java, if you want to restrict login to any Microsoft Entra ID account, use the `https://login.microsoftonline.com/organizations` authority (which is the same behavior as with ADAL4J). To specify an authority, set the `authority` parameter in the <xref:com.microsoft.aad.msal4j.PublicClientApplication.Builder> method when you instantiate a `PublicClientApplication` class.

## v1.0 and v2.0 tokens

The v1.0 endpoint (used by ADAL) only emits v1.0 tokens.

The v2.0 endpoint (used by MSAL) can emit v1.0 and v2.0 tokens. A property of the application manifest of the web API enables developers to choose which version of token is accepted. See `accessTokenAcceptedVersion` in the [application manifest](/azure/active-directory/develop/reference-app-manifest) reference documentation.

For more information about v1.0 and v2.0 tokens, see [Azure Active Directory access tokens](/azure/active-directory/develop/access-tokens).

## ADAL to MSAL migration

In ADAL4J, the refresh tokens were exposed--which allowed developers to cache them. They would then use `AcquireTokenByRefreshToken()` to enable solutions such as implementing long-running services that refresh dashboards on behalf of the user when the user is no longer connected.

MSAL for Java doesn't expose refresh tokens for security reasons. Instead, MSAL handles refreshing tokens for you.

MSAL for Java has an API that allows you to migrate refresh tokens acquired with ADAL4J into the `ClientApplication`: <xref:com.microsoft.aad.msal4j.RefreshTokenParameters>. With this method, you can provide the previously used refresh token along with any scopes (resources) you desire. The refresh token will be exchanged for a new one and cached for use by your application.

The following code snippet shows a simple migration code snippet in a confidential client application:

```java
String rt = GetCachedRefreshTokenForSignedInUser(); // Get refresh token from where you have them stored
Set<String> scopes = Collections.singleton("SCOPE_FOR_REFRESH_TOKEN");

RefreshTokenParameters parameters = RefreshTokenParameters.builder(scopes, rt).build();

PublicClientApplication app = PublicClientApplication.builder(CLIENT_ID) // ClientId for your application
.authority(AUTHORITY) //plug in your authority
.build();

IAuthenticationResult result = app.acquireToken(parameters);
```

The `IAuthenticationResult` returns an access token and ID token, while your new refresh token is stored in the cache. The application will also now contain an `IAccount`:

```java
Set<IAccount> accounts = app.getAccounts().join();
```

To use the tokens that are now in the cache, call:

```java
SilentParameters parameters = SilentParameters.builder(scope, accounts.iterator().next()).build();
IAuthenticationResult result = app.acquireToken(parameters);
```
94 changes: 94 additions & 0 deletions msal-java-articles/advanced/msal-error-handling-java.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: Handle errors and exceptions in MSAL4J
description: Learn how to handle errors and exceptions, Conditional Access claims challenges, and retries in MSAL4J applications.
---

# Handle errors and exceptions in MSAL for Java

This article gives an overview of the different types of errors and recommendations for handling them.

## MSAL error handling basics

Exceptions in Microsoft Authentication Library (MSAL) are intended for app developers to troubleshoot, not for displaying to end users. Exception messages are not localized.

When processing exceptions and errors, you can use the exception type itself and the error code to distinguish between exceptions. For a list of error codes, see [Azure AD Authentication and authorization error codes](/azure/active-directory/develop/reference-error-codes).

During the sign-in experience, you may encounter errors about consents, Conditional Access (e.g., multi-factor authentication, device management, location-based restrictions), token issuance and redemption, and user properties.

The following section provides more details about error handling for your app.

## Error handling in MSAL for Java

In MSAL for Java, there are three types of exceptions: `MsalClientException`, `MsalServiceException`, and `MsalInteractionRequiredException`; all which inherit from `MsalException`.

- `MsalClientException` is thrown when an error occurs that is local to the library or device.
- `MsalServiceException` is thrown when the secure token service (STS) returns an error response or another networking error occurs.
- `MsalInteractionRequiredException` is thrown when UI interaction is required for authentication to succeed.

### MsalServiceException

`MsalServiceException` exposes HTTP headers returned in the requests to the STS. Access them via `MsalServiceException.headers()`

### MsalInteractionRequiredException

One of common status codes returned from MSAL for Java when calling `AcquireTokenSilently()` is `InvalidGrantError`. This means that additional user interaction is required before an authentication token can be issued. Your application should call the authentication library again, but in interactive mode by sending `AuthorizationCodeParameters` or `DeviceCodeParameters` for public client applications.

Most of the time when `AcquireTokenSilently` fails, it's because the token cache doesn't have a token matching your request. Access tokens expire in one hour, and `AcquireTokenSilently` will try to get a new one based on a refresh token. In OAuth2 terms, this is the Refresh Token flow. This flow can also fail for various reasons such as when a tenant admin configures more stringent login policies.

Some conditions that result in this error are easy for users to resolve. For example, they may need to accept Terms of Use or the request can't be fulfilled with the current configuration because the machine needs to connect to a specific corporate network.

MSAL exposes a `reason` field, which you can use to provide a better user experience. For example, the `reason` field may lead you to tell the user that their password expired or that they'll need to provide consent to use some resources. The supported values are part of the `InteractionRequiredExceptionReason` enum:

| Reason | Meaning | Recommended Handling |
|---------|-----------|-----------------------------|
| `BasicAction` | Condition can be resolved by user interaction during the interactive authentication flow. | Call `acquireToken` with interactive parameters. |
| `AdditionalAction` | Condition can be resolved by additional remedial interaction with the system outside of the interactive authentication flow. | Call `acquireToken` with interactive parameters to show a message that explains the remedial action to take. The calling app may choose to hide flows that require additional action if the user is unlikely to complete the remedial action. |
| `MessageOnly` | Condition can't be resolved at this time. Launch interactive authentication flow to show a message explaining the condition. | Call `acquireToken` with interactive parameters to show a message that explains the condition. `acquireToken` will return the `UserCanceled` error after the user reads the message and closes the window. The app may choose to hide flows that result in message if the user is unlikely to benefit from the message. |
| `ConsentRequired`| User consent is missing, or has been revoked. |Call `acquireToken` with interactive parameters so that the user can give consent. |
| `UserPasswordExpired` | User's password has expired. | Call `acquireToken` with interactive parameter so the user can reset their password. |
| `None` | Further details are provided. The condition may be resolved by user interaction during the interactive authentication flow. | Call `acquireToken` with interactive parameters. |

### Code Example

```java
IAuthenticationResult result;
try {
PublicClientApplication application = PublicClientApplication
.builder("clientId")
.b2cAuthority("authority")
.build();

SilentParameters parameters = SilentParameters
.builder(Collections.singleton("scope"))
.build();

result = application.acquireTokenSilently(parameters).join();
}
catch (Exception ex){
if(ex instanceof MsalInteractionRequiredException){
// AcquireToken by either AuthorizationCodeParameters or DeviceCodeParameters
} else{
// Log and handle exception accordingly
}
}
```

## Conditional Access and claims challenges

When getting tokens silently, your application may receive errors when a [Conditional Access claims challenge](/azure/active-directory/develop/v2-conditional-access-dev-guide), such as MFA policy, is required by the API you're trying to access.

The pattern for handling this error is to interactively acquire a token using MSAL. This prompts the user and gives them the opportunity to satisfy the required Conditional Access policy.

In certain cases when calling an API requiring Conditional Access, you can receive a claims challenge in the error from the API. For instance if the Conditional Access policy is to have a managed device (Intune) the error will be something like [AADSTS53000: Your device is required to be managed to access this resource](/azure/active-directory/develop/reference-error-codes) or something similar. In this case, you can pass the claims in the acquire token call so that the user is prompted to satisfy the appropriate policy.

## Retrying after errors and exceptions

You're expected to implement your own retry policies when calling MSAL. MSAL makes HTTP calls to the Microsoft Entra ID service, and occasionally failures can occur. For example the network can go down or the server is overloaded.

### HTTP 429

When the Service Token Server (STS) is overloaded with too many requests, it returns HTTP error 429 with a hint about how long until you can try again in the `Retry-After` response field.

## Next steps

Consider enabling [Logging in MSAL for Java](msal-logging-java.md) to help you diagnose and debug issues.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: Get & remove accounts from the token cache (MSAL4j)
description: Learn how to view and remove accounts from the token cache using the Microsoft Authentication Library for Java.
---

# Get and remove accounts from the token cache using MSAL for Java

MSAL for Java provides an in-memory token cache by default. The in-memory token cache persists for the duration of the application execution.

## See which accounts are in the cache

You can check what accounts are in the cache by calling `PublicClientApplication.getAccounts()` as shown in the following example:

```java
PublicClientApplication pca = new PublicClientApplication.Builder(
labResponse.getAppId()).
authority(TestConstants.ORGANIZATIONS_AUTHORITY).
build();

Set<IAccount> accounts = pca.getAccounts().join();
```

## Remove accounts from the cache

To remove an account from the cache, find the account that needs to be removed and then call `PublicClientApplication.removeAccount()` as shown in the following example:

```java
Set<IAccount> accounts = pca.getAccounts().join();

IAccount accountToBeRemoved = accounts.stream().filter(
x -> x.username().equalsIgnoreCase(
UPN_OF_USER_TO_BE_REMOVED)).findFirst().orElse(null);

pca.removeAccount(accountToBeRemoved).join();
```

## Learn more

If you are using MSAL for Java, learn about [Custom token cache serialization in MSAL for Java](msal-java-token-cache-serialization.md).
Loading

0 comments on commit ed652d4

Please sign in to comment.