Spring authorization server latest version with PKCE + Angular SPA app 403 forbidden on...

Discussão em 'Angular' iniciado por San Jaisy, Novembro 30, 2024.

  1. San Jaisy

    San Jaisy Guest

    Security configuration

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {

    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer.authorizationServer();
    http
    .cors(Customizer.withDefaults())
    .authorizeHttpRequests(authz -> authz
    .requestMatchers(HttpMethod.POST, "/oauth2/jwks").hasAuthority("SCOPE_keys.write"))
    .securityMatchers(matchers ->
    matchers.requestMatchers(antMatcher("/oauth2/**"), authorizationServerConfigurer.getEndpointsMatcher()))
    .with(authorizationServerConfigurer, (authorizationServer) ->
    authorizationServer.oidc(Customizer.withDefaults())) // Enable OpenID Connect 1.0

    // 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((oauth2) -> oauth2.jwt(Customizer.withDefaults()));
    return http.build();
    }

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

    return http.build();
    }

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

    private static KeyPair generateRsaKey() {
    KeyPair keyPair;
    try {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048);
    keyPair = keyPairGenerator.generateKeyPair();
    } catch (Exception ex) {
    throw new IllegalStateException(ex);
    }
    return keyPair;
    }


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

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

    }


    Clients Registration

    @Configuration
    public class Clients {
    @Bean
    public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
    .clientId("stomble")
    .clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
    .authorizationGrantTypes(types -> {
    types.add(AuthorizationGrantType.AUTHORIZATION_CODE);
    types.add(AuthorizationGrantType.REFRESH_TOKEN);
    })
    .redirectUris(redirectUri -> {
    redirectUri.add("http://localhost:4200/");
    redirectUri.add("https://oauth.pstmn.io/v1/callback");
    redirectUri.add("http://localhost:4200/assets/silent-renew.html");
    redirectUri.add("http://localhost:4200/auth-callback");
    })
    .postLogoutRedirectUri("http://localhost:4200/")
    .scopes(score -> {
    score.add(OidcScopes.OPENID);
    score.add(OidcScopes.PROFILE);
    score.add(OidcScopes.EMAIL);
    })
    .clientSettings(ClientSettings.builder()
    .requireAuthorizationConsent(false)
    .requireProofKey(true)
    .build())
    .build();

    return new InMemoryRegisteredClientRepository(oidcClient);
    }
    }


    Angular App

    fetch("http://127.0.0.1:5100/oauth2/token", {
    "headers": {
    "accept": "application/json",
    "accept-language": "en-US,en;q=0.9",
    "content-type": "application/x-www-form-urlencoded",
    "sec-ch-ua": "\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"macOS\"",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "cross-site"
    },
    "referrer": "http://localhost:4200/",
    "referrerPolicy": "strict-origin-when-cross-origin",
    "body": "grant_type=authorization_code&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Fauth-callback&code=2y8jZGgxjkicK4kIxDTBfgS7gC7dm6yVDRpgRSL8f_eRCf0qe6zrO67q1S0xzl0DX5HD3quSGeSCRr59hSWQC8D7bfINM-YME4L8CcNAelx1KiKvLk5X6UUwgOQoCLps&code_verifier=0d335bff326449bfbaeeb1cc14ef005fae3ac7af0a6e4a9096c48b23988c8ad2206bae4ee2a64f5a975000b39ef8545f&client_id=stomble",
    "method": "POST",
    "mode": "cors",
    "credentials": "omit"
    });


    Payload

    grant_type: authorization_code
    redirect_uri: http://localhost:4200/auth-callback
    code: 2y8jZGgxjkicK4kIxDTBfgS7gC7dm6yVDRpgRSL8f_eRCf0qe6zrO67q1S0xzl0DX5HD3quSGeSCRr59hSWQC8D7bfINM-YME4L8CcNAelx1KiKvLk5X6UUwgOQoCLps
    code_verifier: 0d335bff326449bfbaeeb1cc14ef005fae3ac7af0a6e4a9096c48b23988c8ad2206bae4ee2a64f5a975000b39ef8545f
    client_id: stomble


    Network response

    Request URL:
    http://127.0.0.1:5100/oauth2/token
    Request Method:
    POST
    Status Code:
    403 Forbidden
    Remote Address:
    127.0.0.1:5100


    Using oidc-client.ts library with below configuration https://github.com/authts/oidc-client-ts

    openID = {
    authority: 'http://127.0.0.1:5100',
    client_id: 'stomble',
    redirect_uri: 'http://localhost:4200/auth-callback',
    post_logout_redirect_uri: 'http://localhost:4200',
    response_type: 'code',
    scope: 'openid profile email',
    automaticSilentRenew: false,
    silentRenewUrl: window.location.origin + '/assets/silent-renew.html',
    renewTimeBeforeTokenExpiresInSeconds: 10,
    autoUserInfo: false,
    };


    Authentication server logs

    logging.level.org.springframework.security.oauth2=trace

    server.port=5100


    logs

    2024-12-01T10:33:07.590+11:00 INFO 38608 --- [identity] [ restartedMain] stomble.identity.IdentityApplication : Starting IdentityApplication using Java 21.0.4 with PID 38608 (/Users/san/project/Sample/stomble/src/infrastructure/identity/build/classes/java/main started by san in /Users/san/project/Sample/stomble/src/infrastructure/identity)
    2024-12-01T10:33:07.593+11:00 INFO 38608 --- [identity] [ restartedMain] stomble.identity.IdentityApplication : No active profile set, falling back to 1 default profile: "default"
    2024-12-01T10:33:07.614+11:00 INFO 38608 --- [identity] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
    2024-12-01T10:33:07.614+11:00 INFO 38608 --- [identity] [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
    2024-12-01T10:33:08.058+11:00 INFO 38608 --- [identity] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 5100 (http)
    2024-12-01T10:33:08.065+11:00 INFO 38608 --- [identity] [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
    2024-12-01T10:33:08.066+11:00 INFO 38608 --- [identity] [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.33]
    2024-12-01T10:33:08.083+11:00 INFO 38608 --- [identity] [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
    2024-12-01T10:33:08.084+11:00 INFO 38608 --- [identity] [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 469 ms
    2024-12-01T10:33:08.259+11:00 INFO 38608 --- [identity] [ restartedMain] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with UserDetailsService bean with name userDetailsService
    2024-12-01T10:33:08.701+11:00 INFO 38608 --- [identity] [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
    2024-12-01T10:33:08.716+11:00 INFO 38608 --- [identity] [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 5100 (http) with context path '/'
    2024-12-01T10:33:08.722+11:00 INFO 38608 --- [identity] [ restartedMain] stomble.identity.IdentityApplication : Started IdentityApplication in 1.292 seconds (process running for 1.558)
    2024-12-01T10:33:23.013+11:00 INFO 38608 --- [identity] [nio-5100-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
    2024-12-01T10:33:23.013+11:00 INFO 38608 --- [identity] [nio-5100-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
    2024-12-01T10:33:23.014+11:00 INFO 38608 --- [identity] [nio-5100-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
    2024-12-01T10:33:23.062+11:00 TRACE 38608 --- [identity] [nio-5100-exec-2] izationCodeRequestAuthenticationProvider : Retrieved registered client
    2024-12-01T10:33:23.063+11:00 TRACE 38608 --- [identity] [nio-5100-exec-2] izationCodeRequestAuthenticationProvider : Validated authorization code request parameters
    2024-12-01T10:33:23.066+11:00 TRACE 38608 --- [identity] [nio-5100-exec-2] izationCodeRequestAuthenticationProvider : Generated authorization code
    2024-12-01T10:33:23.066+11:00 TRACE 38608 --- [identity] [nio-5100-exec-2] izationCodeRequestAuthenticationProvider : Saved authorization
    2024-12-01T10:33:23.066+11:00 TRACE 38608 --- [identity] [nio-5100-exec-2] izationCodeRequestAuthenticationProvider : Authenticated authorization code request
    2024-12-01T10:33:23.326+11:00 TRACE 38608 --- [identity] [nio-5100-exec-4] s.a.a.PublicClientAuthenticationProvider : Retrieved registered client
    2024-12-01T10:33:23.326+11:00 TRACE 38608 --- [identity] [nio-5100-exec-4] s.a.a.PublicClientAuthenticationProvider : Validated client authentication parameters
    2024-12-01T10:33:23.326+11:00 TRACE 38608 --- [identity] [nio-5100-exec-4] o.s.s.o.s.a.a.CodeVerifierAuthenticator : Retrieved authorization with authorization code
    2024-12-01T10:33:23.326+11:00 TRACE 38608 --- [identity] [nio-5100-exec-4] o.s.s.o.s.a.a.CodeVerifierAuthenticator : Validated code verifier parameters
    2024-12-01T10:33:23.326+11:00 TRACE 38608 --- [identity] [nio-5100-exec-4] o.s.s.o.s.a.a.CodeVerifierAuthenticator : Authenticated code verifier
    2024-12-01T10:33:23.326+11:00 TRACE 38608 --- [identity] [nio-5100-exec-4] s.a.a.PublicClientAuthenticationProvider : Authenticated public client
    2024-12-01T10:33:23.327+11:00 DEBUG 38608 --- [identity] [nio-5100-exec-4] o.s.a.w.OAuth2ClientAuthenticationFilter : Set SecurityContextHolder authentication to OAuth2ClientAuthenticationToken
    2024-12-01T10:33:23.329+11:00 TRACE 38608 --- [identity] [nio-5100-exec-4] .s.r.w.a.BearerTokenAuthenticationFilter : Did not process request since did not find bearer token


    Its says - Did not process request since did not find bearer token

    Same issue from Postman as well

    Continue reading...

Compartilhe esta Página