Сообщение об ошибке
oidc: expected audience "api-client" got ["web-client"]
coreos/go-oidc (Go) — IDTokenVerifier.Verify
Что это означает
ID-токен подписан нужным провайдером, но его утверждение `aud` не содержит `ClientID`, заданный в `oidc.Config`. go-oidc реализует правило OpenID Connect, по которому ID-токен действителен только для клиента, которому он выдан; первое значение в кавычках — ваш `ClientID`, а список — аудитории токена.
Почему это происходит
Переслан ID-токен другого клиента
частоФронтенд отправляет свой ID-токен в API бэкенда, а тот проверяет его по собственному идентификатору клиента API. ID-токены предназначены для клиента, который их запросил; API следует принимать токены доступа.
Задан неверный идентификатор клиента
частоСкопирован идентификатор клиента из регистрации другого приложения или из другого окружения, либо вместо идентификатора указано имя секрета клиента. Правильное значение видно в `aud` токена.
Токен доступа проверяют как ID-токен
иногдаТокены доступа в формате JWT содержат в `aud` идентификатор API, а не идентификатор клиента. `IDTokenVerifier` по умолчанию ищет там идентификатор клиента, поэтому токены доступа не проходят проверку, если не проверять аудиторию самостоятельно.
Как исправить
- 1.
Используйте идентификатор клиента приложения, через которое вошёл пользователь
Для ID-токенов задайте именно тот идентификатор клиента, для которого выдан токен.
go verifier := provider.Verifier(&oidc.Config{ ClientID: os.Getenv("OIDC_CLIENT_ID"), // the client the user signed in to; must equal the token's aud }) idToken, err := verifier.Verify(ctx, rawIDToken) - 2.
Для токенов доступа к API проверяйте аудиторию API самостоятельно
`SkipClientIDCheck` отключает только встроенное сравнение с идентификатором клиента. Замените его явной проверкой идентификатора вашего API и никогда не отключайте проверку аудитории полностью.
go // Verifying a JWT access token for an API: check signature/issuer/expiry here, // then check the API audience yourself. verifier := provider.Verifier(&oidc.Config{SkipClientIDCheck: true}) tok, err := verifier.Verify(ctx, rawAccessToken) if err != nil { return err } if !slices.Contains(tok.Audience, "https://api.example.com") { return errors.New("token not issued for this API") }