does not match one of the registered values異常原因及び対応方式
いじょうげんしょう
OAuth 2をSSOとして使用する場合、クライアントは統合認証センターにアクセスし、検証に合格し、リダイレクトが戻った後、次の問題が発生する可能性があります OAuth Error error="invalid_grant",error_description=“Invalid redirect: http://localhost:8082/login does not match one of the registered values.”
ソリューション
このとき、リダイレクトアドレスのプロトコル、ドメイン名、ポートが認証サーバに登録されているリダイレクトアドレスと一致しているかどうかを確認する必要があります.一致しない場合は、複数のドメイン名を認証サーバに構成する必要があります.例えば、認証サーバの構成
このとき、クライアントが次の2つのアドレスにアクセスすれば、統合認証センターにリダイレクトできます. http://127.0.0.1:8082/index http://localhost:8082/indexしかし、2つ目を使用すると、次のインタフェースが表示されます.なぜなら、私のhostと構成が一致していないためです.私のhostは127.0.0.1を構成しています.
の原因となる
なぜこのような状況が発生したのかをコードから解析します.具体的な論理はJAvaで
一致するかどうかを検出するロジック
OAuth 2をSSOとして使用する場合、クライアントは統合認証センターにアクセスし、検証に合格し、リダイレクトが戻った後、次の問題が発生する可能性があります OAuth Error error="invalid_grant",error_description=“Invalid redirect: http://localhost:8082/login does not match one of the registered values.”
ソリューション
このとき、リダイレクトアドレスのプロトコル、ドメイン名、ポートが認証サーバに登録されているリダイレクトアドレスと一致しているかどうかを確認する必要があります.一致しない場合は、複数のドメイン名を認証サーバに構成する必要があります.例えば、認証サーバの構成
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client1")
.secret(passwordEncoder.encode("client1"))
.autoApprove(true)
.redirectUris("http://127.0.0.1:8082/index")
.scopes("admin")
.accessTokenValiditySeconds(7200)
.authorizedGrantTypes("authorization_code");
}
このとき、クライアントが次の2つのアドレスにアクセスすれば、統合認証センターにリダイレクトできます.
の原因となる
なぜこのような状況が発生したのかをコードから解析します.具体的な論理はJAvaで
/**
* Attempt to match one of the registered URIs to the that of the requested one.
*
* @param redirectUris the set of the registered URIs to try and find a match. This cannot be null or empty.
* @param requestedRedirect the URI used as part of the request
* @return redirect uri
* @throws RedirectMismatchException if no match was found
*/
private String obtainMatchingRedirect(Set<String> redirectUris, String requestedRedirect) {
Assert.notEmpty(redirectUris, "Redirect URIs cannot be empty");
//
if (redirectUris.size() == 1 && requestedRedirect == null) {
return redirectUris.iterator().next();
}
// ,
for (String redirectUri : redirectUris) {
// , does not match one of the registered values
if (requestedRedirect != null && redirectMatches(requestedRedirect, redirectUri)) {
// Initialize with the registered redirect-uri
UriComponentsBuilder redirectUriBuilder = UriComponentsBuilder.fromUriString(redirectUri);
UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build();
if (this.matchSubdomains) {
redirectUriBuilder.host(requestedRedirectUri.getHost());
}
if (!this.matchPorts) {
redirectUriBuilder.port(requestedRedirectUri.getPort());
}
redirectUriBuilder.replaceQuery(requestedRedirectUri.getQuery()); // retain additional params (if any)
redirectUriBuilder.fragment(null);
return redirectUriBuilder.build().toUriString();
}
}
throw new RedirectMismatchException("Invalid redirect: " + requestedRedirect
+ " does not match one of the registered values.");
}
一致するかどうかを検出するロジック
/**
* Whether the requested redirect URI "matches" the specified redirect URI. For a URL, this implementation tests if
* the user requested redirect starts with the registered redirect, so it would have the same host and root path if
* it is an HTTP URL. The port, userinfo, query params also matched. Request redirect uri path can include
* additional parameters which are ignored for the match
*
* For other (non-URL) cases, such as for some implicit clients, the redirect_uri must be an exact match.
*
* @param requestedRedirect The requested redirect URI.
* @param redirectUri The registered redirect URI.
* @return Whether the requested redirect URI "matches" the specified redirect URI.
*/
protected boolean redirectMatches(String requestedRedirect, String redirectUri) {
UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build();
UriComponents registeredRedirectUri = UriComponentsBuilder.fromUriString(redirectUri).build();
// scheme
boolean schemeMatch = isEqual(registeredRedirectUri.getScheme(), requestedRedirectUri.getScheme());
//
boolean userInfoMatch = isEqual(registeredRedirectUri.getUserInfo(), requestedRedirectUri.getUserInfo());
// host
boolean hostMatch = hostMatches(registeredRedirectUri.getHost(), requestedRedirectUri.getHost());
//
boolean portMatch = matchPorts ? registeredRedirectUri.getPort() == requestedRedirectUri.getPort() : true;
// path
boolean pathMatch = isEqual(registeredRedirectUri.getPath(),
StringUtils.cleanPath(requestedRedirectUri.getPath()));
//
boolean queryParamMatch = matchQueryParams(registeredRedirectUri.getQueryParams(),
requestedRedirectUri.getQueryParams());
//
return schemeMatch && userInfoMatch && hostMatch && portMatch && pathMatch && queryParamMatch;
}