Giter Site home page Giter Site logo

okta-jwt-verifier-java's Introduction

Maven Central License Support Build Status

Okta JWT Verifier for Java

As a result of a successful authentication by obtaining an authorization grant from a user or using the Okta API, you will be provided with a signed JWT (id_token and/or access_token). A common use case for these access tokens is to use it inside of the Bearer authentication header to let your application know who the user is that is making the request. In order for you to know this use is valid, you will need to know how to validate the token against Okta. This guide gives you an example of how to do this using Okta's JWT Validation library for Java.

If you are validating access tokens from a Spring application take a look at the Okta Spring Boot Starter.

Things you will need

To validate a JWT, you will need a few different items:

  1. Your issuer URL
  2. The JWT string you want to verify
  3. The Okta JWT Verifier for Java library, for example in your Apache Maven pom.xml:
  <dependency>
    <groupId>com.okta.jwt</groupId>
    <artifactId>okta-jwt-verifier</artifactId>
    <version>${okta-jwt.version}</version>
  </dependency>
  
  <dependency>
    <groupId>com.okta.jwt</groupId>
    <artifactId>okta-jwt-verifier-impl</artifactId>
    <version>${okta-jwt.version}</version>
    <scope>runtime</scope>
  </dependency>

Setting up the Library

The Okta JWT Verifier can created via the fluent JwtVerifiers class:

AccessTokenVerifier jwtVerifier = JwtVerifiers.accessTokenVerifierBuilder()
    .setIssuer("https://{yourOktaDomain}/oauth2/default")
    .setAudience("api://default")                   // defaults to 'api://default'
    .setConnectionTimeout(Duration.ofSeconds(1))    // defaults to 1s
    .setRetryMaxAttempts(2)                     // defaults to 2
    .setRetryMaxElapsed(Duration.ofSeconds(10)) // defaults to 10s
    .setPreloadSigningKeys(true)                // defaults to false
    .build();

This helper class configures a JWT parser with the details found through the OpenID Connect discovery endpoint. The public keys (JWKS) used to validate the JWTs will also be retrieved and cached automatically via blocking calls at startup and whenever the keys are rotated.

Validating a JWT

After you have a JwtVerifier from the above section and an access_token from a successful sign in, or from a Bearer token in the authorization header, you will need to make sure that it is still valid. All you need to do is call the decode method (where jwtString is your access token in string format).

Jwt jwt = jwtVerifier.decode(jwtString);

This will validate your JWT for the following:

  • token expiration time
  • the time it was issue at
  • that the token issuer matches the expected value passed into the above helper
  • that the token audience matches the expected value passed into the above helper

The result from the decode method is a Jwt object which you can introspect additional claims by calling:

jwt.getClaims().get("aClaimKey");

Conclusion

The above are the basic steps for verifying an access token locally. The steps are not tied directly to a framework so you could plug in the okta-jwt-verifier into the framework of your choice (Dropwizard, Guice, Servlet API, or JAX-RS).

For more information on this project take a look at the following resources:

Android

Okta JWT Verifier works with Android API 21+.

Java 8 library desugaring may be required as Okta JWT Verifier makes use of java 8 features. See the link, or the example below on how to configure it.

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled true
  }

  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
    // Sets Java compatibility to Java 8
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  // For Kotlin projects
  kotlinOptions {
    jvmTarget = "1.8"
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
}

okta-jwt-verifier-java's People

Contributors

arvindkrishnakumar-okta avatar bdemers avatar bjr-okta avatar dependabot[bot] avatar er1c avatar flicken avatar jaynewstrom avatar nishant-mehta avatar oktauploader-okta avatar zaza avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

okta-jwt-verifier-java's Issues

Async API

I'm submitting a

  • bug report
  • feature request

Background info

It's not directly obvious how to configure the http client requests to an issuer URL using a Future other than wrapping them in my own task runner.

Expected behavior

I would like:

  • Future<Jwt> jwtFuture = jwtVerifier.asyncDecode(jwtString);
  • setExecutor(Executor executor) in AccessTokenVerifier.Builder

Add support for OSGI

I am trying to use this maven artifact in an OSGI environment (Adobe Experience Manager), but it seems to be a non-OSGI jar, and when I deployed my application code, it says "com.okta.jwt -- Cannot be resolved".

It'll be good if you add support for OSGI.

Timeouts in example in README.md is incorrect

The setConnectionTimeout(1000) and setReadTimeout(1000) in the example in README.md take a Duration instead of an integer. The example should be re-written as follows (assuming the right imports are done elsewhere)

Duration timeout = Duration.of(1, ChronoUnit.SECONDS)

and change the methods in the builder to

setConnectionTimeout(timeout)
setReadTimeout(timeout)

Improved javadoc

The javadoc leave a lot to be desired. What methods Block? What is a JoseException?

com.okta.jwt.JwtVerificationException: Failed to parse token

ℹ️ If you have a question, please post it on the Okta Developer Forum instead. Issues in this repository are reserved for bug reports and feature requests only.

I'm submitting a

  • bug report

Background info

Describe your issue or request here (if necessary).

we are using OKTA verifier for OKTA token offline validation. Sometime we got the exceptions message while parsing the token. It is inconsistency

    <dependency>
		<groupId>com.okta.jwt</groupId>
		<artifactId>okta-jwt-verifier</artifactId>
		<version>${okta-jwt.version}</version>
	</dependency>
	<dependency>
		<groupId>com.okta.jwt</groupId>
		<artifactId>okta-jwt-verifier-impl</artifactId>
		<version>${okta-jwt.version}</version>
		<scope>runtime</scope>
	</dependency>

Version details: 0.4.1

StackTrace details :

com.okta.jwt.JwtVerificationException: Failed to parse token
at com.okta.jwt.impl.jjwt.TokenVerifierSupport.decode(TokenVerifierSupport.java:67)
at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifier.decode(JjwtAccessTokenVerifier.java:45)
at com.pgs.subsurface.util.JwtTokenProvider.resolveTokenDetails(JwtTokenProvider.java:40)
at com.pgs.subsurface.util.CommonFunctionUtil.fetchJWTClaimValues(CommonFunctionUtil.java:17)
at com.pgs.subsurface.service.HelperService.extractedLogCheck(HelperService.java:237)
at com.pgs.subsurface.controller.ReferenceController.getProductCatagory(ReferenceController.java:63)
at jdk.internal.reflect.GeneratedMethodAccessor112.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1707)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: io.jsonwebtoken.JwtException: Failed to fetch keys from URL: https://XXXXXXXXXXXXX/oauth2/default/v1/keys
at com.okta.jwt.impl.jjwt.RemoteJwkSigningKeyResolver.updateKeys(RemoteJwkSigningKeyResolver.java:95)
at com.okta.jwt.impl.jjwt.RemoteJwkSigningKeyResolver.getKey(RemoteJwkSigningKeyResolver.java:69)
at com.okta.jwt.impl.jjwt.RemoteJwkSigningKeyResolver.resolveSigningKey(RemoteJwkSigningKeyResolver.java:54)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:376)
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:550)
at com.okta.jwt.impl.jjwt.TokenVerifierSupport.decode(TokenVerifierSupport.java:61)
... 58 more
Caused by: java.net.SocketTimeoutException: connect timed out

