Spring boot 如何为Okta自动刷新承载令牌

Spring boot 如何为Okta自动刷新承载令牌,spring-boot,spring-security,spring-security-oauth2,okta,spring-autoconfiguration,Spring Boot,Spring Security,Spring Security Oauth2,Okta,Spring Autoconfiguration,我有一个带有AngularUI、Zuul和一些与Okta登录(OAuth)集成的服务的应用程序(不是被动的)。这可以正常工作,但在jwt令牌过期后会被卡住。有关工作流的一些详细信息 应用程序URL指向Zuul Zuul将请求重定向到Okta。用户登录 Okta发回一个承载令牌(也是一个刷新令牌) 此承载令牌被传递到UI并存储为cookie。对于每个请求,UI都会发送带有承载令牌的授权标头 这个过程可以正常工作,直到jwt令牌在一小时后过期,然后Zuul尝试将其重定向到默认登录页面,该页面在我们使

我有一个带有AngularUI、Zuul和一些与Okta登录(OAuth)集成的服务的应用程序(不是被动的)。这可以正常工作,但在jwt令牌过期后会被卡住。有关工作流的一些详细信息

  • 应用程序URL指向Zuul
  • Zuul将请求重定向到Okta。用户登录
  • Okta发回一个承载令牌(也是一个刷新令牌)
  • 此承载令牌被传递到UI并存储为cookie。对于每个请求,UI都会发送带有承载令牌的授权标头
  • 这个过程可以正常工作,直到jwt令牌在一小时后过期,然后Zuul尝试将其重定向到默认登录页面,该页面在我们使用okta登录时没有任何内容
  • 我的问题

  • 如果需要,登录页面可以重定向到哪里?
  • 如何基于刷新令牌获取新的承载令牌
  • 我可以根据刷新令牌自动获得Zuul中的新承载令牌吗?如果不可能,最好的方法是什么
  • 这是Zuul的application.yml文件

    spring:
      application:
        name: service-gateway
      cloud:
        loadbalancer:
          ribbon:
            enabled: false
    
    server:
      port: 8080
    
    okta:
      oauth2:
        issuer: https://dev1234.okta.com/oauth2/default
        client-id: <value>
        client-secret: <value>
    
        
    feign:
      hystrix:
        enabled: true
    hystrix:
      shareSecurityContext: true
    
    eureka:
      client:
        enabled: true
        fetch-registry: true
        
    zuul:
      routes:
        abc-service:
          path: /api/**
          strip-prefix: true
          service-id: ABC-SERVICE
    
        ui:
          path: /**
          url: http://localhost:4200
          
      host:
        connect-timeout-millis: 10000
        socket-timeout-millis: 20000
        
      sensitive-headers:
      - Cookie,Set-Cookie  
    
    Zulu Web安全配置适配器

    package abc
    @EnableDiscoveryClient
    @EnableZuulProxy
    @SpringBootApplication
    
    public class ServiceGateway {
    
        private static List<String> clients = Arrays.asList("okta");
        @Autowired
        private ClientRegistrationRepository clientRegistrationRepository;
    
        @Value("${okta.oauth2.client-id}")
        String clientId;
        @Value("${okta.oauth2.client-secret}")
        String clientSecret;
    
        public static void main(String[] args) {
            SpringApplication.run(ServiceGateway.class, args);
        }
    
        @Configuration
        static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                // @formatter:off
                http
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .oauth2Login()
                .and()
                .oauth2ResourceServer().jwt();
                // @formatter:on
            }
        }
    
        @Bean
        public FilterRegistrationBean<CorsFilter> simpleCorsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowCredentials(true);
            config.setAllowedOrigins(Collections.singletonList("*"));
            config.setAllowedMethods(Collections.singletonList("*"));
            config.setAllowedHeaders(Collections.singletonList("*"));
            source.registerCorsConfiguration("/**", config);
            FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
            bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
            return bean;
        }
    
        @Bean
        public OktaAuthenticationFilter oktaAuthFilter(OAuth2AuthorizedClientService clientService) {
            return new OktaAuthenticationFilter(clientService);
        }
    
    
    
    格雷德尔档案

    plugins {
        id 'org.springframework.boot' version '2.3.7.RELEASE'
        id 'io.spring.dependency-management' version '1.0.10.RELEASE'
        id 'java'
    }
    
    group = 'com.example'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '1.8'
    
    configurations {
        developmentOnly
        runtimeClasspath {
            extendsFrom developmentOnly
        }
    }
    
    repositories {
        mavenCentral()
    }
    
    ext {
        set('springCloudServicesVersion', "2.3.0.RELEASE")
        set('springCloudVersion', "Hoxton.SR9")
    }
    
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-actuator'
        implementation 'com.okta.spring:okta-spring-boot-starter:1.4.0'
        implementation 'io.pivotal.spring.cloud:spring-cloud-services-starter-service-registry'
        implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
        implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'
        implementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul'
        implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
        implementation 'io.pivotal.spring.cloud:spring-cloud-services-starter-config-client'
        implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure'
        developmentOnly 'org.springframework.boot:spring-boot-devtools'
        testImplementation('org.springframework.boot:spring-boot-starter-test') {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        }
    }
    
    dependencyManagement {
        imports {
            mavenBom "io.pivotal.spring.cloud:spring-cloud-services-dependencies:${springCloudServicesVersion}"
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        }
    }
    
    test {
        useJUnitPlatform()
    }
    
    buildscript {
        dependencies {
            classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0')
        }
    }
    
    plugins {
        id 'org.springframework.boot' version '2.3.7.RELEASE'
        id 'io.spring.dependency-management' version '1.0.10.RELEASE'
        id 'java'
    }
    
    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'com.palantir.docker'
    
    group = 'com.demo'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '1.8'
    
    configurations {
        developmentOnly
        runtimeClasspath {
            extendsFrom developmentOnly
        }
        compileOnly {
            extendsFrom annotationProcessor
        }
    }
    
    repositories {
        mavenCentral()
        maven { url 'https://repo.spring.io/milestone' }
    }
    
    ext {
        set('springCloudVersion', "Hoxton.SR9")
        set('springCloudServicesVersion', "2.3.0.RELEASE")
    }
    
    dependencies {
        implementation 'io.pivotal.spring.cloud:spring-cloud-services-starter-config-client'
        implementation 'io.pivotal.spring.cloud:spring-cloud-services-starter-service-registry'
        implementation 'org.springframework.boot:spring-boot-starter-actuator'
        implementation 'org.springframework.boot:spring-boot-starter-web'
        implementation 'org.springframework.boot:spring-boot-starter-security'
        implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
        implementation 'org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure'
        implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
        implementation 'com.okta.spring:okta-spring-boot-starter:1.4.0'
        compileOnly    'org.projectlombok:lombok'
        implementation    'com.googlecode.json-simple:json-simple:1.1.1'
        annotationProcessor 'org.projectlombok:lombok'
        developmentOnly 'org.springframework.boot:spring-boot-devtools'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
        testImplementation 'org.mockito:mockito-core:2.7.22'
    }
    
    dependencyManagement {
        imports {
            mavenBom "io.pivotal.spring.cloud:spring-cloud-services-dependencies:${springCloudServicesVersion}"
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        }
    }
    
    task unpack(type: Copy) {
        dependsOn bootJar
        from(zipTree(tasks.bootJar.outputs.files.singleFile))
        into("build/dependency")
    }
    docker {
        name "${project.group}/${bootJar.baseName}"
        copySpec.from(tasks.unpack.outputs).into("dependency")
        buildArgs(['DEPENDENCY': "dependency"])
    }
    
    task standardTests(type: Test) {
        useJUnitPlatform {
        }
    }  
    
    更新 看起来“脱机访问”的作用域确实有所不同。现在我得到一个CORS错误。过滤器就位后,我是否应该看不到这一点?这是因为存在授权标头吗? 此外,如果我手动刷新浏览器,将提供一个新令牌。那就没有CORS问题了

    zone.js:3243 POST http://localhost:8080/api/system/summary/salesHierarchy 401
    core.js:15724 ERROR 
    HttpErrorResponse {headers: HttpHeaders, status: 401, statusText: "OK", url: "http://localhost:8080/api/system/summary/salesHierarchy", ok: false, …}
    :8080/verification:1 Access to XMLHttpRequest at 'https://dev-770454.okta.com/oauth2/default/v1/authorize?response_type=code&…0/login/oauth2/code/okta&nonce=4aoYCPl3OKhsOTTpCUiqayYjQXdpZLuonn6_Q6193-o' (redirected from 'http://localhost:8080/verification') from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    zone.js:3243 GET https://dev-770454.okta.com/oauth2/default/v1/authorize?response_type=code&…0/login/oauth2/code/okta&nonce=4aoYCPl3OKhsOTTpCUiqayYjQXdpZLuonn6_Q6193-o net::ERR_FAILED
    core.js:15724 ERROR 
    HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "http://localhost:8080/verification", ok: false, …}
    
    更新1 当JWT令牌过期时,我看到下面的错误,这是预期的

    2021-01-31 10:38:53 [http-nio-8080-exec-9] DEBUG o.s.s.o.s.r.w.BearerTokenAuthenticationFilter - Authentication request for failed!
    org.springframework.security.oauth2.server.resource.InvalidBearerTokenException: An error occurred while attempting to decode the Jwt: Jwt expired at 2021-01-31T16:35:39Z
    
    401被发送到UI,UI捕获它并重定向到应用程序中的另一个url。这些是网关日志

    2021-01-31 10:38:53 [http-nio-8080-exec-10] DEBUG o.s.s.w.s.HttpSessionRequestCache - DefaultSavedRequest added to Session: DefaultSavedRequest[http://localhost:8080/verification]
    2021-01-31 10:38:53 [http-nio-8080-exec-10] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Calling Authentication entry point.
    org.springframework.security.web.authentication.WebAuthenticationDetails@2cd90: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: A55D113FD46A0031CA1FADD21C008382; Granted Authorities: ROLE_ANONYMOUS
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@4180b4a8, returned: -1
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /oauth2/authorization/okta at position 1 of 17 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /oauth2/authorization/okta at position 2 of 17 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@422bdd20. A new one will be created.
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /oauth2/authorization/okta at position 3 of 17 in additional filter chain; firing Filter: 'HeaderWriterFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /oauth2/authorization/okta at position 4 of 17 in additional filter chain; firing Filter: 'CorsFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
    org.springframework.security.access.AccessDeniedException: Access is denied
        at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
        at 
    ......
    
    o.s.s.w.a.ExceptionTranslationFilter - Calling Authentication entry point.
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using AndRequestMatcher [requestMatchers=[NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@6f86a06a, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]]
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using org.springframework.security.web.csrf.CsrfFilter$DefaultRequiresCsrfMatcher@3f60847a
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]]
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Did not match
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.NegatedRequestMatcher - matches = true
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /oauth2/authorization/okta at position 6 of 17 in additional filter chain; firing Filter: 'LogoutFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@6f86a06a, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /oauth2/authorization/okta' doesn't match 'POST /logout'
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.security.web.FilterChainProxy - /oauth2/authorization/okta at position 7 of 17 in additional filter chain; firing Filter: 'OAuth2AuthorizationRequestRedirectFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth2/authorization/okta'; against '/oauth2/authorization/{registrationId}'
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth2/authorization/okta'; against '/oauth2/authorization/{registrationId}'
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - httpRequestMediaTypes=[image/avif, image/webp, image/apng, image/svg+xml, image/*, */*;q=0.8]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - Processing image/avif
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - application/xhtml+xml .isCompatibleWith image/avif = false
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - image/* .isCompatibleWith image/avif = true
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - All requestMatchers returned true
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Match found! Executing org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint@1c10eb3a
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - Trying to match using AndRequestMatcher [requestMatchers=[NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], NegatedRequestMatcher [requestMatcher=AndRequestMatcher [requestMatchers=[OrRequestMatcher [requestMatchers=[Ant [pattern='/login'], Ant [pattern='/favicon.ico']]], AndRequestMatcher [requestMatchers=[NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@6f86a06a, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]]]]]]]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.NegatedRequestMatcher - matches = true
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using NegatedRequestMatcher [requestMatcher=AndRequestMatcher [requestMatchers=[OrRequestMatcher [requestMatchers=[Ant [pattern='/login'], Ant [pattern='/favicon.ico']]], AndRequestMatcher [requestMatchers=[NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@6f86a06a, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]]]]]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using OrRequestMatcher [requestMatchers=[Ant [pattern='/login'], Ant [pattern='/favicon.ico']]]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/login']
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/favicon.ico'; against '/login'
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/favicon.ico']
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/favicon.ico'; against '/favicon.ico'
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.OrRequestMatcher - matched
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using AndRequestMatcher [requestMatchers=[NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@6f86a06a, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.NegatedRequestMatcher - matches = true
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@6f86a06a, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - httpRequestMediaTypes=[image/avif, image/webp, image/apng, image/svg+xml, image/*, */*;q=0.8]
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to 'https://dev-770454.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=0oa2amci5xaQcrWbF357&scope=openid%20profile%20email%20address%20phone%20offline_access&state=yXMfdZoYPFl3yoISRnJLftlFnXmf3AnBgnUdGk0MBAc%3D&redirect_uri=http://localhost:8080/login/oauth2/code/okta&nonce=sKf92sk_wHRT6Zq1XwEw-NdYwik-CRMgXLZa_3jfKpA'
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - Processing image/avif
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - application/xhtml+xml .isCompatibleWith image/avif = false
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@61505c39
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.MediaTypeRequestMatcher - image/* .isCompatibleWith image/avif = true
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - All requestMatchers returned true
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - All requestMatchers returned true
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.m.NegatedRequestMatcher - matches = false
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Did not match
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.a.DelegatingAuthenticationEntryPoint - No match found. Using default entry point org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@693f1240
    2021-01-31 10:38:53 [http-nio-8080-exec-1] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.web.DefaultRedirectStrategy - Redirecting to 'http://localhost:8080/login'
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@61505c39
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
    2021-01-31 10:38:53 [http-nio-8080-exec-8] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 1 of 17 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 2 of 17 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@422bdd20. A new one will be created.
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 3 of 17 in additional filter chain; firing Filter: 'HeaderWriterFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 4 of 17 in additional filter chain; firing Filter: 'CorsFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] TRACE o.s.c.n.zuul.web.ZuulHandlerMapping - Mapped to HandlerExecutionChain with [org.springframework.cloud.netflix.zuul.web.ZuulController@3ce8f88f] and 1 interceptors
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 5 of 17 in additional filter chain; firing Filter: 'CsrfFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Trying to match using org.springframework.security.web.csrf.CsrfFilter$DefaultRequiresCsrfMatcher@3f60847a
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.u.matcher.AndRequestMatcher - Did not match
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 6 of 17 in additional filter chain; firing Filter: 'LogoutFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /login' doesn't match 'POST /logout'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 7 of 17 in additional filter chain; firing Filter: 'OAuth2AuthorizationRequestRedirectFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login'; against '/oauth2/authorization/{registrationId}'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 8 of 17 in additional filter chain; firing Filter: 'OAuth2LoginAuthenticationFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/login'; against '/login/oauth2/code/*'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.security.web.FilterChainProxy - /login at position 9 of 17 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
    2021-01-31 10:38:53 [http-nio-8080-exec-6] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@61505c39
    
    在浏览器控制台上,我看到了错误

    Access to XMLHttpRequest at 'https://dev-770454.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=0oa2amci5xaQcrWbF357&scope=openid%20profile%20email%20address%20phone%20offline_access&state=yXMfdZoYPFl3yoISRnJLftlFnXmf3AnBgnUdGk0MBAc%3D&redirect_uri=http://localhost:8080/login/oauth2/code/okta&nonce=sKf92sk_wHRT6Zq1XwEw-NdYwik-CRMgXLZa_3jfKpA' (redirected from 'http://localhost:8080/verification') from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    

    此CORS错误是否应由网关上定义的筛选器处理,或者CORS筛选器是否未应用?让我困惑的是,如果我进入浏览器并单击刷新按钮,它工作正常。

    如果您有刷新令牌,您可以。您只需要决定是先获取新令牌(基于其到期时间)还是重新获取(如果现有令牌停止工作,则请求新的访问令牌)。

    来自:

    OAuth2RefreshToken可以选择性地在授权代码和密码授予类型的访问令牌响应中返回。如果
    OAuth2AuthorizedClient.getRefreshToken()
    可用,并且
    OAuth2AuthorizedClient.getAccessToken()
    过期,它将由
    RefreshTokenOAuth2AuthorizedClient提供程序自动刷新

    检查Okta应用程序中的刷新令牌框不足以获取刷新令牌。您还需要传入
    脱机访问
    范围,否则将不会返回

    我建议您升级到Okta Spring Boot starter 2.0.0并使用以下scopes属性:

    okta.oauth2.scopes=openid, email, profile, offline_access
    

    我在OAuth2AuthorizedClient的令牌中有这两个。脱机访问的范围是缺少的。让我试试。现在我有一个CORS问题,CORS过滤器不应该处理它吗?Okta或API有CORS错误?您可以添加错误/更新原始问题吗?CORS错误似乎来自网关。我在Okta中没有看到错误日志。在update1中更新日志如果CORS错误来自Okta,则需要添加
    http://localhost:8080
    在API>Trusted Origins的Okta开发者仪表板中。如果它来自您的网关,您需要为Spring Security配置CORS。我确实写了一个zuul过滤器来实现这一点,并且能够获得新的令牌。将令牌发送到UI并将其存储在cookie中之后。当使用新令牌发出新请求时,会显示错误。2021-01-28 11:45:43[http-nio-8080-exec-1]调试o.s.s.w.a.ExceptionTranslationFilter-访问被拒绝(用户是匿名的);重定向到身份验证入口点org.springframework.security.access.AccessDeniedException:访问被拒绝
    Access to XMLHttpRequest at 'https://dev-770454.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=0oa2amci5xaQcrWbF357&scope=openid%20profile%20email%20address%20phone%20offline_access&state=yXMfdZoYPFl3yoISRnJLftlFnXmf3AnBgnUdGk0MBAc%3D&redirect_uri=http://localhost:8080/login/oauth2/code/okta&nonce=sKf92sk_wHRT6Zq1XwEw-NdYwik-CRMgXLZa_3jfKpA' (redirected from 'http://localhost:8080/verification') from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    
    okta.oauth2.scopes=openid, email, profile, offline_access