OpenID Connect authentication on TIBCO Spotfire server fails with the error "Signed JWT rejected: Another algorithm expected, or no matching key(s) found"

OpenID Connect authentication on TIBCO Spotfire server fails with the error "Signed JWT rejected: Another algorithm expected, or no matching key(s) found"

book

Article ID: KB0075881

calendar_today

Updated On:

Products Versions
Spotfire Server 7.8 and higher

Description

With OpenID Connect authentication enabled on TIBCO Spotfire Server, you may see the following error in server.log when authentication fails.

WARN 2020-03-04T02:13:19,043-0600 [unknown, #16, #106] auth.oidc.IdTokenKeySelector: Found unexpected JWS algorithm (alg) in ID token: HS256
WARN 2020-03-04T02:13:19,043-0600 [unknown, #16, #106] auth.oidc.OidcAuthenticator: OpenID Connect authentication failed
com.spotfire.server.security.auth.oidc.OidcException: ID token validation failed
    at com.spotfire.server.security.auth.oidc.TokenEndpointResponse.validateIdToken(TokenEndpointResponse.java:207) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.auth.oidc.TokenEndpointResponse.parse(TokenEndpointResponse.java:153) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.auth.oidc.OidcAuthenticator.callTokenEndpoint(OidcAuthenticator.java:545) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.auth.oidc.OidcAuthenticator.authenticate(OidcAuthenticator.java:323) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AuthenticationManager.doAuthenticate(AuthenticationManager.java:406) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AuthenticationManager.authenticateNonAnonymously(AuthenticationManager.java:356) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AuthenticationManager.authenticateFrontend(AuthenticationManager.java:221) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AuthenticationManager.authenticate(AuthenticationManager.java:205) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$AuthenticationFilter.attemptAuthentication(SecurityFilter.java:444) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$AuthenticationFilter.doFilter(SecurityFilter.java:241) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$InternalFilter.doFilter(SecurityFilter.java:978) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$InternalFilterChain.doFilter(SecurityFilter.java:1007) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$UserDataConstraintFilter.doFilter(SecurityFilter.java:852) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$InternalFilter.doFilter(SecurityFilter.java:978) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$InternalFilterChain.doFilter(SecurityFilter.java:1007) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$ConnectorFilter.doFilter(SecurityFilter.java:812) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$InternalFilter.doFilter(SecurityFilter.java:978) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter$InternalFilterChain.doFilter(SecurityFilter.java:1007) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.SecurityFilter.doFilter(SecurityFilter.java:159) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web.jar:5.1.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.21]
    at com.spotfire.server.security.CustomAuthFilterWrapper.doFilter(CustomAuthFilterWrapper.java:89) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web.jar:5.1.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.21]
    at com.spotfire.server.security.CsrfFilter.doFilter(CsrfFilter.java:74) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web.jar:5.1.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.21]
    at com.spotfire.server.security.HttpMethodsFilter.doFilter(HttpMethodsFilter.java:182) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web.jar:5.1.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.21]
    at com.spotfire.server.security.headers.HeadersFilter.doFilter(HeadersFilter.java:274) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web.jar:5.1.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.21]
    at com.spotfire.server.security.AccessLogFilter.doFilter(AccessLogFilter.java:73) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web.jar:5.1.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.21]
    at com.spotfire.server.security.RequestContextFilter$InnerFilter.doFilter(RequestContextFilter.java:179) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.RequestContextFilter.lambda$doFilter$2(RequestContextFilter.java:130) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.ClusteredSessionFilter.doFilter(ClusteredSessionFilter.java:79) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.RequestContextFilter.doFilter(RequestContextFilter.java:128) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.RequestContextFilter.doFilter(RequestContextFilter.java:98) ~[spotfire-server.jar:?]
    at com.spotfire.server.security.AbstractFilter.doFilter(AbstractFilter.java:124) ~[spotfire-server.jar:?]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web.jar:5.1.7.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web.jar:5.1.7.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[catalina.jar:9.0.21]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[catalina.jar:9.0.21]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[catalina.jar:9.0.21]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[catalina.jar:9.0.21]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[catalina.jar:9.0.21]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-coyote.jar:9.0.21]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-coyote.jar:9.0.21]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853) ~[tomcat-coyote.jar:9.0.21]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) ~[tomcat-coyote.jar:9.0.21]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-coyote.jar:9.0.21]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_212]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_212]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-util.jar:9.0.21]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_212]
Caused by: com.nimbusds.jose.proc.BadJOSEException: Signed JWT rejected: Another algorithm expected, or no matching key(s) found
    at com.nimbusds.jwt.proc.DefaultJWTProcessor.<clinit>(DefaultJWTProcessor.java:99) ~[nimbus-jose-jwt.jar:6.1]
    at com.spotfire.server.security.auth.oidc.TokenEndpointResponse.validateIdToken(TokenEndpointResponse.java:192) ~[spotfire-server.jar:?]
    ... 80 more


