Spring授权服务器在请求令牌时重定向到登录页面。

huangapple go评论52阅读模式
英文:

Spring authorization server redirect to login page when token is requested

问题

以下是你要翻译的内容:

We currently have 2 web applications that authenticate against a CAS. The communication between them is done via Basic Auth.

For security reasons we want to switch to OAuth2 to get rid of the Basic Auth. At the same time we want to get rid of the CAS because it does not meet our requirements.

So the goal is something along those lines:

I am at the point that I can log in to the user management and manipulate data. The 2nd application also correctly redirects me to the 1st application to authenticate me. Authentication also works. And the 1st application responds correctly to the 2nd application. The 2nd application then executes the expected POST to the url "oauth2/token". But the 1st application replies with a 302 to "/login" instead of a token.

Which point am I missing or do I still have to configure?

I have orientated myself on the following documentation:

My AuthorizationServerConfig looks like this:

And the Configuration from App 2 looks like this:

application.properties from App2 is:

The request from App2 to App 1 that causes the redirect is:

POST [URL]

Body:
[Body Content]

Header:
[Header Content]

英文:

We currently have 2 web applications that authenticate against a CAS. The communication between them is done via Basic Auth.

Spring授权服务器在请求令牌时重定向到登录页面。

For security reasons we want to switch to OAuth2 to get rid of the Basic Auth. At the same time we want to get rid of the CAS because it does not meet our requirements.

So the goal is something along those lines:

Spring授权服务器在请求令牌时重定向到登录页面。

I am at the point that I can log in to the user management and manipulate data. The 2nd application also correctly redirects me to the 1st application to authenticate me. Authentication also works. And the 1st application responds correctly to the 2nd application. The 2nd application then executes the expected POST to the url "oauth2/token". But the 1st application replies with a 302 to "/login" instead of a token.

Which point am I missing or do I still have to configure?

I have orientated myself on the following documentation:
https://docs.spring.io/spring-authorization-server/docs/current/reference/html/getting-started.html

My AuthorizationServerConfig looks like this:

@Configuration
public class AuthorizationServerConfig {

  private final SecurityApp app;

  public AuthorizationServerConfig(SecurityApp app) {
    this.app = app;
  }

  @Bean
  @Order(1)
  public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
      throws Exception {

    OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
        new OAuth2AuthorizationServerConfigurer();
    authorizationServerConfigurer
        .authorizationEndpoint(authorizationEndpoint ->
            authorizationEndpoint.consentPage("/oauth2/authorize"))
        .oidc(Customizer.withDefaults());	// Enable OpenID Connect 1.0

    RequestMatcher endpointsMatcher = authorizationServerConfigurer
        .getEndpointsMatcher();

    http
        .securityMatcher(endpointsMatcher)
        .authorizeHttpRequests(authorize ->
            authorize.anyRequest().authenticated()
        )
        .csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
        .exceptionHandling(exceptions ->
            exceptions.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
        )
        .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
        .apply(authorizationServerConfigurer);
    return http.build();
  }

  @Bean
  @Order(2)
  public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
      throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().authenticated()
        )
        // Form login handles the redirect to the login page from the
        // authorization server filter chain
        .formLogin(Customizer.withDefaults());

    return http.build();
  }

  @Bean
  UserDetailsService users() {
    return app::findUserByLogin;
  }

  // OVERWATCH

  @Bean
  public RegisteredClientRepository registeredClientRepository() {

    return new RegisteredClientRepository() {
      @Override
      public void save(RegisteredClient registeredClient) {
        throw new NotImplementedException();
      }

      @Override
      public RegisteredClient findById(String id) {
        return app.findByClientId(id);
      }

      @Override
      public RegisteredClient findByClientId(String clientId) {
        return app.findByClientId(clientId);
      }
    };
  }

  @Bean
  public JWKSource<SecurityContext> jwkSource() {
    RSAPublicKey publicKey = app.getPublicKey();
    RSAPrivateKey privateKey = (RSAPrivateKey) app.getPrivateKey();
    RSAKey rsaKey = new RSAKey.Builder(publicKey)
        .privateKey(privateKey)
        .keyID(UUID.randomUUID().toString())
        .build();
    JWKSet jwkSet = new JWKSet(rsaKey);
    return new ImmutableJWKSet<>(jwkSet);
  }

  @Bean
  public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
    return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
  }

  @Bean
  public AuthorizationServerSettings authorizationServerSettings() {
    return AuthorizationServerSettings.builder().build();
  }


  // region Password Authenticator

  @Bean
  public PasswordEncoder passwordEncoder() {
    return app.passwordEncoder();
  }

  // endregion
}