Version upgraded form 0.4.1 to 0.5.6:
Exception details: Unable to execute HTTP request - retryable exception: timeout

Configuration Value:
Connection timedout - 1 seconds
retryAttempt: 2
retryMaxElapsed: 10

Could you please help on this.

Confusion about purpose of this library

I was hoping this library would be usable as a general purpose JWT verifier, but it seems to only work with okta. Is that the intention? If so than please clarify this. If not then I have a few bugs that are blockers for me.

Validating native app's access token throws exception

Hi ,

We have a mobile app that authenticates using oidc lib from okta and passes the access token to our resource service part of it’s request call (POST, GET, etc). We have setup an authorization server in our dashboard with default settings and using /oauth2/default endpoint with default audience “api://default”. With this setup, we are using okta’s okta-jwt-verifier-java lib to verify the access token. The problem is we always get java.lang.IllegalArgumentException: A signing key must be specified if the specified JWT is digitally signed. When we try to verify the access token. Not sure we made anything wrong here. Is this a bug?

[Update 1] I tried with nodejs resource api from the sample too i got below error when i tried to verify JWT from the app Error while resolving signing key for kid "cgtXxWFpMZm3g62lMjRpnwiF2dY4r3mqsBRh2HB9NyM"

So native app signing the jwt but the okta-jwt-verifier unable to resolve the signature? Am I missing something here? Either this should be a config issue which I missed or there is a bug in the verifier.

[Update 2] I tried to verify a JWT generated by another application which is a java web app. Here I am successfully able to verify the JWT using above node and java services but I am unable to verify the JWT generated only by the android app.

Security vulnerability with required library, njwt

We are using the below version of the library.

"@okta/jwt-verifier": {
"version": "0.0.14",
"resolved": "https://registry.npmjs.org/@okta/jwt-verifier/-/jwt-verifier-0.0.14.tgz",
"integrity": "sha512-O+CzOeMy6aUi0PtqmoZLmKjE1xpUF9nUMlZ3hYlz4fUpb3zKUUESohq/iSuBijw2dB0Lru6Tsi7OWJXFJT1vew==",
"requires": {
"@okta/configuration-validation": "^0.1.1",
"jwks-rsa": "^1.2.0",
"njwt": "^0.4.0"
}
}

The version of njwt used has been flagged with a Uninitialized Buffer Allocation Vulnerability.
https://www.sourceclear.com/vulnerability-database/security/sca/vulnerability/sid-6814/summary

Please can you review and use a new version of the library or use a different one so that the issue is resolved?

Gradle shadowJar throws No `interface com.okta.jwt.AccessTokenVerifier$Builder` implementation found on the classpath.

I'm submitting a

  • bug report
  • feature request

Background info

Do you have any gradle examples?

I try to use this in my gradle project:

plugins {
    id 'java'
    id 'com.github.johnrengelman.shadow' version '6.1.0'
}

repositories {
    mavenCentral()
}

dependencies {
// ...
    implementation('com.okta.jwt:okta-jwt-verifier:0.5.1') {
        exclude group: 'org.slf4j'
    }
    runtimeOnly('com.okta.jwt:okta-jwt-verifier-impl:0.5.1') {
        exclude group: 'org.slf4j'
    }
}

shadowJar {
    archiveClassifier.set('')
    mergeServiceFiles()
}

But when I run my shadow jar will throws:

Caused by: java.lang.IllegalStateException: No `interface com.okta.jwt.AccessTokenVerifier$Builder` implementation found on the classpath. Have you remembered to include the okta-jwt-verifier-impl.jar in your runtime classpath?
        at com.okta.jwt.JwtVerifiers.lambda$loadService$1(JwtVerifiers.java:60)
        at <unknown class>.get(Unknown Source)
        at java.base/java.util.Optional.orElseThrow(Optional.java:408)
        at com.okta.jwt.JwtVerifiers.loadService(JwtVerifiers.java:60)
        at com.okta.jwt.JwtVerifiers.accessTokenVerifierBuilder(JwtVerifiers.java:51)
        at id.attestation.plugins.auth.FacebookAuthService.<init>(FacebookAuthService.java:22)
        at java.base/java.lang.J9VMInternals.newInstanceImpl(Native Method)
        at java.base/java.lang.Class.newInstance(Class.java:2288)
        at org.pf4j.DefaultExtensionFactory.create(DefaultExtensionFactory.java:38)
        ... 30 common frames omitted

In fact okta-jwt-verifier-impl and services files already contains in shadow jar file:

META-INF/
META-INF/MANIFEST.MF
...
META-INF/okta/
META-INF/okta/version.properties
com/
com/okta/
com/okta/jwt/
com/okta/jwt/impl/
com/okta/jwt/impl/jjwt/
com/okta/jwt/impl/jjwt/BaseVerifierBuilderSupport.class
com/okta/jwt/impl/jjwt/TokenVerifierSupport.class
com/okta/jwt/impl/jjwt/TokenVerifierSupport$OktaJwtHandler.class
com/okta/jwt/impl/jjwt/ClaimsValidator$CompositeClaimsValidator.class
com/okta/jwt/impl/jjwt/ClaimsValidator.class
com/okta/jwt/impl/jjwt/ClaimsValidator$ContainsAudienceClaimsValidator.class
com/okta/jwt/impl/jjwt/IssuerMatchingSigningKeyResolver.class
com/okta/jwt/impl/jjwt/models/
com/okta/jwt/impl/jjwt/models/JwkKeys.class
com/okta/jwt/impl/jjwt/models/JwkKey.class
com/okta/jwt/impl/jjwt/JjwtAccessTokenVerifierBuilder.class
com/okta/jwt/impl/jjwt/RemoteJwkSigningKeyResolver.class
com/okta/jwt/impl/jjwt/JjwtIdTokenVerifier.class
com/okta/jwt/impl/jjwt/JjwtAccessTokenVerifier.class
com/okta/jwt/impl/jjwt/JjwtIdTokenVerifierBuilder.class
com/okta/jwt/impl/http/
com/okta/jwt/impl/http/HttpClient.class
com/okta/jwt/impl/http/OktaCommonsHttpClient.class
com/okta/jwt/impl/DefaultJwt.class
...
META-INF/services/com.okta.jwt.AccessTokenVerifier$Builder
META-INF/services/com.okta.jwt.IdTokenVerifier$Builder
META-INF/services/com.okta.commons.http.RequestExecutorFactory
META-INF/services/io.jsonwebtoken.CompressionCodec
META-INF/services/io.jsonwebtoken.io.Serializer
META-INF/services/io.jsonwebtoken.io.Deserializer
META-INF/services/com.fasterxml.jackson.core.JsonFactory
META-INF/services/com.fasterxml.jackson.core.ObjectCodec
...

