Spring Security Spring授权服务器在身份验证后未重定向回前端应用程序(nextjs)

cbeh67ev  于 2023-10-20  发布在  Spring
关注(0)|答案(1)|浏览(126)

我有一个Java Spring后端API,Spring授权服务器运行在localhost:8080上,Nextjs前端运行在localhost:3000上。注册用户后,我正确地被重定向到授权服务器的登录页面。我输入正确的用户名和密码,并可以在Spring日志中看到用户已通过身份验证:
namePasswordAuthenticationToken,Credentials=[已验证],Authenticated=true,Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1,SessionId=4FEB7A8392B22372152176A6F947D0BA],Granted Authorities=[User]]
现在我想重定向到我的前端应用程序,在那里我已经设置了一个页面来接收来自响应的代码,并进行另一个调用来检索令牌。相反,我得到404(它说没有特定的/错误页面,但没有说错误是什么)。
下面是我的Spring授权配置:

@Bean
    public AuthenticationManager authenticationManager(
            CustomUserDetailsService userDetailsService,
            PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder);

        return new ProviderManager(authenticationProvider);
    }
 

    @Bean 
        public RegisteredClientRepository registeredClientRepository() {
            RegisteredClient linguaClient = RegisteredClient.withId("lingua-client.frontend")
                    .clientId("lingua-client")
                    .clientSecret("secret")
                    .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                    .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                    .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                    .redirectUri("http://localhost:3000/login/oauth2/code/lingua-client")
                    .postLogoutRedirectUri("http://localhost:3000")
                    .scope(OidcScopes.OPENID)
                    .scope("user.read")
                    .scope("user.write")
                    .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
                    .build();
    
            return new InMemoryRegisteredClientRepository(linguaClient);
        }

这就是我构建呼叫客户端的地方:

const clientId = process.env.CLIENT_ID;
    const redirectUri = encodeURIComponent('http://localhost:3000/login/oauth2/code/lingua-client');
    const response_type = 'code';
    const scope = encodeURIComponent('user.read user.write');
    const authServerUrl = process.env.AUTH_SERVER;

    const authUrl = `${authServerUrl}/authorize?response_type=${response_type}&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope};

我在http://localhost:3000/login/oauth2/code/lingua-client上有一个页面,它正在监听调用,但从未到达那里。
我尝试了不同的重定向网址,因为我不确定它是否需要遵循特定的格式。我也试过直接从浏览器访问网址,但仍然得到一个404。
更新:我可以通过添加以下安全链过滤器来重定向授权代码:

@Bean 
@Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
            throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
            .oidc(Customizer.withDefaults());   // Enable OpenID Connect 1.0
        http
            // Redirect to the login page when not authenticated from the
            // authorization endpoint
            .exceptionHandling((exceptions) -> exceptions
                .defaultAuthenticationEntryPointFor(
                    new LoginUrlAuthenticationEntryPoint("/login"),
                    new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
                )
            )
        return http.build();
    }

现在我得到了授权代码,但是在调用token端点之后,我得到了invalid_client。

yfwxisqw

yfwxisqw1#

我通过添加以下securityfilterchain解决了最初的问题,即无法使用授权代码重定向回我的redirectUri:

@Bean 
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
            throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
            .oidc(Customizer.withDefaults());   // Enable OpenID Connect 1.0
        http
            // Redirect to the login page when not authenticated from the
            // authorization endpoint
            .exceptionHandling((exceptions) -> exceptions
                .defaultAuthenticationEntryPointFor(
                    new LoginUrlAuthenticationEntryPoint("/login"),
                    new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
                )
            )
            // Accept access tokens for User Info and/or Client Registration
            .oauth2ResourceServer((resourceServer) -> resourceServer
                .jwt(Customizer.withDefaults()));

        return http.build();
    }

一旦我得到代码并使用它来调用令牌端点,我就得到了invalid_client错误。我通过在注册客户端中编码密码解决了这个问题:

@Bean 
    public RegisteredClientRepository registeredClientRepository() {
        RegisteredClient linguaClient = RegisteredClient.withId("lingua-client")
                .clientId("lingua-client")
                .clientSecret(encoder().encode("secret"))
         ...

相关问题