And the Configuration from App 2 looks like this:

@Configuration
@EnableWebSecurity
public class AceSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .antMatcher("/**")
        .authorizeRequests()
        .antMatchers("/oauth/authorize**", "/login**", "/error**")
        .permitAll()
        .and()
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .oauth2Login( oauth2Login -> oauth2Login.defaultSuccessUrl("/index.html") );
  }
}

application.properties from App2 is:

spring.security.oauth2.client.registration.<provider-name>.client-id=${app.uuid}
spring.security.oauth2.client.registration.<provider-name>.client-secret=${app.secret}
spring.security.oauth2.client.registration.<provider-name>.scope=openid
spring.security.oauth2.client.registration.<provider-name>.redirect-uri=http://127.0.0.1:8088/login/oauth2/code/<provider-name>
spring.security.oauth2.client.registration.<provider-name>.client-name=${app.name}
spring.security.oauth2.client.registration.<provider-name>.provider=${provider.name}
spring.security.oauth2.client.registration.<provider-name>.client-authentication-method=code
spring.security.oauth2.client.registration.<provider-name>.authorization-grant type=authorization_code

spring.security.oauth2.client.provider.<provider-name>.authorization-uri=http://localhost:8086/oauth2/authorize
spring.security.oauth2.client.provider.<provider-name>.token-uri=http://localhost:8086/oauth2/token
spring.security.oauth2.client.provider.<provider-name>.user-info-uri=http://localhost:8086/oauth2/userinfo?schema=openid
spring.security.oauth2.client.provider.<provider-name>.user-name-attribute=name
spring.security.oauth2.client.provider.<provider-name>.user-info-authentication-method=header
spring.security.oauth2.client.provider.<provider-name>.jwk-set-uri=http://localhost:8086/jwks

The request from App2 to App 1 that causes the redirect is:

POST http://localhost:8086/oauth2/token

Body:
grant_type=authorization_code, 
code=Zls0ppjnS_RXyMVPB8fg_eQQgoiUAxRguOMsdyVYQpgd8eDkUDzgz813L0ybovTL7sNj0TDRUHibPfek9NzwULND1mty5WPW2DOtQjTAaEROL3qP7RvyTWXTEzzYe-o,
redirect_uri=[http://127.0.0.1:8088/login/oauth2/code/<provider-name>],
client_id=<app.uuid>

Header:
Accept:"application/json;charset=UTF-8", 
Content-Type:"application/x-www-form-urlencoded;charset=UTF-8"

答案1

得分: 0

以下是已翻译的部分:

对于遇到相同或类似问题的人。
实际问题是:

spring.security.oauth2.client.registration.<provider-name>.client-authentication-method=code.

数据库中声明了不同的身份验证方法。

另一个问题是PasswordEncoder的声明。
数据库中存储的密码是BCrypt加密的。
但共享密钥是未加密的,存储在数据库中(以便在前端显示)。
因此,比较这两个密钥时会出现问题。

英文:

For people running into the same or a similar problem.
The actual problem was:

spring.security.oauth2.client.registration.&lt;provider-name&gt;.client-authentication-method=code.

A different authentication method was declared in the database.

Another problem was the declaration of the PasswordEncoder.
Passwords in the database were stored BCrypt encrypted.
The shared secret, however, was stored unencrypted in the database (in order to be able to display it in the frontend).
So there was a problem comparing these two secrets.

huangapple
  • 本文由 发表于 2023年2月14日 20:29:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75447848.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定