Steps to reproduce

If the current behavior is a bug, please provide the steps to reproduce and a minimal demo if possible.

Library Version

0.5.1

token invalid on back-end after successful login on front-end SPA

Hi,
I've been following the quick start guide https://developer.okta.com/quickstart/#/angular/java/spring but keep getting an invalid token exception from spring.
I'v double checked that all parameters are as described in the guide, angular widget is working properly and getting an access token but when this access token is being sent to the back-end as a "Authorization: 'Bearer ' + token" header, spring is throwing an invalid token exception after trying to restore it from some internal storage.

I'm attaching below the spring log & stack trace, lmk if any other info is required.
Spring security chain log:

o.s.security.web.FilterChainProxy        : /admin/get-list at position 1 of 16 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
o.s.security.web.FilterChainProxy        : /admin/get-list at position 2 of 16 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
o.s.security.web.FilterChainProxy        : /admin/get-list at position 3 of 16 in additional filter chain; firing Filter: 'HeaderWriterFilter'
o.s.security.web.FilterChainProxy        : /admin/get-list at position 4 of 16 in additional filter chain; firing Filter: 'LogoutFilter'
o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', GET]
o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/admin/get-list'; against '/logout'
o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', POST]
o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /admin/get-list' doesn't match 'POST /logout'
o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', PUT]
o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /admin/get-list' doesn't match 'PUT /logout'
o.s.s.web.util.matcher.OrRequestMatcher  : Trying to match using Ant [pattern='/logout', DELETE]
o.s.s.w.u.matcher.AntPathRequestMatcher  : Request 'GET /admin/get-list' doesn't match 'DELETE /logout'
o.s.s.web.util.matcher.OrRequestMatcher  : No matches found
o.s.security.web.FilterChainProxy        : /admin/get-list at position 5 of 16 in additional filter chain; firing Filter: 'OAuth2AuthorizationRequestRedirectFilter'
o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/admin/get-list'; against '/oauth2/authorization/{registrationId}'
o.s.security.web.FilterChainProxy        : /admin/get-list at position 6 of 16 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'
p.a.OAuth2AuthenticationProcessingFilter : Authentication request failed: error="invalid_token", error_description="Invalid access token: undefined"
o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@3b99c2b1
s.s.o.p.e.DefaultOAuth2ExceptionRenderer : Written [error="invalid_token", error_description="Invalid access token: undefined"] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@498e5da7]
s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

Stack trace:

Daemon Thread [http-nio-9999-exec-5] (Suspended)	
	owns: NioEndpoint$NioSocketWrapper  (id=466)	
	DefaultTokenServices.loadAuthentication(String) line: 231	
	OAuth2AuthenticationManager.authenticate(Authentication) line: 83	
	OAuth2AuthenticationProcessingFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 150	
	FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 334	
	OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 160	
	OAuth2AuthorizationRequestRedirectFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 334	
	LogoutFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 116	
	FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 334	
	HeaderWriterFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 66	
	HeaderWriterFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 334	
	SecurityContextPersistenceFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 105	
	FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 334	
	WebAsyncManagerIntegrationFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 56	
	WebAsyncManagerIntegrationFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 334	
	FilterChainProxy.doFilterInternal(ServletRequest, ServletResponse, FilterChain) line: 215	
	FilterChainProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 178	
	DelegatingFilterProxyRegistrationBean$1(DelegatingFilterProxy).invokeDelegate(Filter, ServletRequest, ServletResponse, FilterChain) line: 357	
	DelegatingFilterProxyRegistrationBean$1(DelegatingFilterProxy).doFilter(ServletRequest, ServletResponse, FilterChain) line: 270	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
	OrderedRequestContextFilter(RequestContextFilter).doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 99	
	OrderedRequestContextFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
	OrderedFormContentFilter(FormContentFilter).doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 92	
	OrderedFormContentFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
	OrderedHiddenHttpMethodFilter(HiddenHttpMethodFilter).doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 93	
	OrderedHiddenHttpMethodFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
	WebMvcMetricsFilter.filterAndRecordMetrics(HttpServletRequest, HttpServletResponse, FilterChain, Object) line: 154	
	WebMvcMetricsFilter.filterAndRecordMetrics(HttpServletRequest, HttpServletResponse, FilterChain) line: 122	
	WebMvcMetricsFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 107	
	WebMvcMetricsFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
	OrderedCharacterEncodingFilter(CharacterEncodingFilter).doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 200	
	OrderedCharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
	CorsFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 96	
	CorsFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107	
	ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 193	
	ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 166	
	StandardWrapperValve.invoke(Request, Response) line: 199	
	StandardContextValve.invoke(Request, Response) line: 96	
	NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 490	
	StandardHostValve.invoke(Request, Response) line: 139	
	ErrorReportValve.invoke(Request, Response) line: 92	
	StandardEngineValve.invoke(Request, Response) line: 74	
	CoyoteAdapter.service(Request, Response) line: 343	
	Http11Processor.service(SocketWrapperBase<?>) line: 408	
	Http11Processor(AbstractProcessorLight).process(SocketWrapperBase<?>, SocketEvent) line: 66	
	AbstractProtocol$ConnectionHandler<S>.process(SocketWrapperBase<S>, SocketEvent) line: 770	
	NioEndpoint$SocketProcessor.doRun() line: 1415	
	NioEndpoint$SocketProcessor(SocketProcessorBase<S>).run() line: 49	
	ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1142	
	ThreadPoolExecutor$Worker.run() line: 617	
	TaskThread$WrappingRunnable.run() line: 61	
	TaskThread(Thread).run() line: 745	

