You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Outlook个人日历遇属性缺失及权限问题求助

Spring Boot + Azure AD + MS Graph:个人Outlook账户登录时提示Missing attribute 'name'错误

我正在构建一个Spring Boot Java应用,用来获取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

Azure门户中已将应用的支持账户类型设置为“任何组织目录中的账户(多租户Azure AD目录)和个人Microsoft账户(如Skype、Xbox)”,tenant-id设为common以支持任意Outlook个人账户。

测试代码

为验证MS Graph Calendar API的访问权限,我添加了以下代码:

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

问题现象

使用与Azure门户登录相同的个人账户(同时是应用注册租户的管理员账户)可以成功连接并获取日历事件,但使用另一个非租户内的测试用Outlook个人账户登录时失败。我不清楚个人Microsoft账户所属租户,也不知道如何向其添加服务主体。

错误栈

报错信息如下:

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]

疑问

我猜测问题是Microsoft身份平台不允许该测试账户连接应用,因为应用的服务主体未存储在其租户中。请问如何解决这个问题?我当前的实现方法是否正确?是否需要放弃Spring提供的OAuth2Client、AzureActiveDirectory库,自行构建OAuth2.0客户端?

内容的提问来源于stack exchange,提问作者Vyassa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:01:02