Skip to content

Commit

Permalink
Migrate Identity to azure-json (#41523)
Browse files Browse the repository at this point in the history
* msitoken

* AuthenticationRecord

* enable Feature.ALLOW_COMMENTS on the default json reader.

* VisualStudioCacheAccessor

* remove extra usings

* add ctor for easier serialization

* improve test

* msal cache part of IntelliJCacheAccessor

* refactor to remove JsonNode from IdentityClient

* HttpPipelineAdapter cleanup

Moved the two functions into IdentityUtil for testability.

* Fix cache file name

* remove test from wrong place

* bug fix for earlier refactor

* fix test

* Remove legacy Azure Toolkit login path

* Remove wrapper type for MSAL ClaimsRequest

This type existed to cover a functional hole in the base type that was fixed a while ago.

* fixup module-info

* remove final bits of kdbx support

* checkstyle

* update changelog

* update changelog

* linter fixes

* typo

* AuthenticationRecord cr feedback

* VisualStudioCacheAccessor feedback

* azure-json feedback

* pr feedback

* Update IntelliJCacheAccessorTests.java

* AuthenticationRecord feedback

* Update version_client to match main and have the correct unreleased module.

* add missing javadoc

* linter fixes

* MSIToken never gets serialized, so we can remove implementing the interface.

* remove unused variables

* If you've removed the interface you can't use the serializer adapter..

* Remove final `JacksonAdapter` usage

* Properly configure the reader for comments

* checkstyle
  • Loading branch information
billwert authored Sep 5, 2024
1 parent f71fbef commit a048c1f
Show file tree
Hide file tree
Showing 38 changed files with 592 additions and 2,150 deletions.
2 changes: 1 addition & 1 deletion eng/versioning/version_client.txt
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ io.clientcore:http-stress;1.0.0-beta.1;1.0.0-beta.1
# note: The unreleased dependencies will not be manipulated with the automatic PR creation code.
# In the pom, the version update tag after the version should name the unreleased package and the dependency version:
# <!-- {x-version-update;unreleased_com.azure:azure-core;dependency} -->
unreleased_com.azure:azure-identity;1.14.0-beta.2
unreleased_com.azure:azure-json;1.3.0-beta.1

unreleased_com.azure:azure-core-amqp;2.10.0-beta.1

Expand Down
2 changes: 2 additions & 0 deletions sdk/identity/azure-identity/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
### Features Added

### Breaking Changes
- Removed support in `IntelliJCredential` for legacy Azure Toolkit for IntelliJ versions. Please upgrade to latest if you are using 3.52 or below.

### Bugs Fixed
Fixed issue in `IntelliJCredential` blocking sign in [#39799](https://github.com/Azure/azure-sdk-for-java/issues/39799)

### Other Changes

Expand Down
2 changes: 2 additions & 0 deletions sdk/identity/azure-identity/TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ Get-AzAccessToken -ResourceUrl "https://management.core.windows.net"
|---|---|---|
|`CredentialUnavailableException` raised with message. "IntelliJ Authentication not available. Please log in with Azure Tools for IntelliJ plugin in the IDE."| The Credential was not able to locate the cached token to use for authentication. | Ensure that you login on the Azure Tools for IntelliJ plugin, that will populate the cache for the credential to pick up.

> Note: Azure Toolkit for IntelliJ version 3.53 and higher are supported by this credential. If you are using an older version, please update to the latest version.
## Troubleshoot `AzurePipelinesCredential` authentication issues

## Troubleshoot multi-tenant authentication issues
Expand Down
2 changes: 1 addition & 1 deletion sdk/identity/azure-identity/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-json</artifactId>
<version>1.2.0</version> <!-- {x-version-update;com.azure:azure-json;dependency} -->
<version>1.3.0-beta.1</version> <!-- {x-version-update;unreleased_com.azure:azure-json;dependency} -->
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

package com.azure.identity;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.azure.core.util.logging.ClientLogger;
import com.azure.json.JsonProviders;
import com.azure.json.JsonReader;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import reactor.core.publisher.Mono;

Expand All @@ -28,31 +31,35 @@
* @see InteractiveBrowserCredential
*/
public final class AuthenticationRecord {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

@JsonProperty("authority")
static final ClientLogger LOGGER = new ClientLogger(AuthenticationRecord.class);

private String authority;

@JsonProperty("homeAccountId")
private String homeAccountId;

@JsonProperty("tenantId")
private String tenantId;

@JsonProperty("username")
private String username;

@JsonProperty("clientId")
private String clientId;


AuthenticationRecord() { }

AuthenticationRecord(IAuthenticationResult authenticationResult, String tenantId, String clientId) {
authority = authenticationResult.account().environment();
homeAccountId = authenticationResult.account().homeAccountId();
username = authenticationResult.account().username();
this(authenticationResult.account().environment(),
authenticationResult.account().homeAccountId(),
authenticationResult.account().username(),
tenantId,
clientId);
}

AuthenticationRecord(String authority, String homeAccountId, String userName, String tenantId, String clientId) {
this.authority = authority;
this.homeAccountId = homeAccountId;
this.tenantId = tenantId;
this.username = userName;
this.clientId = clientId;
}

Expand Down Expand Up @@ -108,13 +115,9 @@ public String getUsername() {
* @return A {@link Mono} containing {@link Void}
*/
public Mono<OutputStream> serializeAsync(OutputStream outputStream) {
return Mono.defer(() -> {
try {
OBJECT_MAPPER.writeValue(outputStream, this);
} catch (IOException e) {
return Mono.error(e);
}
return Mono.just(outputStream);
return Mono.fromCallable(() -> {
serialize(outputStream);
return outputStream;
});
}

Expand All @@ -124,7 +127,17 @@ public Mono<OutputStream> serializeAsync(OutputStream outputStream) {
* @param outputStream The {@link OutputStream} to which the serialized record will be written to.
*/
public void serialize(OutputStream outputStream) {
serializeAsync(outputStream).block();
try (JsonWriter writer = JsonProviders.createWriter(outputStream)) {
writer.writeStartObject();
writer.writeStringField("authority", authority);
writer.writeStringField("homeAccountId", homeAccountId);
writer.writeStringField("tenantId", tenantId);
writer.writeStringField("username", username);
writer.writeStringField("clientId", clientId);
writer.writeEndObject();
} catch (IOException e) {
throw LOGGER.logExceptionAsError(new RuntimeException(e));
}
}

/**
Expand All @@ -134,16 +147,7 @@ public void serialize(OutputStream outputStream) {
* @return A {@link Mono} containing the {@link AuthenticationRecord} object.
*/
public static Mono<AuthenticationRecord> deserializeAsync(InputStream inputStream) {
return Mono.defer(() -> {
AuthenticationRecord authenticationRecord;
try {
authenticationRecord =
OBJECT_MAPPER.readValue(inputStream, AuthenticationRecord.class);
} catch (IOException e) {
return Mono.error(e);
}
return Mono.just(authenticationRecord);
});
return Mono.fromCallable(() -> deserialize(inputStream));
}

/**
Expand All @@ -153,6 +157,34 @@ public static Mono<AuthenticationRecord> deserializeAsync(InputStream inputStrea
* @return the {@link AuthenticationRecord} object.
*/
public static AuthenticationRecord deserialize(InputStream inputStream) {
return deserializeAsync(inputStream).block();
try (JsonReader jsonReader = JsonProviders.createReader(inputStream)) {
return jsonReader.readObject(reader -> {
String authority = null;
String homeAccountId = null;
String tenantId = null;
String username = null;
String clientId = null;
while (reader.nextToken() != JsonToken.END_OBJECT) {
String fieldName = reader.getFieldName();
reader.nextToken();
if ("authority".equals(fieldName)) {
authority = reader.getString();
} else if ("homeAccountId".equals(fieldName)) {
homeAccountId = reader.getString();
} else if ("tenantId".equals(fieldName)) {
tenantId = reader.getString();
} else if ("username".equals(fieldName)) {
username = reader.getString();
} else if ("clientId".equals(fieldName)) {
clientId = reader.getString();
} else {
reader.skipChildren();
}
}
return new AuthenticationRecord(authority, homeAccountId, username, tenantId, clientId);
});
} catch (IOException e) {
throw LOGGER.logExceptionAsError(new RuntimeException(e));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@
import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenCredential;
import com.azure.core.credential.TokenRequestContext;
import com.azure.core.util.CoreUtils;
import com.azure.core.util.logging.ClientLogger;
import com.azure.identity.implementation.IdentityClient;
import com.azure.identity.implementation.IdentityClientBuilder;
import com.azure.identity.implementation.IdentityClientOptions;
import com.azure.identity.implementation.IntelliJAuthMethodDetails;
import com.azure.identity.implementation.IntelliJCacheAccessor;
import com.azure.identity.implementation.MsalToken;
import com.azure.identity.implementation.util.IdentityConstants;
import com.azure.identity.implementation.util.LoggingUtil;
Expand Down Expand Up @@ -84,22 +81,6 @@ public class IntelliJCredential implements TokenCredential {
IdentityClientOptions options =
identityClientOptions == null ? new IdentityClientOptions() : identityClientOptions;

IntelliJCacheAccessor accessor =
new IntelliJCacheAccessor(options.getIntelliJKeePassDatabasePath());

IntelliJAuthMethodDetails authMethodDetails;
try {
authMethodDetails = accessor.getAuthDetailsIfAvailable();
} catch (Exception e) {
authMethodDetails = null;
}

if (CoreUtils.isNullOrEmpty(options.getAuthorityHost())) {
String azureEnv = authMethodDetails != null ? authMethodDetails.getAzureEnv() : "";
String cloudInstance = accessor.getAzureAuthHost(azureEnv);
options.setAuthorityHost(cloudInstance);
}

String tenant = tenantId;

if (tenant == null) {
Expand Down

This file was deleted.

Loading

0 comments on commit a048c1f

Please sign in to comment.