PKCE flow and ID token nonce value?

Hi there!

I'm interested in your recommendations about the best way to fetch the OIDC profile data for an authenticated user. My use case is as follows:

  • PKCE flow from my React app, using @okta/okta-react
  • Verify JWTs in my Scala backend app using this library (okta/okta-jwt-verifier-java)

What I'd like to do is accomplish the following:

  • User logs in to my frontend application using the PKCE flow
  • Frontend app attaches the identity token JWT to subsequent API requests as an Authorization: Bearer header
  • Backend rehydrates basic user profile information statelessly by extracting user profile claims information from the ID token itself

However, in order to verify the JWT using okta/okta-jwt-verifier-java, I need to be able to supply a nonce value to compare the expected nonce value I submitted while requesting an access token with the actual claim on the ID JWT.

Does this imply that I should not be passing around the ID token if I'm using the PKCE flow initiated by my frontend application, and should instead only be sending an access token JWT to my backend for verification?

Access Token Verifier Builder fails to initialize

ℹ️ If you have a question, please post it on the Okta Developer Forum instead. Issues in this repository are reserved for bug reports and feature requests only.

I'm submitting a

  • [x ] bug report
  • feature request

Background info

jwtVerifier = JwtVerifiers.accessTokenVerifierBuilder()
.setIssuer(oauthURL+"/oauth2/default")
.setAudience("api://default")
.setConnectionTimeout(Duration.ofSeconds(5)) // defaults to 1s
//.setReadTimeout(Duration.ofSeconds(5)) // defaults to 1s
.setRetryMaxAttempts(5)
.setRetryMaxElapsed(Duration.ofSeconds(5))
.build();

generates the following error when executed:

java.util.ServiceConfigurationError: com.okta.jwt.AccessTokenVerifier$Builder: Provider com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifierBuilder not a subtype

Expected behavior

JwtVerifiers.accessTokenVerifierBuilder should have initialized

What went wrong?

Initializing the builder caused and Error to be thrown:
java.util.ServiceConfigurationError: com.okta.jwt.AccessTokenVerifier$Builder: Provider com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifierBuilder not a subtype

Steps to reproduce

Execut the code above

Library Version

pom.xml says version is 25

Feature Request: Stronger typing in Jwt Claims

https://github.com/okta/okta-jwt-verifier-java/blob/master/api/src/main/java/com/okta/jwt/Jwt.java#L48

This would be better to have a concrete class, rather than a Map.

I'd prefer not to have to cast / pattern match / infer types when interacting with this API.

Reference for the upstream library is: https://github.com/jwtk/jjwt/blob/master/api/src/main/java/io/jsonwebtoken/Claims.java

First class support for scp is also desireable.

(e.g. create a Claims that extends that interface, and adds the scp)

Best Regards,

Eric

No Support for Java 7

Hi Team,

I'm not able use the jar in my project which is in jdk 1.7. please suggest.

Thanks.

NoClassDefFoundError after upgrade

ℹ️ If you have a question, please post it on the Okta Developer Forum instead. Issues in this repository are reserved for bug reports and feature requests only.

I'm submitting a

  • bug report
  • feature request

Background info

Upgrading from 0.5.4 -> 0.5.5 results in a NoClassDefFoundError

Expected behavior

Behavior remains unchanged.

What went wrong?

The following stacktrace illustrates the issue, related to exclusion of the kotlin stdlib in #130

