diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4aa43c5d..85b4861d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.2.1" + ".": "3.3.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c386ad..f98daa20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.3.0](https://github.com/microsoftgraph/msgraph-sdk-java-core/compare/v3.2.1...v3.3.0) (2024-09-30) + + +### Features + +* support authorization handler in middleware pipeline ([e0b5675](https://github.com/microsoftgraph/msgraph-sdk-java-core/commit/e0b56758d869a8621db3125d950dbe904777c833)) + ## [3.2.1](https://github.com/microsoftgraph/msgraph-sdk-java-core/compare/v3.2.0...v3.2.1) (2024-09-09) diff --git a/README.md b/README.md index 10c7c2bf..7389b92f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ repositories { dependencies { // Include the sdk as a dependency // x-release-please-start-version - implementation 'com.microsoft.graph:microsoft-graph-core:3.2.1' + implementation 'com.microsoft.graph:microsoft-graph-core:3.3.0' // x-release-please-end // This dependency is only needed if you are using the TokenCredentialAuthProvider implementation 'com.azure:azure-identity:1.11.0' @@ -40,7 +40,7 @@ Add the dependency in `dependencies` in pom.xml com.microsoft.graph microsoft-graph-core - 3.2.1 + 3.3.0 com.azure @@ -59,23 +59,23 @@ The nature of the Graph API is such that the SDK needs quite a large set of clas Register your application by following the steps at [Register your app with the Microsoft Identity Platform](https://docs.microsoft.com/graph/auth-register-app-v2). -### 2.2 Create an IAuthenticationProvider object +### 2.2 Create an AuthenticationProvider object -An instance of the **HttpClients** class handles building client. To create a new instance of this class, you need to provide an instance of `IAuthenticationProvider`, which can authenticate requests to Microsoft Graph. +[Initialize an `AuthenticationProvider`](https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?view=graph-rest-1.0&tabs=java) based on your preferred authentication flow -For an example of how to get an authentication provider, see [choose a Microsoft Graph authentication provider](https://docs.microsoft.com/graph/sdks/choose-authentication-providers?tabs=Java). +### 2.3 Get a OkHttpClient object -### 2.3 Get a HttpClients object +You must get an **OkHttpClient** object to make requests against the service. -You must get a **HttpClients** object to make requests against the service. +Using the `GraphClientFactory`, you can initialize an `OkHttpClient` pre-configured for use with Microsoft Graph ```java -OkHttpClient client = HttpClients.createDefault(iAuthenticationProvider); +OkHttpClient client = GraphClientFactory.create(authenticationProvider).build(); ``` ## 3. Make requests against the service -After you have a HttpClients that is authenticated, you can begin making calls against the service. The requests against the service look like our [REST API](https://developer.microsoft.com/en-us/graph/docs/concepts/overview). +After you have an OkHttpClient that is authenticated, you can begin making calls against the service. The requests against the service look like our [REST API](https://developer.microsoft.com/en-us/graph/docs/concepts/overview). ### 3.1 Get the user's details diff --git a/SECURITY.md b/SECURITY.md index f7b89984..e138ec5d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,20 +1,20 @@ - + ## Security -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. ## Reporting Security Issues **Please do not report security vulnerabilities through public GitHub issues.** -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: @@ -28,7 +28,7 @@ Please include the requested information listed below (as much as you can provid This information will help us triage your report more quickly. -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. ## Preferred Languages @@ -36,6 +36,6 @@ We prefer all communications to be in English. ## Policy -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). - \ No newline at end of file + diff --git a/android/build.gradle b/android/build.gradle index 7d3f250e..517d219f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,8 +5,8 @@ buildscript { } dependencies { - classpath "com.gradle:gradle-enterprise-gradle-plugin:3.18" - classpath "com.android.tools.build:gradle:8.6.0" + classpath "com.gradle:gradle-enterprise-gradle-plugin:3.18.1" + classpath "com.android.tools.build:gradle:8.6.1" classpath "com.github.ben-manes:gradle-versions-plugin:0.51.0" } } diff --git a/build.gradle b/build.gradle index bf7dfe51..64c6eb49 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'maven-publish' id 'signing' id 'jacoco' - id 'com.github.spotbugs' version '6.0.22' + id 'com.github.spotbugs' version '6.0.23' id "org.sonarqube" version "5.1.0.4882" id 'io.github.gradle-nexus.publish-plugin' version '2.0.0' } diff --git a/gradle.properties b/gradle.properties index 45bcd865..16397215 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,10 +27,10 @@ mavenArtifactId = microsoft-graph-core mavenMajorVersion = 3 # x-release-please-end # x-release-please-start-minor -mavenMinorVersion = 2 +mavenMinorVersion = 3 # x-release-please-end # x-release-please-start-patch -mavenPatchVersion = 1 +mavenPatchVersion = 0 # x-release-please-end mavenArtifactSuffix = diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 6c69c6f6..66648e3a 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -1,24 +1,24 @@ dependencies { // Use JUnit test framework - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.0' - testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.0' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.0' - testImplementation 'org.mockito:mockito-core:5.13.0' - testImplementation 'io.opentelemetry:opentelemetry-api:1.42.0' - testImplementation 'io.opentelemetry:opentelemetry-context:1.42.0' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.1' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.1' + testImplementation 'org.mockito:mockito-core:5.14.0' + testImplementation 'io.opentelemetry:opentelemetry-api:1.42.1' + testImplementation 'io.opentelemetry:opentelemetry-context:1.42.1' testImplementation 'io.github.std-uritemplate:std-uritemplate:1.0.6' implementation 'com.google.code.gson:gson:2.11.0' implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1' api 'com.squareup.okhttp3:okhttp:4.12.0' - api 'com.azure:azure-core:1.51.0' + api 'com.azure:azure-core:1.52.0' - api 'com.microsoft.kiota:microsoft-kiota-abstractions:1.3.0' - api 'com.microsoft.kiota:microsoft-kiota-authentication-azure:1.3.0' - implementation 'com.microsoft.kiota:microsoft-kiota-http-okHttp:1.3.0' - implementation 'com.microsoft.kiota:microsoft-kiota-serialization-json:1.3.0' - implementation 'com.microsoft.kiota:microsoft-kiota-serialization-text:1.3.0' - implementation 'com.microsoft.kiota:microsoft-kiota-serialization-form:1.3.0' - implementation 'com.microsoft.kiota:microsoft-kiota-serialization-multipart:1.3.0' + api 'com.microsoft.kiota:microsoft-kiota-abstractions:1.5.0' + api 'com.microsoft.kiota:microsoft-kiota-authentication-azure:1.5.0' + implementation 'com.microsoft.kiota:microsoft-kiota-http-okHttp:1.5.0' + implementation 'com.microsoft.kiota:microsoft-kiota-serialization-json:1.5.0' + implementation 'com.microsoft.kiota:microsoft-kiota-serialization-text:1.5.0' + implementation 'com.microsoft.kiota:microsoft-kiota-serialization-form:1.5.0' + implementation 'com.microsoft.kiota:microsoft-kiota-serialization-multipart:1.5.0' } diff --git a/pom.xml b/pom.xml index 7c467b09..aeaeb64a 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.microsoft.graph microsoft-graph-core - 3.2.1 + 3.3.0 pom @@ -32,18 +32,18 @@ com.azure azure-core - 1.51.0 + 1.52.0 org.junit.jupiter junit-jupiter-api - 5.11.0 + 5.11.1 test org.junit.jupiter junit-jupiter-params - 5.11.0 + 5.11.1 test diff --git a/src/main/java/com/microsoft/graph/core/CoreConstants.java b/src/main/java/com/microsoft/graph/core/CoreConstants.java index b8dadec8..0c19f723 100644 --- a/src/main/java/com/microsoft/graph/core/CoreConstants.java +++ b/src/main/java/com/microsoft/graph/core/CoreConstants.java @@ -16,10 +16,10 @@ private static class VersionValues { private static final int MAJOR = 3; // x-release-please-end // x-release-please-start-minor - private static final int MINOR = 2; + private static final int MINOR = 3; // x-release-please-end // x-release-please-start-patch - private static final int PATCH = 1; + private static final int PATCH = 0; // x-release-please-end } diff --git a/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java b/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java index 7833952a..baa38bd7 100644 --- a/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java +++ b/src/main/java/com/microsoft/graph/core/requests/GraphClientFactory.java @@ -3,7 +3,9 @@ import com.microsoft.graph.core.CoreConstants; import com.microsoft.graph.core.requests.middleware.GraphTelemetryHandler; import com.microsoft.graph.core.requests.options.GraphClientOption; +import com.microsoft.kiota.authentication.BaseBearerTokenAuthenticationProvider; import com.microsoft.kiota.http.KiotaClientFactory; +import com.microsoft.kiota.http.middleware.AuthorizationHandler; import com.microsoft.kiota.http.middleware.UrlReplaceHandler; import com.microsoft.kiota.http.middleware.options.UrlReplaceHandlerOption; import okhttp3.Interceptor; @@ -37,6 +39,33 @@ public static OkHttpClient.Builder create() { public static OkHttpClient.Builder create(@Nonnull Interceptor... interceptors) { return create(new GraphClientOption(), interceptors); } + + /** + * OkHttpClient Builder for Graph with specified Interceptors + * @param interceptors desired interceptors for use in requests. + * @return an OkHttpClient Builder instance. + */ + @Nonnull + public static OkHttpClient.Builder create(@Nonnull List interceptors) { + return create(new GraphClientOption(), interceptors.toArray(new Interceptor[0])); + } + + /** + * OkHttpClient Builder for Graph with specified AuthenticationProvider. + * Adds an AuthorizationHandler to the OkHttpClient Builder. + * @param authenticationProvider the AuthenticationProvider to use for requests. + * @return an OkHttpClient Builder instance. + */ + @Nonnull + public static OkHttpClient.Builder create(@Nonnull BaseBearerTokenAuthenticationProvider authenticationProvider) { + final GraphClientOption graphClientOption = new GraphClientOption(); + final Interceptor[] interceptors = createDefaultGraphInterceptors(graphClientOption); + final ArrayList interceptorList = new ArrayList<>(Arrays.asList(interceptors)); + interceptorList.add(new AuthorizationHandler(authenticationProvider)); + graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.AUTH_HANDLER_FLAG); + return create(graphClientOption, interceptorList); + } + /** * OkHttpClient Builder for Graph with specified Interceptors and GraphClientOption. * @@ -60,6 +89,18 @@ public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClient } return builder; } + + /** + * OkHttpClient Builder for Graph with specified Interceptors and GraphClientOption. + * @param graphClientOption the GraphClientOption for use in requests. + * @param interceptors desired interceptors for use in requests. + * @return an OkHttpClient Builder instance. + */ + @Nonnull + public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClientOption, @Nonnull List interceptors) { + return create(graphClientOption, interceptors.toArray(new Interceptor[0])); + } + /** * The OkHttpClient Builder with optional GraphClientOption * @@ -92,6 +133,5 @@ private static void addDefaultFeatureUsages(GraphClientOption graphClientOption) graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.RETRY_HANDLER_FLAG); graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.REDIRECT_HANDLER_FLAG); graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.URL_REPLACEMENT_FLAG); - graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.BATCH_REQUEST_FLAG); } } diff --git a/src/test/java/com/microsoft/graph/core/requests/GraphClientFactoryTest.java b/src/test/java/com/microsoft/graph/core/requests/GraphClientFactoryTest.java new file mode 100644 index 00000000..fcc2972b --- /dev/null +++ b/src/test/java/com/microsoft/graph/core/requests/GraphClientFactoryTest.java @@ -0,0 +1,56 @@ +package com.microsoft.graph.core.requests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.net.URI; + +import org.junit.jupiter.api.Test; + +import com.microsoft.graph.core.authentication.AzureIdentityAccessTokenProvider; +import com.microsoft.graph.core.authentication.AzureIdentityAuthenticationProvider; +import com.microsoft.kiota.authentication.AccessTokenProvider; +import com.microsoft.kiota.authentication.AllowedHostsValidator; +import com.microsoft.kiota.authentication.BaseBearerTokenAuthenticationProvider; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +class GraphClientFactoryTest { + + private static final String ACCESS_TOKEN_STRING = "token"; + + @Test + void testCreateWithAuthenticationProvider() throws IOException { + final BaseBearerTokenAuthenticationProvider mockAuthenticationProvider = + getMockAuthenticationProvider(); + OkHttpClient graphClient = GraphClientFactory.create(mockAuthenticationProvider).addInterceptor(new MockResponseHandler()).build(); + + Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me").build(); + Response response = graphClient.newCall(request).execute(); + + assertEquals(200, response.code()); + assertNotNull(response.request()); + assertTrue(response.request().headers().names().contains("Authorization")); + assertEquals("Bearer " + ACCESS_TOKEN_STRING, response.request().header("Authorization")); + } + + private static BaseBearerTokenAuthenticationProvider getMockAuthenticationProvider() { + final AccessTokenProvider mockAccessTokenProvider = mock(AzureIdentityAccessTokenProvider.class); + when(mockAccessTokenProvider.getAuthorizationToken(any(URI.class), anyMap())) + .thenReturn(ACCESS_TOKEN_STRING); + when(mockAccessTokenProvider.getAllowedHostsValidator()).thenReturn(new AllowedHostsValidator("graph.microsoft.com")); + final AzureIdentityAuthenticationProvider mockAuthenticationProvider = + mock(AzureIdentityAuthenticationProvider.class); + when(mockAuthenticationProvider.getAccessTokenProvider()) + .thenReturn(mockAccessTokenProvider); + return mockAuthenticationProvider; + } +} diff --git a/src/test/java/com/microsoft/graph/core/requests/MockResponseHandler.java b/src/test/java/com/microsoft/graph/core/requests/MockResponseHandler.java new file mode 100644 index 00000000..272fc9b0 --- /dev/null +++ b/src/test/java/com/microsoft/graph/core/requests/MockResponseHandler.java @@ -0,0 +1,50 @@ +package com.microsoft.graph.core.requests; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.Buffer; + +class MockResponseHandler implements Interceptor { + + private int statusCode; + + public MockResponseHandler(int statusCode) { + this.statusCode = statusCode; + } + + public MockResponseHandler() { + this.statusCode = 200; + } + + @Override + public Response intercept(Chain chain) throws IOException { + final var request = chain.request(); + final var requestBody = request.body(); + if (request != null && requestBody != null) { + final var buffer = new Buffer(); + requestBody.writeTo(buffer); + return new Response.Builder() + .code(this.statusCode) + .message("OK") + .protocol(Protocol.HTTP_1_1) + .request(request) + .body( + ResponseBody.create( + buffer.readByteArray(), MediaType.parse("application/json"))) + .build(); + } + return new Response.Builder() + .code(this.statusCode) + .message("OK") + .protocol(Protocol.HTTP_1_1) + .request(request) + .body(ResponseBody.create("", MediaType.parse("application/json"))) + .build(); + } + +}