PKCE 验证失败:代码与 Apache Shiro 和 Pac4j 不匹配

问题描述 投票:0回答:1

在尝试使用 Keycloak、Apache Shiro 和 Pac4j 与 Apache Zeppelin 集成进行身份验证时,我遇到了 PKCE 验证问题。我收到的错误是:

HTTP ERROR 500 javax.servlet.ServletException: org.pac4j.core.exception.TechnicalException: Bad token response, error=invalid_grant, description=PKCE verification failed: Code mismatch
URI:    /api/callback
STATUS: 500
MESSAGE:    javax.servlet.ServletException: org.pac4j.core.exception.TechnicalException: Bad token response, error=invalid_grant, description=PKCE verification failed: Code mismatch
SERVLET:    rest
CAUSED BY:  javax.servlet.ServletException: org.pac4j.core.exception.TechnicalException: Bad token response, error=invalid_grant, description=PKCE verification failed: Code mismatch
CAUSED BY:  org.pac4j.core.exception.TechnicalException: Bad token response, error=invalid_grant, description=PKCE verification failed: Code mismatch
Caused by:
javax.servlet.ServletException: org.pac4j.core.exception.TechnicalException: Bad token response, error=invalid_grant, description=PKCE verification failed: Code mismatch
    at org.apache.shiro.web.servlet.AdviceFilter.cleanup(AdviceFilter.java:196)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:148)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:458)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:373)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:370)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:154)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
    at org.apache.zeppelin.server.CorsFilter.doFilter(CorsFilter.java:64)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:234)
    at io.micrometer.core.instrument.binder.jetty.TimedHandler.handle(TimedHandler.java:120)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:516)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
    at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.pac4j.core.exception.TechnicalException: Bad token response, error=invalid_grant, description=PKCE verification failed: Code mismatch
    at org.pac4j.oidc.credentials.authenticator.OidcAuthenticator.executeTokenRequest(OidcAuthenticator.java:206)
    at org.pac4j.oidc.credentials.authenticator.OidcAuthenticator.validate(OidcAuthenticator.java:165)
    at org.pac4j.core.client.BaseClient.lambda$retrieveCredentials$0(BaseClient.java:75)
    at java.base/java.util.Optional.ifPresent(Optional.java:183)
    at org.pac4j.core.client.BaseClient.retrieveCredentials(BaseClient.java:72)
    at org.pac4j.core.client.IndirectClient.getCredentials(IndirectClient.java:145)
    at org.pac4j.core.engine.DefaultCallbackLogic.perform(DefaultCallbackLogic.java:75)
    at org.pac4j.jee.filter.CallbackFilter.internalFilter(CallbackFilter.java:71)
    at org.pac4j.jee.config.AbstractConfigFilter.doFilter(AbstractConfigFilter.java:72)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    ... 42 more
Powered by Jetty:// 9.4.52.v20230823

这是我的 shiro.ini:

[main]
roleAdminAuthGenerator = org.pac4j.core.authorization.generator.FromAttributesAuthorizationGenerator
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
securityManager.sessionManager.globalSessionTimeout = 86400000

### Define CodeChallengeMethod
#S256 = com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod
#S256.name = S256

### OIDC Pac4j Config
oidcConfig = org.pac4j.oidc.config.OidcConfiguration
oidcConfig.withState = false
oidcConfig.discoveryURI = http://localhost:8323/realms/zeppelin/.well-known/openid-configuration
oidcConfig.clientAuthenticationMethodAsString = client_secret_basic
oidcConfig.clientId = zeppelin-client
oidcConfig.secret = <secret>
oidcConfig.scope = openid
oidcConfig.useNonce = true
oidcConfig.responseType = code
oidcConfig.logoutUrl = http://localhost:8323/realms/zeppelin/protocol/openid-connect/logout

oidcClient = org.pac4j.oidc.client.OidcClient
oidcClient.name = oidcClient
oidcClient.configuration = $oidcConfig
oidcClient.authorizationGenerator = $roleAdminAuthGenerator

### Pac4J Client Details
clients = org.pac4j.core.client.Clients

requireRoleAdmin = org.pac4j.core.authorization.authorizer.RequireAnyRoleAuthorizer
requireRoleAdmin.elements = admin_role
requireRoleUser = org.pac4j.core.authorization.authorizer.RequireAnyRoleAuthorizer
requireRoleUser.elements = admin_role, user_role

### Pac4j Config
config = org.pac4j.core.config.Config
config.clients = $clients
config.authorizers = admin:$requireRoleAdmin, user:$requireRoleUser

### Pac4jRealm and SecurityFilter
pac4jRealm = io.buji.pac4j.realm.Pac4jRealm
pac4jRealm.principalNameAttribute = preferred_username
pac4jSubjectFactory = io.buji.pac4j.subject.Pac4jSubjectFactory

securityManager.realms = $pac4jRealm
securityManager.subjectFactory = $pac4jSubjectFactory
oidcSecurityFilter = org.pac4j.jee.filter.SecurityFilter
oidcSecurityFilter.clients = oidcClient
oidcSecurityFilter.config = $config

### Logout Filter
logoutFilter = org.pac4j.jee.filter.LogoutFilter
logoutFilter.localLogout = true
logoutFilter.centralLogout = true
logoutFilter.config = $config
logoutFilter.defaultUrl = http://localhost:8323/realms/zeppelin/protocol/openid-connect/logout

### Ajax Resolvers
ajaxRequestResolver = org.pac4j.core.http.ajax.DefaultAjaxRequestResolver
ajaxRequestResolver.addRedirectionUrlAsHeader = true
oidcClient.ajaxRequestResolver = $ajaxRequestResolver

### Callback Filters
callbackFilter = org.pac4j.jee.filter.CallbackFilter
callbackFilter.defaultUrl = http://localhost:8080
callbackFilter.config = $config

clients.callbackUrl = http://localhost:8080/api/callback
clients.clients = $oidcClient

[urls]
/api/version = anon
/api/callback = callbackFilter
/api/login/logout = logoutFilter
/** = oidcSecurityFilter

齐柏林飞艇版本:0.11.1 使用中的图书馆

asm-1.0.2.jar
buji-pac4j-8.1.0.jar
content-type-2.3.jar
javaee-pac4j-7.1.0.jar
json-smart-2.5.1.jar
lang-tag-1.7.jar
pac4j-config-5.7.6.jar
pac4j-core-5.7.6.jar
pac4j-http-5.7.6.jar
pac4j-javaee-5.7.6.jar
pac4j-oauth-5.7.6.jar
pac4j-oidc-5.7.6.jar
oauth2-oidc-sdk-11.13.jar

我在Google上搜索过,但发现之前没有人遇到过这个错误。

openid-connect apache-zeppelin shiro pac4j
1个回答
0
投票

事实上,错误来自 Keycloack,当 pac4j 想要将接收到的代码交换为访问令牌时,它会回复:

PKCE verification failed: Code mismatch

您可以尝试删除此配置吗:

oidcConfig.secret=xxx
? PKCE 不需要秘密。

© www.soinside.com 2019 - 2024. All rights reserved.