java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
 at okhttp3.ConnectionPool.<init>(ConnectionPool.kt)
 at okhttp3.ConnectionPool.<init>(ConnectionPool.kt:47)
 at okhttp3.OkHttpClient$Builder.<init>(OkHttpClient.kt:471)
 at com.okta.commons.http.okhttp.OkHttpRequestExecutor.createOkHttpClient([OkHttpRequestExecutor.java:73]
 at com.okta.commons.http.okhttp.OkHttpRequestExecutor.([OkHttpRequestExecutor.java:62]
 at com.okta.commons.http.okhttp.OkHttpRequestExecutorFactory.create([OkHttpRequestExecutorFactory.java:58]
 at com.okta.jwt.impl.http.OktaCommonsHttpClient.createRequestExecutor([OktaCommonsHttpClient.java:67]
 at com.okta.jwt.impl.http.OktaCommonsHttpClient.([OktaCommonsHttpClient.java:47]
 at com.okta.jwt.impl.jjwt.BaseVerifierBuilderSupport.httpClient([BaseVerifierBuilderSupport.java:182]
 at com.okta.jwt.impl.jjwt.BaseVerifierBuilderSupport.signingKeyResolver([BaseVerifierBuilderSupport.java:166]
 at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifierBuilder.build([JjwtAccessTokenVerifierBuilder.java:58]
 at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifierBuilder.build([JjwtAccessTokenVerifierBuilder.java:27]

Steps to reproduce

Upgrade to 0.5.5 and create an AccessTokenVerifier something like:

final String issuer = "https://my-oauth-domain/oauth2/default";
final AccessTokenVerifier.Builder builder = JwtVerifiers.accessTokenVerifierBuilder().setIssuer(issuer);
this.verifier = builder.build();

Explicitly re-adding the kotlin stdlib as a direct dependency in the project restores the original behavior, e.g.

<dependency>
  <groupId>org.jetbrains.kotlin</groupId>
  <artifactId>kotlin-stdlib</artifactId>
  <version>1.7.20</version>
</dependency>

Library Version

0.5.5

Allow specifying a java.time.Clock to better write unit tests.

I have a mockito webservice and unit tests with a fixed java.time.Clock, when I try to decode the bearer token, I get an exception on the expired state of the token from the okta library sigh. I'd like to have an optional java.time.Clock argument in AccessTokenVerifier for the: Jwt decode(String accessToken) throws JwtVerificationException

image

Issuer URL cannot be set to other than URI

When you are using Google+ API for sign in using Oauth2 it can return both an URI or a string, in the OktaJWTClaimsVerifier it would be an improvement to check if the issuer is either URI or URI-link substring https://, or is there another workaround for this?

https://accounts.google.com this is required for the JWTHelper to be an URI
accounts.google.com what google actually can return as well

AccessTokenVerifier.decode while ignoring 'audience' field

Hi there,

We have a use case where we would like to decode a JWT token while ignoring the aud field.

Is it a valid use case? can it somehow be achieved with the latest version?

in case it's not possible - as a 2nd best, I found functionality in the nodeJs library that we can use:
https://github.com/okta/okta-oidc-js/tree/master/packages/jwt-verifier#how-to-use
where we can pass the audience dynamically to the decode call (rather then to the builder) - is that likely to be part of the Java lib anytime soon?

Thanks

Use without querying /default/v1/keys ?

Hey there,
I was integrating this lib into one of my apps and noticed that this makes use of the RemoteJwkSigningKeyResolver which makes an HTTP request to jwkUri everytime getKey() is called (via updateKeys()).

Is it possible for me to use the library without making any HTTP requests? It adds a lot of latency to my token verification process.

Does the JSON returned by https://dev-******.okta.com/oauth2/default/v1/keys change or can I save it locally and use that instead of querying the HTTP endpoint?

I know Okta recommends dynamically querying the endpoint, but trying to see if there is a faster way to achieve this.

Thanks for the lib! 😄

Using beginner example: "Caused by: com.nimbusds.jose.proc.BadJOSEException: Signed JWT rejected: Another algorithm expected, or no matching key(s) found"

I was originally using my own implementation of a JWT verifier based on nimbus' jwt jose library, but kept getting "com.nimbusds.jwt.SignedJWT@4dc6c945 : Signed JWT rejected: Another algorithm expected, or no matching key(s) found"

So I found this library, and followed the example on the first page https://github.com/okta/okta-jwt-verifier-java

I get the same exception. code is currently:

    JwtVerifier jwtVerifier = new JwtHelper()
        .setIssuerUrl("https://dev-******.oktapreview.com/oauth2/default")
        .setAudience("api://default")  // defaults to 'api://default'
        .setConnectionTimeout(1000)    // defaults to 1000ms
        .setReadTimeout(1000)          // defaults to 1000ms
        .setClientId("******") // optional
        .build();

    String accessToken = "eyJ******";
    Jwt jwt = jwtVerifier.decodeAccessToken(accessToken);

And fails on "build". I've masked my okta domain and client id and accessToken. I don't see how I can make this simpler than this. Maybe my Okta config is wrong?

Exception is:
Exception in thread "main" com.okta.jwt.JoseException: Failed to validate JWT string
at com.okta.jwt.impl.NimbusJwtVerifier.decode(NimbusJwtVerifier.java:82)
at com.okta.jwt.impl.NimbusJwtVerifier.decodeAccessToken(NimbusJwtVerifier.java:68)
at veeva.vdm.auth.core.Sandbox.main(Sandbox.java:31)
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.(DefaultJWTProcessor.java:100)
at com.okta.jwt.JwtHelper.build(JwtHelper.java:92)
at veeva.vdm.auth.core.Sandbox.main(Sandbox.java:23)

Additional note: I am using the following tool to get the accessToken to test with: https://oidcdebugger.com/

RemoteJwkSigningKeyResolver updateKeys() returns null map despite key being retrieved

This specific method returns null map which was resulting in following exception: java.lang.IllegalArgumentException: A signing key must be specified if the specified JWT is digitally signed. I could see in debug mode that the key is retrieved and should pass both filters (sig - public key use, RSA - key type) and go into .map/.collect. This wasn't happening. I copied the code into my own java class, was trying to work out whenever i had a free moment and the problem lies with collection to map. it just cannot see the key and value of AbstractMap this way. I got it working in my local code but obviously this needs to be fixed on library level. This is my fixed code:

Map<String, Key> newKeys = (Map) keys.stream()
    .filter(jwkKey -> "sig".equals(jwkKey.getPublicKeyUse()) && 
        "RSA".equals(jwkKey.getKeyType()))
    .collect(Collectors.toMap(key -> key.getKeyId(), key -> {
        BigInteger modulus = base64ToBigInteger(key.getPublicKeyModulus());
        BigInteger exponent = base64ToBigInteger(key.getPublicKeyExponent());
        RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, exponent);
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
            return publicKey;
        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
            throw new IllegalStateException("Failed to parse public key");
        }}));

Much appreciated,
Ania Richardson

Verification issue - Signed JWT rejected: Another algorithm expected, or no matching key(s) found

Hi,

I am trying to verify an freshly generated access_token using your library and I am encoutering this issue :
com.okta.jwt.JoseException: Failed to validate JWT string at com.okta.jwt.impl.NimbusJwtVerifier.decode(NimbusJwtVerifier.java:82) at com.okta.jwt.impl.NimbusJwtVerifier.decodeAccessToken(NimbusJwtVerifier.java:68) at com.xxx.poc.oauth2.api.endpoints.AuthenticationEndpoint.post(AuthenticationEndpoint.java:71) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205) at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288) at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:852) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:219) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.Server.handle(Server.java:530) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626) at java.lang.Thread.run(Thread.java:748) 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:100) at com.okta.jwt.JwtHelper.build(JwtHelper.java:79) at com.xxx.poc.oauth2.api.endpoints.AuthenticationEndpoint.post(AuthenticationEndpoint.java:69) ... 50 more

This seems to be the root cause :
Signed JWT rejected: Another algorithm expected, or no matching key(s) found

Do you have any idea ?

this is not working with reactive webflux restapi

I tried to use this dependancy in spring webflux library but i am getting error. Please help me is there any way to do custom validation for signature and scopes using oauth2 okta in spring webflux reactive APIs.

Support for org authorization servers

I'm submitting a

  • bug report
  • feature request

Background info

I am working on OpenID Connect implementation for the Okta Integration Network. The documentation says:

To support the potentially large numbers of Okta orgs accessing it through the OIN, an OIDC integration can't use a custom authorization server, including the default server. You can only use the Org Authorization Server (opens new window).

I assume that means the baseUrl should not include default or an authorizationServerId. However, in JjwtAccessTokenVerifierBuilder.java there is validation:

if (!getIssuer().matches(".*/oauth2/.*")) {
    log.warn("Decoding access tokens from this issuer '{}' may not be possible. Your issuer URL should be in the format of 'https://{yourOktaDomain}/oauth2/qualifier'", getIssuer());
}

Is there a reason why the qualifier is necessary? Am I missing something about how this should work with a Org Authorization Server?

Everything works if I use the default authorization server in my dev environment, but I'm worried that will not work for the Okta Integration Network based on the documentation above.

Expected behavior

I thought it would validate the token.

What went wrong?

Decoding access tokens from this issuer 'https://dev-55695188.okta.com/oauth2' may not be possible. Your issuer URL should be in the format of 'https://{yourOktaDomain}/oauth2/qualifier'
Failed to parse token

Steps to reproduce

Submit a url like https://xxx.com/oauth2 as the issuer

Library Version

  "com.okta.jwt" % "okta-jwt-verifier" % "0.5.1",
  "com.okta.jwt" % "okta-jwt-verifier-impl" % "0.5.1",

Issuer verification failed (Okta + Ktor + SwaggerUI)

Hello,

currently I have an issue with my api authentication.

Setup:
I'm building a basic Ktor API and provided an Authentication feature to validate Okta accessTokens.

Via a swagger UI I login at okta and retrieve my accessToken, which contains an issuer:
"iss": "https://dev-ylqkdtaqkg6cqazy.eu.auth0.com/"

When I am using the accessTokenVerifier to validate and verify the incoming accessToken using the following builder

JwtVerifiers.accessTokenVerifierBuilder()
    .setIssuer("https://dev-ylqkdtaqkg6cqazy.eu.auth0.com/")
    .setAudience("api://default")
    .build()

I get an exception that issuer claim does not match
Caused by: io.jsonwebtoken.IncorrectClaimException: Expected iss claim to be: https://dev-ylqkdtaqkg6cqazy.eu.auth0.com, but was: https://dev-ylqkdtaqkg6cqazy.eu.auth0.com/.

Checking the BaseVerifierBuilderSupport it seams like the trailing slash was removed, when setIssuer() is called

What can I do, as the issuer in the accessToken comes from auth0 as well. See my openid-configuration
https://dev-ylqkdtaqkg6cqazy.eu.auth0.com/.well-known/openid-configuration

Regards

Provide better exception when issuer doesn't match (common issue when switching between issuers or Okta Authorization Servers)

Here the exception stacktrace:

com.okta.jwt.JoseException: Failed to validate JWT string
	at com.okta.jwt.impl.NimbusJwtVerifier.decode(NimbusJwtVerifier.java:82)
	at com.okta.jwt.impl.NimbusJwtVerifier.decodeAccessToken(NimbusJwtVerifier.java:68)
	at com.cuebiq.apigateway.handler.OktaAuthHandler.handle(OktaAuthHandler.kt:23)
	at com.cuebiq.apigateway.handler.OktaAuthHandler.handle(OktaAuthHandler.kt:11)
	at io.vertx.reactivex.ext.web.Route$1.handle(Route.java:155)
	at io.vertx.reactivex.ext.web.Route$1.handle(Route.java:153)
	at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:219)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:120)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:133)
	at io.vertx.ext.web.impl.RouterImpl.accept(RouterImpl.java:79)
	at io.vertx.reactivex.ext.web.Router.accept(Router.java:94)
	at com.cuebiq.apigateway.verticle.ApiGatewayVerticle$startHttpServer$1.invoke(ApiGatewayVerticle.kt:75)
	at com.cuebiq.apigateway.verticle.ApiGatewayVerticle$startHttpServer$1.invoke(ApiGatewayVerticle.kt:20)
	at com.cuebiq.apigateway.verticle.ApiGatewayVerticleKt$sam$Handler$4b7b53e4.handle(ApiGatewayVerticle.kt)
	at io.vertx.reactivex.core.http.HttpServer$1.handle(HttpServer.java:111)
	at io.vertx.reactivex.core.http.HttpServer$1.handle(HttpServer.java:109)
	at io.vertx.core.http.impl.Http1xServerConnection.processMessage(Http1xServerConnection.java:454)
	at io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:144)
	at io.vertx.core.http.impl.HttpServerImpl$ServerHandlerWithWebSockets.handleMessage(HttpServerImpl.java:669)
	at io.vertx.core.http.impl.HttpServerImpl$ServerHandlerWithWebSockets.handleMessage(HttpServerImpl.java:622)
	at io.vertx.core.net.impl.VertxHandler.lambda$channelRead$1(VertxHandler.java:146)
	at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:337)
	at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:195)
	at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:144)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.vertx.core.http.impl.HttpServerImpl$Http2UpgradeHandler.channelRead(HttpServerImpl.java:970)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:141)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)
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:100)
	at com.okta.jwt.JwtHelper.build(JwtHelper.java:92)
	at com.cuebiq.apigateway.handler.OktaAuthHandler.handle(OktaAuthHandler.kt:19)
	... 45 more

