From c148491539be316173d0c58124a4358599efaf6a Mon Sep 17 00:00:00 2001 From: Rujun Chen Date: Thu, 1 Jul 2021 15:46:34 +0800 Subject: [PATCH] In sample project, add content about client_credential. --- .../sample/aad/controller/HomeController.java | 8 ++- .../aad/controller/WebApiController.java | 59 +++++++++++-------- .../src/main/resources/application.yml | 6 +- .../src/main/resources/templates/index.html | 1 + .../README.md | 6 +- 5 files changed, 54 insertions(+), 26 deletions(-) diff --git a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server/src/main/java/com/azure/spring/sample/aad/controller/HomeController.java b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server/src/main/java/com/azure/spring/sample/aad/controller/HomeController.java index d3f44133bc9b..8f269c7bb7ce 100644 --- a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server/src/main/java/com/azure/spring/sample/aad/controller/HomeController.java +++ b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server/src/main/java/com/azure/spring/sample/aad/controller/HomeController.java @@ -17,7 +17,7 @@ public class HomeController { @ResponseBody @PreAuthorize("hasAuthority('SCOPE_WebApiB.ExampleScope')") public String file() { - return "Response from WebApiB."; + return "Response from webApiB."; } @GetMapping("/user") @@ -27,4 +27,10 @@ public String user() { return "User read success."; } + @GetMapping("/webapiB/clientCredential") + @ResponseBody + public String clientCredential() { + return "Response from webApiB: clientCredential"; + } + } diff --git a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/java/com/azure/spring/sample/aad/controller/WebApiController.java b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/java/com/azure/spring/sample/aad/controller/WebApiController.java index 8d20903c0785..f181a05d5665 100644 --- a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/java/com/azure/spring/sample/aad/controller/WebApiController.java +++ b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/java/com/azure/spring/sample/aad/controller/WebApiController.java @@ -13,48 +13,61 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.reactive.function.client.WebClient; - import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient; @Controller public class WebApiController { private static final Logger LOGGER = LoggerFactory.getLogger(WebApiController.class); - - private static final String CUSTOM_LOCAL_FILE_ENDPOINT = "http://localhost:8081/webapiA"; + private static final String WEB_API_A_URI = "http://localhost:8081/webapiA"; + private static final String WEB_API_B_URI = "http://localhost:8082/webapiB/clientCredential"; @Autowired private WebClient webClient; /** - * Call webapiA endpoint, combine all the response and return. - * @param webapiAClient authorized client for Custom + * Check whether webapiA is accessible. + * + * @param client authorized client for webapiA * @return Response webapiA data. */ @GetMapping("/webapp/webapiA/webapiB") @ResponseBody - public String callWebApi(@RegisteredOAuth2AuthorizedClient("webapiA") OAuth2AuthorizedClient webapiAClient) { - return callWebApiAEndpoint(webapiAClient); + public String webapiA(@RegisteredOAuth2AuthorizedClient("webapiA") OAuth2AuthorizedClient client) { + return canVisitUri(client, WEB_API_A_URI); + } + + /** + * Check whether webapiB/clientCredential is accessible. + * + * @param client authorized client for webapiB + * @return Response webapiA data. + */ + @GetMapping("/webapp/webapiB/clientCredential") + @ResponseBody + public String webapiB(@RegisteredOAuth2AuthorizedClient("webapiB") OAuth2AuthorizedClient client) { + return canVisitUri(client, WEB_API_B_URI); } /** - * Call webapiA endpoint - * @param webapiAClient Authorized Client - * @return Response string data. + * Check whether uri is accessible by provided client. + * + * @param client Authorized client. + * @param uri The request uri. + * @return "Get http response successfully." or "Get http response failed." */ - private String callWebApiAEndpoint(OAuth2AuthorizedClient webapiAClient) { - if (null != webapiAClient) { - String body = webClient - .get() - .uri(CUSTOM_LOCAL_FILE_ENDPOINT) - .attributes(oauth2AuthorizedClient(webapiAClient)) - .retrieve() - .bodyToMono(String.class) - .block(); - LOGGER.info("Response from webapiA : {}", body); - return "webapiA response " + (null != body ? "success." : "failed."); - } else { - return "webapiA response failed."; + private String canVisitUri(OAuth2AuthorizedClient client, String uri) { + if (null == client) { + return "Get response failed."; } + String body = webClient + .get() + .uri(uri) + .attributes(oauth2AuthorizedClient(client)) + .retrieve() + .bodyToMono(String.class) + .block(); + LOGGER.info("Response from {} : {}", uri, body); + return "Get response " + (null != body ? "successfully" : "failed"); } } diff --git a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/application.yml b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/application.yml index d6f3a3f79725..4aa176b645b4 100644 --- a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/application.yml +++ b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/application.yml @@ -18,6 +18,10 @@ azure: scopes: - https://graph.microsoft.com/User.Read - https://graph.microsoft.com/Directory.Read.All -# webapiA: +# webapiA: # This is used to demonstrate on-behalf-of function. Refs: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow # scopes: # - /Obo.WebApiA.ExampleScope +# webapiB: # This is used to demonstrate client_credentials type. Refs: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow +# scopes: +# - api:///.default +# authorization-grant-type: client_credentials diff --git a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/templates/index.html b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/templates/index.html index 1bcb455cdc17..43cfc3f0863d 100644 --- a/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/templates/index.html +++ b/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/src/main/resources/templates/index.html @@ -37,6 +37,7 @@

Azure Active Directory OAuth 2.0 Login with Spring Security

Graph Client | Arm Client | Obo Client | + Client Credential Client | diff --git a/sdk/spring/azure-spring-boot-starter-active-directory/README.md b/sdk/spring/azure-spring-boot-starter-active-directory/README.md index fddb6b743839..3f35ec03023b 100644 --- a/sdk/spring/azure-spring-boot-starter-active-directory/README.md +++ b/sdk/spring/azure-spring-boot-starter-active-directory/README.md @@ -274,6 +274,7 @@ This starter provides following properties: | **azure.activedirectory**.authorization-clients | A map configure the resource APIs the application is going to visit. Each item corresponding to one resource API the application is going to visit. In Spring code, each item corresponding to one OAuth2AuthorizedClient object| | **azure.activedirectory**.authorization-clients.{client-name}.scopes | API permissions of a resource server that the application is going to acquire. | | **azure.activedirectory**.authorization-clients.{client-name}.on-demand | This is used for incremental consent. The default value is false. If it's true, it's not consent when user login, when application needs the additional permission, incremental consent is performed with one OAuth2 authorization code flow.| +| **azure.activedirectory**.authorization-clients.{client-name}.authorization-grant-type | Type of authorization client. Supported types are [authorization_code] (default type for webapp), [on-behalf-of] (default type for resource-server), [client_credentials]. | | **azure.activedirectory**.base-uri | Base uri for authorization server, the default value is `https://login.microsoftonline.com/`. | | **azure.activedirectory**.client-id | Registered application ID in Azure AD. | | **azure.activedirectory**.client-secret | client secret of the registered application. | @@ -553,7 +554,7 @@ In [Resource server visiting other resource server] scenario(For better descript @GetMapping("/webapp/webapiA/webapiB") @ResponseBody public String callWebApi(@RegisteredOAuth2AuthorizedClient("webapiA") OAuth2AuthorizedClient webapiAClient) { - return callWebApiAEndpoint(webapiAClient); + return canVisitUri(client, WEB_API_A_URI); } ``` - webapiA: @@ -724,3 +725,6 @@ Please follow [instructions here] to build from source or contribute. [configure webapiB]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-resource-server/README.md#configure-web-api [configure webapp]: https://github.com/Azure/azure-sdk-for-java/blob/main/sdk/spring/azure-spring-boot-samples/azure-spring-boot-sample-active-directory-webapp/README.md#configure-access-other-resources-server [ms-identity-java-spring-tutorial]:https://github.com/Azure-Samples/ms-identity-java-spring-tutorial +[authorization_code]: https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow +[on-behalf-of]: https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow +[client_credentials]: https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow