3 回答

TA貢獻1848條經驗 獲得超6個贊
我知道我參加聚會遲到了,但當前答案中缺少一些信息。
非法狀態異常:
provided in the configuration did not match the requested issuer
很可能是由于 @Dragana Le Mitova 已經在 issues-uri 屬性末尾的斜線提到的那樣引起的。這需要設置為:
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0
然后 Spring 將自動提取 OAuth 資源服務器的配置https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/.well-known/openid-configuration。
為了確保我們只接受來自 Azure 應用程序的 JWT,我們需要檢查 JWT 的受眾 (aud) 屬性。對于 Azure 應用程序,這通常與客戶端/應用程序 ID 相同。正如 @Wim Deblauwe 已經回答的那樣,這是通過JwtDecoder. Spring Security 甚至在他們的文檔中為我們提供了一個自定義 JWT 驗證器的示例,其中他們實現了受眾聲明檢查。這是通過在JwtDecoderbean 中提供我們自己的驗證器來完成的。
受眾(aud)聲明驗證器:
public class AudienceValidator implements OAuth2TokenValidator<Jwt> {
OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);
public OAuth2TokenValidatorResult validate(Jwt jwt) {
if (jwt.getAudience().contains("messaging")) {
return OAuth2TokenValidatorResult.success();
} else {
return OAuth2TokenValidatorResult.failure(error);
}
}
}
Jwt解碼器:
@Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoderJwkSupport jwtDecoder = (NimbusJwtDecoderJwkSupport)
JwtDecoders.withOidcIssuerLocation(issuerUri);
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator();
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
這與 @Wim Deblauwe 提供的答案略有不同,我們使用JwtValidators.createDefaultWithIssuer(issuerUri)而不是創建驗證器JwtValidators.createDefault()。這很重要,因為我們本質上要檢查 3 個 JWT 屬性:
到期日
發行人
觀眾
我們JwtValidators.createDefault()只為過期屬性創建一個驗證器。我們為JwtValidators.createDefaultWithIssuer(issuerUri)過期和發行者屬性創建驗證器。JwtValidators.createDefaultWithIssuer(issuerUri)也是 Spring Security 設置 issues-uri 屬性時的默認行為。
如果您想更深入地了解,我們目前添加自定義驗證器的方式是否是最佳方式正在進行討論。

TA貢獻1799條經驗 獲得超8個贊
在閱讀了Spring Security 文檔中的自定義令牌驗證器后,我添加了一個自定義驗證器來檢查受眾聲明,以確保令牌是為我自己的應用程序頒發的。為此,請創建此驗證器類:
private static class AudienceValidator implements OAuth2TokenValidator<Jwt> {
@Override
public OAuth2TokenValidatorResult validate(Jwt token) {
if (token.getAudience().contains("my-application-id-here")) {
return OAuth2TokenValidatorResult.success();
} else {
return OAuth2TokenValidatorResult.failure(
new OAuth2Error("invalid_token", "The audience is not as expected, got " + token.getAudience(),
null));
}
}
}
并通過JwtDecoder在配置類中聲明您自己的 bean來使用它WebSecurityConfigurerAdapter:
@Bean
public JwtDecoder jwtDecoder() {
NimbusJwtDecoder result = NimbusJwtDecoder.withJwkSetUri(properties.getJwt().getJwkSetUri()).build();
result.setJwtValidator(
new DelegatingOAuth2TokenValidator<Jwt>(
JwtValidators.createDefault(),
new AudienceValidator())
);
return result;
}
默認驗證器將檢查時間戳等內容。如果沒問題,AudienceValidator 將檢查受眾聲明。
注意:您在驗證器中傳遞的順序DelegatingOAuth2TokenValidator定義了 JWT 令牌的檢查順序。在此示例中,在觀眾之前檢查時間戳。如果你想讓觀眾先檢查,你需要把它放在構造函數的前面DelegatingOAuth2TokenValidator

TA貢獻1815條經驗 獲得超10個贊
我懷疑您在嘗試聲明自己的JwtDecoder光束時遇到的異常來自缺少的斜杠。
請注意,“請求的發行者”始終缺少尾部斜杠,即使在配置中明確指定了尾部斜杠。
按照規范的要求, Spring Security在附加之前會從頒發者 URI 中刪除所有尾部斜杠。但是,在獲取配置后,返回的配置的頒發者 URI 與問題 URI 的“清理”版本相匹配,而不是最初提供的版本。
由于fromOidcIssuerLocation()不知道最初提供的頒發者 URL,因此它會與 cleanIssuer 進行匹配,從而導致所描述的問題。解決這個問題的最簡單方法是在fromOidcIssuerLocation()中進行清理,然后仍然可以使用原始版本進行匹配。
另一條注釋與您提出的第一個問題相關。
如果我知道您的 API 標識符 + 您的租戶 ID,我可以使用客戶端憑據獲取您的 API 的訪問令牌!令牌不會包含范圍或角色,它不能。因此,檢查是否存在有效的委派權限(也稱為范圍)或有效的應用程序權限(在角色聲明中)至關重要。
看看這個特定的代碼。
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
TokenValidationParameters validationParameters = new TokenValidationParameters
{
// We accept both the App Id URI and the AppId of this service application
ValidAudiences = new[] { audience, clientId },
// Supports both the Azure AD V1 and V2 endpoint
ValidIssuers = new[] { issuer, $"{issuer}/v2.0" },
IssuerSigningKeys = signingKeys
};
添加回答
舉報