Root cause seems to be: Signed JWT rejected: Another algorithm expected, or no matching key(s)

Here my configuration of JWTVerifier:
val jwtVerifier = JwtHelper()
.setIssuerUrl("https://dev-826799.oktapreview.com/oauth2/default")
.setAudience("api://default") // defaults to 'api://default'
.setConnectionTimeout(1000) // defaults to 1000ms
.setReadTimeout(1000) // defaults to 1000ms
.setClientId("0oafjb9h4f3lcTja20h7") // optional
.build()

what's happening?

Feature Request : Method for introspect token.

I'm submitting a

  • feature request

Background info

Submitting a feature request for token introspection method so that a separate code for API call will not have to be developed.

Expected behavior

Token Introspection with Okta Introspect API

support for HS512

Is there anyway we can add support for HS512 ? Looking at the code you only support SignatureAlgorithm.RS256 at the moment. If so, how do you handle PR? and releases. I can definitely help out if needed

java.lang.NoSuchMethodError: 'io.jsonwebtoken.JwtParserBuilder io.jsonwebtoken.Jwts.parserBuilder()'

On scala:

libraryDependencies ++= Seq(
  "com.okta.jwt" % "okta-jwt-verifier" % "0.5.1",
  "com.okta.jwt" % "okta-jwt-verifier-impl" % "0.5.1"// % "runtime,test",
)
[info] com.evenfinancial.auth.oidc.OidcConfigurationSpec *** ABORTED ***
[info]   java.lang.NoSuchMethodError: 'io.jsonwebtoken.JwtParserBuilder io.jsonwebtoken.Jwts.parserBuilder()'
[info]   at com.okta.jwt.impl.jjwt.TokenVerifierSupport.buildJwtParser(TokenVerifierSupport.java:50)
[info]   at com.okta.jwt.impl.jjwt.TokenVerifierSupport.<init>(TokenVerifierSupport.java:46)
[info]   at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifier.<init>(JjwtAccessTokenVerifier.java:39)
[info]   at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifierBuilder.build(JjwtAccessTokenVerifierBuilder.java:58)
[info]   at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifierBuilder.build(JjwtAccessTokenVerifierBuilder.java:27)
[info]   at com.evenfinancial.auth.oidc.OidcConfiguration$.accessTokenVerifier(OidcConfiguration.scala:37)
[info]   at com.evenfinancial.auth.oidc.OidcConfiguration$.accessTokenVerifier(OidcConfiguration.scala:29)
[info]   at com.evenfinancial.auth.oidc.OidcConfiguration$.parseToken(OidcConfiguration.scala:19)
[info]   at com.evenfinancial.auth.oidc.OidcConfigurationSpec.$anonfun$new$2(OidcConfigurationSpec.scala:11)

