У меня есть то, что я считал типичным приложением с интерфейсом React и загрузкой Spring в качестве сервера. Я пытаюсь настроить безопасность, чтобы использовать активный каталог Azure для аутентификации и авторизации пользователей. Аутентификация работает, а авторизация нет
Часть пользовательского интерфейса проста и работает, я использую MSAL для аутентификации и получения учетной записи. Я вижу в журнале консоли, что с этой точки зрения все в порядке. Я также вижу следующее в запросе/ответе токена: https://login.microsoftonline.com/*{XX}*/oauth2/v2.0/token
scope: "User.Read profile openid email"
token_type: "Bearer"
У меня проблема в бэкэнде, я получаю следующую ошибку:
Failed to authorize filter invocation [GET /api/document/list] with attributes [hasAuthority('SCOPE_User.Read')] using AffirmativeBased [DecisionVoters=[org.springframework.security.web.access.expression.WebExpressionVoter@470b5213], AllowIfAllAbstainDecisions=false]
Sending JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@43ebd8ff, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]] to access denied handler since access is denied
Как вы могли видеть, по какой-то причине на сервере ресурсов мы не получаем области, к которым у пользователя есть доступ (т.е. User.Read)
Настройка весенней безопасности:
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
http.authorizeRequests((authorize) -> authorize
.mvcMatchers("/**").hasAuthority("SCOPE_User.Read") // .permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
}
В application.properties:
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://login.microsoftonline.com/{XX}/v2.0
Чтобы быть очень обидчивым, «бэкэнд» — это сервер ресурсов, а не клиент (клиент — это приложение React в вашем случае).
У меня недостаточно опыта работы с Azure AD, чтобы быть категоричным, но я подозреваю, что Microsoft не следует общепринятым практикам OpenID (.well-known/openid-configuration
доступ из URI эмитента и раскрытие JWKS_URI
), что приводит к тому, что Spring не разрешает открытый ключ авторизации правильно.
Вы пытались установить spring.security.oauth2.resourceserver.jwt.jwk-set-uri
вместо или в дополнение к spring.security.oauth2.resourceserver.jwt.issuer-uri
(issuer-uri
должно быть установлено точное значение, указанное в токене доступа iss
, даже косая черта в конце важна)?
Рад, что помог, жаль, что не решил
После долгих исследований я наконец понял, что запрос, который я выполнял в коде реакции, не имел правильного токена. Как это работает, вы должны сначала запросить токен входа, а затем запросить токен «области действия». У меня был токен входа, но не область действия, и поэтому я продолжал получать пустые предоставленные полномочия.
Очень помог этот сайт: https://jwt.ms/. Когда я поместил JWT в поле токена, он показал, что областей действия (scp) нет.
Вот как это должно выглядеть (скриншот из https://dev.to/czmiel24/configuring-scopes-in-azure-active-directory-part-1-3bio):
Это не было проблемой, но я голосую за, потому что это действительно отправило меня по пути, где я, наконец, понял это.