This seems like an Azure bug as they are expecting HS256 algorithm but it appears as if the discovery document hasn't listed it as supported (in the id_token_signing_alg_values_supported attribute). See below discovery document metadata for your reference:

{"token_endpoint":"https://login.microsoftonline.com/55e98fdf-9ac4-42f6-a35d-6bcb4d9b4bc7/oauth2/token","token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt","client_secret_basic"],"jwks_uri":"https://login.microsoftonline.com/common/discovery/keys","response_modes_supported":["query","fragment","form_post"],"subject_types_supported":["pairwise"],"id_token_signing_alg_values_supported":["RS256"],"response_types_supported":["code","id_token","code id_token","token id_token","token"],"scopes_supported":["openid"],"issuer":"https://sts.windows.net/55e98fdf-9ac4-42f6-a35d-6bcb4d9b4bc7/","microsoft_multi_refresh_token":true,"authorization_endpoint":"https://login.microsoftonline.com/55e98fdf-9ac4-42f6-a35d-6bcb4d9b4bc7/oauth2/authorize","http_logout_supported":true,"frontchannel_logout_supported":true,"end_session_endpoint":"https://login.microsoftonline.com/55e98fdf-9ac4-42f6-a35d-6bcb4d9b4bc7/oauth2/logout","claims_supported":["sub","iss","cloud_instance_name","cloud_instance_host_name","cloud_graph_host_name","msgraph_host","aud","exp","iat","auth_time","acr","amr","nonce","email","given_name","family_name","nickname"],"check_session_iframe":"https://login.microsoftonline.com/55e98fdf-9ac4-42f6-a35d-6bcb4d9b4bc7/oauth2/checksession","userinfo_endpoint":"https://login.microsoftonline.com/55e98fdf-9ac4-42f6-a35d-6bcb4d9b4bc7/openid/userinfo","tenant_region_scope":"NA","cloud_instance_name":"microsoftonline.com","cloud_graph_host_name":"graph.windows.net","msgraph_host":"graph.microsoft.com","rbac_url":"https://pas.windows.net"}
 

Issue/Introduction

This article describes why this "Signed JWT rejected: Another algorithm expected, or no matching key(s) found" error is returned and possible solutions.

Resolution

There are two possible workarounds we can use to resolve the issue:

Option 1. Disable id token signature validation by adding an id-token-signature-verification-disabledelement (with the value true) to the OpenID provider configuration. Below are the instructions:
  1. Export currently used configuration from the Spotfire database. 
  2. To export, either login to uiconfig.bat file (uiconfig.sh on Linux) which is located in the <Installation dir>\tomcat\spotfire-bin directory  OR  execute CLI command export-config  
  3. Open exported server configuration from given location in text or xml editor and search for <provider> tag.
  4. Add the line <id-token-signature-verification-disabled>true</id-token-signature-verification-disabled> to the <provider> tag as below:
    <provider>
              <name>GoogleTest</name>
              <enabled>true</enabled>
              <discovery-url>https://accounts.google.com/.well-known/openid configuration</discovery-url>
              <client-id>abcd</client-id>
              <client-secret>1234</client-secret>
              <id-token-signature-verification-disabled>true</id-token-signature-verification-disabled>
              <display-properties />
            </provider>
  5. Save the changes and import the configuration back to the database, either using uiconfig tool or use import-config command
  6. Restart the Spotfire server
  7. After successful server startup message in catalina logs, try opening the Spotfire server url in browser 


Option 2. Configure the provider to always expect HS256 as signing alg, regardless of what the discovery document URL says (but that may then break things if Microsoft changes the algorithm). If so, add an id-token-signing-alg element with that value under the provider element in the server configuration as below:
  1. Export currently used configuration from the Spotfire database. 
  2. To export, either login to uiconfig.bat file (uiconfig.sh on Linux) which is located in the <Installation dir>\tomcat\spotfire-bin directory  OR  execute CLI command export-config  
  3. Open exported server configuration from given location in text or xml editor and search for <provider> tag.
  4. Add the line <id-token-signing-alg>HS256</id-token-signing-alg> to the <provider> tag as below:
    <provider>
              <name>GoogleTest</name>
              <enabled>true</enabled>
              <discovery-url>https://accounts.google.com/.well-known/openid-configuration</discovery-url>
              <client-id>abcd</client-id>
              <client-secret>1234</client-secret>
              <id-token-signing-alg>HS256</id-token-signing-alg>
              <display-properties />
            </provider
  5. Save the changes and import the configuration back to the database, either using uiconfig tool or use import-config command
  6. Restart the Spotfire Server
  7. After successful server startup message in catalina logs, try opening the Spotfire Server url in browser 

Additional Information

Doc: config-oidc Doc: Manually editing the server configuration in an XML or text editor Doc: export-config Doc: import-config