Is there a dependency missing in the pom?

No `interface com.okta.jwt.AccessTokenVerifier$Builder` implementation found on the classpath. Have you remembered to include the okta-jwt-verifier-impl.jar in your runtime classpath

I'm submitting a

  • [ X] bug report

Background info

I am writing an authorizer that will verify a given access token using the readme file in this repository. However, I keep getting the below error whenever the code tries to create AccessTokenVerifier class.

Expected behavior

An instance of the implementation of AccessTokenVerifier must be returned instead.

Steps to reproduce

Here is my pom.xml file's dependencies section and the dependency tree.

<dependencies>
        <!-- AWS -->
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-events</artifactId>
            <version>3.10.0</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-log4j2</artifactId>
            <version>1.2.0</version>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
        <!-- Testing -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>4.0.0</version>
            <scope>test</scope>
        </dependency>
        <!-- Okta verifier -->
        <dependency>
            <groupId>com.okta.jwt</groupId>
            <artifactId>okta-jwt-verifier</artifactId>
            <version>0.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.okta.jwt</groupId>
            <artifactId>okta-jwt-verifier-impl</artifactId>
            <version>0.5.1</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ api ---
[INFO] com.doosan.sa:api:jar:1.0-SNAPSHOT
[INFO] +- com.amazonaws:aws-lambda-java-core:jar:1.2.1:compile
[INFO] +- com.amazonaws:aws-lambda-java-events:jar:3.10.0:compile
[INFO] |  \- joda-time:joda-time:jar:2.6:compile
[INFO] +- com.amazonaws:aws-lambda-java-log4j2:jar:1.2.0:compile
[INFO] |  +- (com.amazonaws:aws-lambda-java-core:jar:1.2.1:compile - omitted for duplicate)
[INFO] |  +- org.apache.logging.log4j:log4j-core:jar:2.13.2:compile
[INFO] |  |  \- (org.apache.logging.log4j:log4j-api:jar:2.13.2:compile - omitted for duplicate)
[INFO] |  \- org.apache.logging.log4j:log4j-api:jar:2.13.2:compile
[INFO] +- org.projectlombok:lombok:jar:1.18.22:compile
[INFO] +- junit:junit:jar:4.13.2:test
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.mockito:mockito-core:jar:4.0.0:test
[INFO] |  +- net.bytebuddy:byte-buddy:jar:1.11.19:test
[INFO] |  +- net.bytebuddy:byte-buddy-agent:jar:1.11.19:test
[INFO] |  \- org.objenesis:objenesis:jar:3.2:test
[INFO] +- com.okta.jwt:okta-jwt-verifier:jar:0.5.1:compile
[INFO] \- com.okta.jwt:okta-jwt-verifier-impl:jar:0.5.1:runtime
[INFO]    +- (com.okta.jwt:okta-jwt-verifier:jar:0.5.1:runtime - omitted for duplicate)
[INFO]    +- com.okta.commons:okta-config-check:jar:1.2.5:runtime
[INFO]    |  \- (org.slf4j:slf4j-api:jar:1.7.29:runtime - omitted for duplicate)
[INFO]    +- com.okta.commons:okta-commons-lang:jar:1.2.5:runtime
[INFO]    |  \- (org.slf4j:slf4j-api:jar:1.7.29:runtime - omitted for duplicate)
[INFO]    +- com.okta.commons:okta-http-api:jar:1.2.5:runtime
[INFO]    |  +- (com.okta.commons:okta-commons-lang:jar:1.2.5:runtime - omitted for duplicate)
[INFO]    |  \- (org.slf4j:slf4j-api:jar:1.7.29:runtime - omitted for duplicate)
[INFO]    +- com.okta.commons:okta-http-okhttp:jar:1.2.5:runtime
[INFO]    |  +- (com.okta.commons:okta-http-api:jar:1.2.5:runtime - omitted for duplicate)
[INFO]    |  +- (com.squareup.okhttp3:okhttp:jar:3.14.4:runtime - omitted for conflict with 4.9.1)
[INFO]    |  \- org.slf4j:jcl-over-slf4j:jar:1.7.29:runtime
[INFO]    |     \- (org.slf4j:slf4j-api:jar:1.7.29:runtime - omitted for duplicate)
[INFO]    +- org.slf4j:slf4j-api:jar:1.7.29:runtime
[INFO]    +- io.jsonwebtoken:jjwt-api:jar:0.11.2:runtime
[INFO]    +- io.jsonwebtoken:jjwt-impl:jar:0.11.2:runtime
[INFO]    |  \- (io.jsonwebtoken:jjwt-api:jar:0.11.2:runtime - omitted for duplicate)
[INFO]    +- io.jsonwebtoken:jjwt-jackson:jar:0.11.2:runtime
[INFO]    |  +- (io.jsonwebtoken:jjwt-api:jar:0.11.2:runtime - omitted for duplicate)
[INFO]    |  \- (com.fasterxml.jackson.core:jackson-databind:jar:2.9.10.4:runtime - omitted for conflict with 2.12.1)
[INFO]    +- com.fasterxml.jackson.core:jackson-annotations:jar:2.12.1:runtime
[INFO]    +- com.fasterxml.jackson.core:jackson-databind:jar:2.12.1:runtime
[INFO]    |  +- (com.fasterxml.jackson.core:jackson-annotations:jar:2.12.1:runtime - omitted for duplicate)
[INFO]    |  \- com.fasterxml.jackson.core:jackson-core:jar:2.12.1:runtime
[INFO]    \- com.squareup.okhttp3:okhttp:jar:4.9.1:runtime
[INFO]       +- com.squareup.okio:okio:jar:2.8.0:runtime
[INFO]       |  +- (org.jetbrains.kotlin:kotlin-stdlib:jar:1.4.0:runtime - omitted for conflict with 1.4.10)
[INFO]       |  \- org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.4.0:runtime
[INFO]       \- org.jetbrains.kotlin:kotlin-stdlib:jar:1.4.10:runtime
[INFO]          +- (org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.4.10:runtime - omitted for conflict with 1.4.0)
[INFO]          \- org.jetbrains:annotations:jar:13.0:runtime
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

I see here com.okta.jwt:okta-jwt-verifier:jar:0.5.1:runtime - omitted for duplicate and I suppose that may be the cause. But I tried many ways to resolve it but nothing worked.

