You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud API Gateway集成Okta登录提示Invalid Credentials问题排查

问题:Okta登录提示"Invalid Credentials"无法解决

访问http://localhost:9090/authenticate/login时,Okta登录页面显示**"Invalid Credentials"**(截图:Okta登录错误截图),多次重新创建Okta应用后问题仍存在。


提供的配置与代码

API Gateway的application.yml配置

server:
  port: 9090


spring:
  application:
    name: API-GATEWAY
  config:
    import: configserver:http://localhost:9296
  cloud:
    gateway:
      routes:
        - id: ORDER-SERVICE
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/order/**
          filters:
            - name: CircuitBreaker
              args:
                name: ORDER-SERVICE
                fallbackuri: forward:/orderServiceFallBack
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1 # 每秒允许的请求数(无丢弃)
                redis-rate-limiter.burstCapacity: 1 # 每秒允许的最大请求数
        - id: PAYMENT-SERVICE
          uri: lb://PAYMENT-SERVICE
          predicates:
            - Path=/payment/**
          filters:
            - name: CircuitBreaker
              args:
                name: PAYMENT-SERVICE
                fallbackuri: forward:/paymentServiceFallBack
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 1
        - id: PRODUCT-SERVICE
          uri: lb://PRODUCT-SERVICE
          predicates:
            - Path=/product/**
          filters:
            - name: CircuitBreaker
              args:
                name: PRODUCT-SERVICE
                fallbackuri: forward:/productServiceFallBack
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 1


okta:
  oauth2:
    issuer: https://dev-54315943.okta.com/oauth2/default
    audience: api://default
    client-id: 0oa6s2k5zyiKYoGwL5d7 // my client id
    client-secret: AqGnodb6VrX-eRiHnnZEE-HTZGUt383CVwLI344t // my client secret
    scopes: openid, email, profile, offline_access

安全配置代码

@Configuration
@EnableWebFluxSecurity
public class OktaOAuth2WebSecurity {

    @Bean
    public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
        http
                .authorizeExchange()
                .anyExchange().authenticated()
                .and()
                .oauth2Login()
                .and()
                .oauth2ResourceServer()
                .jwt();
        return http.build();
    }
}

控制器代码

@RestController
@RequestMapping("/authenticate")
@Slf4j
public class AuthController {

    @GetMapping("/login")
    public ResponseEntity<AuthenticationResponse> login(
            @AuthenticationPrincipal OidcUser oidcUser,
            Model model,
            @RegisteredOAuth2AuthorizedClient("okta")
            OAuth2AuthorizedClient client
    ) {

        log.info("AuthController | login is called");
        log.info("AuthController | login | client : " + client.toString());

        AuthenticationResponse authenticationResponse = null;
        try{
            authenticationResponse
                    = AuthenticationResponse.builder()
                    .userId(oidcUser.getEmail())
                    .accessToken(client.getAccessToken().getTokenValue())
                    .refreshToken(client.getRefreshToken().getTokenValue())
                    .expiresAt(client.getAccessToken().getExpiresAt().getEpochSecond())
                    .authorityList(oidcUser.getAuthorities()
                            .stream()
                            .map(GrantedAuthority::getAuthority)
                            .collect(Collectors.toList()))
                    .build();
        }catch (Exception e){
            log.info("AuthController | login | error : " + e.getMessage());
        }


        return new ResponseEntity<>(authenticationResponse, HttpStatus.OK);
    }
}

修复步骤

1. 修正Okta应用核心配置

  • 确认应用类型:必须创建Web应用(而非Native/SPA类型),Spring Cloud Gateway属于后端服务,仅Web应用支持授权码流程。
  • 配置正确的重定向URI:在Okta应用的「General」设置中,添加http://localhost:9090/login/oauth2/code/okta作为重定向URI——这是Spring OAuth2默认的回调路径,你写的/authenticate/login是登录后的结果处理接口,不是Okta的回调地址。
  • 分配用户权限:在Okta应用的「Assignments」标签中,确保用于登录的用户已被分配到该应用,未分配的用户会直接提示凭证无效。

2. 修复Spring配置错误

  • 移除YAML中的非法注释:YAML不支持//注释,会导致客户端密钥解析错误,修改Okta配置段:
    okta:
      oauth2:
        issuer: https://dev-54315943.okta.com/oauth2/default
        audience: api://default
        client-id: 0oa6s2k5zyiKYoGwL5d7
        client-secret: AqGnodb6VrX-eRiHnnZEE-HTZGUt383CVwLI344t
        scopes: openid, email, profile, offline_access
    
  • 验证Issuer可用性:访问https://dev-54315943.okta.com/oauth2/default/.well-known/openid-configuration,确认返回标准的OpenID配置,排除地址拼写错误。

3. 调整安全配置逻辑

  • 显式注册Okta客户端:添加以下Bean到安全配置类,避免Spring自动配置异常:
    @Bean
    public ReactiveClientRegistrationRepository clientRegistrationRepository() {
        ClientRegistration okta = ClientRegistration.withRegistrationId("okta")
                .clientId("0oa6s2k5zyiKYoGwL5d7")
                .clientSecret("AqGnodb6VrX-eRiHnnZEE-HTZGUt383CVwLI344t")
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
                .scope("openid", "email", "profile", "offline_access")
                .authorizationUri("https://dev-54315943.okta.com/oauth2/default/v1/authorize")
                .tokenUri("https://dev-54315943.okta.com/oauth2/default/v1/token")
                .userInfoUri("https://dev-54315943.okta.com/oauth2/default/v1/userinfo")
                .userNameAttributeName(IdTokenClaimNames.SUB)
                .jwkSetUri("https://dev-54315943.okta.com/oauth2/default/v1/keys")
                .clientName("Okta")
                .build();
        return new InMemoryReactiveClientRegistrationRepository(okta);
    }
    
  • 排除回调路径的网关拦截:在Spring Cloud Gateway路由规则中,添加排除规则,避免/login/oauth2/code/okta被转发到业务服务:
    spring:
      cloud:
        gateway:
          routes:
            # ... 原有路由 ...
          default-filters:
            - RewritePath=/login/oauth2/code/okta, /login/oauth2/code/okta
          predicates:
            - Path=!/login/oauth2/code/**
    

4. 调试日志排查细节

  • 开启Spring Security调试日志,定位具体错误:
    logging:
      level:
        org.springframework.security: DEBUG
        org.springframework.web: DEBUG
    
    查看日志中OAuth2流程的请求、响应细节,比如是否成功获取授权码、令牌请求是否返回错误等。

内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 16:45:43