Как интегрировать Java-приложение Spring Boot с календарем Outlook для пользователей личной учетной записи MS?

Идея состоит в том, чтобы создать Java-приложение Spring Boot, с помощью которого мы можем получать данные календаря владельца личной учетной записи MS Outlook, например, предстоящие события. Основываясь на первоначальных исследованиях, я обнаружил, что MS-Graph API является ответом на то же самое, и я начал с этого руководства в качестве начального кода.

Мой файл application.yml выглядит так:

       spring:
      cloud:
        azure:
          active-directory:
            enabled: true
            profile:
              tenant-id: common
            credential:
              client-id: <from azure portal>
              client-secret: <from azure portal>
            authorization-clients:
              graph:
                scopes:
                 - https://graph.microsoft.com/User.Read
                 - https://graph.microsoft.com/Calendars.Read
                 - https://graph.microsoft.com/Calendars.ReadWrite
                 - https://graph.microsoft.com/Analytics.Read

tenant-id устанавливается общим, так как я хочу подключиться к любому владельцу личной учетной записи Outlook. На портале Azure поддерживаются следующие типы учетных записей: «Учетные записи в любом организационном каталоге (любой каталог Azure AD — мультитенант) и личные учетные записи Microsoft (например, Skype, Xbox)». Введите описание изображения здесь.

Чтобы проверить, могу ли я обратиться к API календаря MS-Graph, я добавил приведенный ниже код (взято отсюда ) :

      EventCollectionPage events = graphClient.me().calendar().events()
    .buildRequest()
    .get();

Я мог подключиться к календарю Outlook и получить события для своей учетной записи, которая оказывается той же учетной записью, с которой осуществляется доступ к порталу Azure. Таким образом, моя личная учетная запись [email protected] также является учетной записью администратора арендатора, в котором зарегистрировано приложение.

Но когда я пытаюсь подключиться к другой личной учетной записи Outlook, созданной мной, и я добавил некоторые события в связанный календарь для целей тестирования, у меня ничего не получается. Эта новая личная учетная запись Outlook, безусловно, не находится в арендаторе, в котором зарегистрировано приложение, я не очень уверен, в какой арендатор входят личные учетные записи MS и как добавить к ним сервисных принципалов.

После настройки регистрации приложения для всех учетных записей на портале Azure и создания общего идентификатора арендатора в моем файле application.yml я ожидал подключения всех личных учетных записей, кто бы ни подписался на приложение Java, но столкнулся со следующими ошибками. Похоже, что платформа Microsoft Identity не позволяет этому другому пользователю подключить свой календарь к моему приложению Java, поскольку принципы службы моего приложения не хранятся в клиенте владельца личной учетной записи. Но как это сделать? Верен ли мой подход к проблеме, или я должен вместо использования библиотек Spring (OAuth2Client, AzureActiveDirectory) предпочесть создание клиента OAuth2.0 самостоятельно, достигая конечных точек /authorize и /token самостоятельно, хотя MS не рекомендует это, поскольку упомянуто здесь ?

      java.lang.IllegalArgumentException: Missing attribute 'name' in attributes
at org.springframework.security.oauth2.core.user.DefaultOAuth2User.<init>(DefaultOAuth2User.java:72) ~[spring-security-oauth2-core-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser.<init>(DefaultOidcUser.java:93) ~[spring-security-oauth2-core-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser.<init>(DefaultOidcUser.java:67) ~[spring-security-oauth2-core-5.6.7.jar:5.6.7]
at com.azure.spring.cloud.autoconfigure.aad.implementation.webapp.AadOAuth2UserService.loadUser(AadOAuth2UserService.java:134) ~[spring-cloud-azure-autoconfigure-4.3.0.jar:4.3.0]
at com.azure.spring.cloud.autoconfigure.aad.implementation.webapp.AadOAuth2UserService.loadUser(AadOAuth2UserService.java:52) ~[spring-cloud-azure-autoconfigure-4.3.0.jar:4.3.0]
at org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider.authenticate(OidcAuthorizationCodeAuthenticationProvider.java:156) ~[spring-security-oauth2-client-5.6.7.jar:5.6.7]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182) ~[spring-security-core-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:195) ~[spring-security-oauth2-client-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:223) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:213) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:178) ~[spring-security-oauth2-client-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar:5.3.22]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221) ~[spring-security-web-5.6.7.jar:5.6.7]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186) ~[spring-security-web-5.6.7.jar:5.6.7]

2 ответа

spring-cloud-azure-starter-active-directoryпредназначен для поддержки. Поддерживается ли, пока не уверен. Это отслеживается в этом выпуске GitHub .

Для разницы междуWork/School accountиPersonal account, пожалуйста, обратитесь к этой странице .

Используйте этот пример, чтобы узнать, как вызвать график

Физические лица являются администраторами своих личных счетов. Когда они войдут в ваше приложение, появится список действий, на которые им необходимо дать согласие, прежде чем они смогут использовать ваше приложение. В вашем случае одним из них будет что-то вроде «читать календарь». Затем человек предоставит вашему приложению возможность читать свой календарь Outlook. Надеюсь, это поможет Вьясе.