What am I missing?

Library Version

0.5.1

AccessTokenVerifier can throw undocumented exceptions

ℹ️ If you have a question, please post it on the Okta Developer Forum instead. Issues in this repository are reserved for bug reports and feature requests only.

I'm submitting a

  • bug report
  • feature request

Background info

In some rare cases I am seeing an IllegalArgumentException being thrown from the AccessTokenVerifier#decode. According to the documentation it should throw a JwtVerificationException when parsing or validation errors occur.

It appears that the try/catch around the code that parses the JWT does not adequately handle all of the exceptions advertised by the JWT parser: https://github.com/okta/okta-jwt-verifier-java/blob/master/impl/src/main/java/com/okta/jwt/impl/jjwt/TokenVerifierSupport.java#L63-L71

Expected behavior

A JwtVerificationException should be thrown.

What went wrong?

java.lang.IllegalArgumentException: A signing key must be specified if the specified JWT is digitally signed.
	at io.jsonwebtoken.lang.Assert.notNull(Assert.java:82)
	at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:357)
	at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:513)
	at com.okta.jwt.impl.jjwt.TokenVerifierSupport.decode(TokenVerifierSupport.java:61)
	at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifier.decode(JjwtAccessTokenVerifier.java:45)
... 

Steps to reproduce

I'm not sure what the content of the JWT is unfortunately but this happens very rarely.

Library Version

  // okta
  implementation 'com.okta.jwt:okta-jwt-verifier:0.4.0'
  implementation 'com.okta.jwt:okta-jwt-verifier-impl:0.4.0'

Throwing NoSuchMethodError with okta-sdk-java >=3.0.2

I'm submitting a

  • bug report

Background info

When installed with okta-sdk-java >= 3.0.2, the id token verifier throws a NoSuchMethodError.

I believe this is probably because the okta.commons.version is different between the two libraries (1.2.4 vs 1.2.5). The method HttpClientConfiguration.getRequestExecutorParams is called but does not exist and so throws a NoSuchMethodError. Potentially related: okta/okta-commons-java#42

Expected behavior

When creating an id token verifier using the builder, an id token verifier is returned

What went wrong?

An exception is thrown:

NoSuchMethodError: 'Map HttpClientConfiguration.getRequestExecutorParams()'

Steps to reproduce

JwtVerifiers.idTokenVerifierBuilder()
          .setClientId("my_client_id")
          .setIssuer("baseurl.okta.com")
          .build();

Library Version

okta-jwt-verifier: 0.5.0
okta-sdk-api: >= 3.0.2

Proposed solution

Release a new version of okta-jwt-verifier-java.

okta.commons.version = 1.2.5 is already set in the pom, the library just hasn't been released since 16th Sep 2020.

Add support for configurable retry

The next version of this library will use OkHttp which already handles retry, but configuring this behavior is currently NOT exposed to the developer.

Multiple Issuer validation support

ℹ️ If you have a question, please post it on the Okta Developer Forum instead. Issues in this repository are reserved for bug reports and feature requests only.

I'm submitting a feature request

Background info

currently one issuer validation is supported but would be great to have list of issuer provided as we have custom authorization server and multiple authorization servers are being used for authentication

Expected behavior

What should have happened?

What went wrong?

Please provide log or error messages if applicable.

Steps to reproduce

If the current behavior is a bug, please provide the steps to reproduce and a minimal demo if possible.

Library Version

JUnit with Wiremock - Issuer HTTPS issue

I'm submitting a

  • bug report

Background info

JjwtAccessTokenVerifierBuilder's build method checks if the issuer in the token is a valid issuer in BaseVerifierBuilderSupport.validate() which calls okta-config-checks JAR's ConfigurationValidator.assertIssuer(). However, when runing the code through a testing scenario, this implementation needs to allow a non HTTPS url as well.
In my case, I'm referring to https://developer.okta.com/blog/2018/05/02/testing-spring-boot-angular-components#mock-oktas-api-with-wiremock and using Wiremock to mock the HTTP calls, for which I've to send issuer such as "http://localhost:51592/oauth/issuer".

I've earlier also used okta.testing.disableHttpsCheck property which is accepted by Okta Java API SDK and works fine. May be we could use the same property here as well?

Expected behavior

"okta.testing.disableHttpsCheck" flag should be read and issuer HTTPs check should be disabled if the flag is true.

What went wrong?

Error thrown: Your Okta Issuer URL must start with https. Current value: http://localhost:64301/oauth/issuer. You can copy your domain from the Okta Developer Console. Follow these instructions to find it: https://bit.ly/finding-okta-domain

Steps to reproduce

Pass a JWT token with localhost issuer.

Library Version

0.5.0

A signing key must be specified if the specified JWT is digitally signed ?

@bdemers
I am following the example to build an AccessTokenVerifier.
Here is my code:

AccessTokenVerifier jwtVerifier = JwtVerifiers.accessTokenVerifierBuilder()
.setIssuer("https://dev-******.okta.com/oauth2/default")
.setAudience("api://default")
.setConnectionTimeout(Duration.ofSeconds(1))
.setReadTimeout(Duration.ofSeconds(1))
.build();

Jwt jwt = jwtVerifier.decode(accessToken);

However, when calling jwtVerifier decode here throws exception below:

java.lang.IllegalArgumentException: A signing key must be specified if the specified JWT is digitally signed.
	at io.jsonwebtoken.lang.Assert.notNull(Assert.java:82) ~[auth-1.0-SNAPSHOT.jar:na]
	at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:357) ~[auth-1.0-SNAPSHOT.jar:na]
	at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:513) ~[auth-1.0-SNAPSHOT.jar:na]
	at com.okta.jwt.impl.jjwt.TokenVerifierSupport.decode(TokenVerifierSupport.java:61) ~[auth-1.0-SNAPSHOT.jar:na]
	at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifier.decode(JjwtAccessTokenVerifier.java:45) ~[auth-1.0-SNAPSHOT.jar:na]

#13 and checking the okta configuration in console don't help.

By digging a bit, when code is executing to line 334 - 357 in DefaultJwtParser.java, we already decoded the whole accessToken, payload and claims contains everything same as a network introspect response.

However, in the RemoteJwkSigningKeyResolver.java, i don't think the jwsHeader(contains two keys kid and alg) has a correct match with any keys in keyMap.

Any places I can attach the Public Key when building the verifier and my jwkUri is https://dev-******.okta.com/oauth2/default/v1/keys.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.