Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POST /logout response Forbidden 403 #179

Closed
TheNullablePrototype opened this issue Jan 21, 2024 · 9 comments
Closed

POST /logout response Forbidden 403 #179

TheNullablePrototype opened this issue Jan 21, 2024 · 9 comments
Assignees
Labels
invalid This doesn't seem right

Comments

@TheNullablePrototype
Copy link

Frontend (SPA / Vue.js 3)

Describe the bug
I'm following the bff turorial, and it looks like there was a problem implementing the logout.

First I saw a warning about CORS policy:
image

I'm not really sure if I did it right, but I did it like this:
application.yaml (Gateway)

scheme: http
issuer: http://localhost:9090/realms/client
client-id: 'client-id'
client-secret: 'client-secret'
user-name-attribute: 'preferred_username'
gateway-uri: ${scheme}://localhost:${server.port}
api-uri: ${scheme}://localhost:8090/api
ui-uri: ${scheme}://localhost:1000

spring:
  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: ${issuer}
            user-name-attribute: ${user-name-attribute}
        registration:
          keycloak:
            provider: keycloak
            client-id: ${client-id}
            client-secret: ${client-secret}
            authorization-grant-type: authorization_code
            scope:
              - openid
              - profile
              - email
              - offline_access
              - roles
  cloud:
    gateway:
      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
        - SaveSession
      routes:
        # set a redirection from / to the UI
        - id: home
          uri: ${ui-uri}
          predicates:
            - Path=/
          filters:
            - RedirectTo=301,${ui-uri}
        # BFF access to greetings API (with TokenRelay replacing session cookies with access tokens)
        # To be used by SPAs (Vue app in our case)
        - id: api-bff
          uri: ${api-uri}
          predicates:
            - Path=/bff/v1/**
          filters:
            - TokenRelay=
            - StripPrefix=2
        - id: ui
          uri: ${ui-uri}
          predicates:
            - Path=/ui/**

com:
  c4-soft:
    springaddons:
      oidc:
        ops:
          - iss: ${issuer}
            authorities:
              - path: $.realm_access.roles
            username-claim: ${user-name-attribute}
        client:
          client-uri: ${gateway-uri}
          security-matchers:
            - /login/**
            - /oauth2/**
            - /logout
            - /bff/**
          permit-all:
            - /login/**
            - /oauth2/**
            - /bff/**
          cors:
            - path: /bff/**
              allowed-origin-patterns:
                - ${gateway-uri}
                - https://localhost/
#       ======================================================== START "fix" CORS policy
            - path: /logout
              allowed-origin-patterns:
                - ${gateway-uri}
                - ${ui-uri}
                - https://localhost/
#       ======================================================== END "fix" CORS policy
          csrf: cookie-accessible-from-js
#          login-path: /ui/
#          post-login-redirect-path: /ui/
#          post-logout-redirect-path: /ui/
#          post-login-redirect-host: ${ui-uri}
          oauth2-redirections:
            rp-initiated-logout: NO_CONTENT

        resourceserver:
          permit-all:
            - /
            - /login-options
            - /ui/**
            - /actuator/health/readiness
            - /actuator/health/liveness
            - /favicon.ico
          cors:
            - path: /login-options
              allowed-origin-patterns:
                - ${gateway-uri}
                - ${ui-uri}
                - https://localhost/

After that, I started getting a new error when I requested it:
The request is ended with a 403 FORBIDDEN code and the response is: An expected CSRF token cannot be found.
This leads to NOT triggering the logout process for providers.

From example

const api = axios.create({
  transformRequest: [dateTransformer, ...axios.defaults.transformRequest],
  // withCredentials: true,
  timeout: 5000,
  headers: { 'Content-Type': 'application/json' }
})

// triggered on logout button
export const logout = async () => {
  return api.post('http://localhost:8080/logout').catch(handleCatch) 
}

As I understand it, cookies are not sent with this policy, how should I correctly implement the /logout request so that everything works "as it should"?
image

@TheNullablePrototype TheNullablePrototype added the bug Something isn't working label Jan 21, 2024
@ch4mpy ch4mpy added invalid This doesn't seem right and removed bug Something isn't working labels Jan 21, 2024
@ch4mpy
Copy link
Owner

ch4mpy commented Jan 21, 2024

I can spot quite a few mistakes above:

CORS

If you correctly use a reverse-proxy serving both UI and BFF, CORS configuration is not needed.

You are apparently sending a request to your BFF (http://localhost:8080) with http://localhost:1000 as origin. This is wrong.

The reason why you need a reverse-proxy serving both UI assets and BFF is that Spring session cookies are flagged with SameSite=Lax by default. So, for the browser to send session cookie with Vue requests to the BFF (and give the TokenRelay filter an opportunity to do its job), Vue app & BFF should have the same origin (the reverse-proxy).

In the tutorial, there is a route for the UI which makes the BFF itself a reverse-proxy for the UI:

      - id: ui
        uri: ${ui-uri}
        predicates:
        - Path=/ui/**

This enough to achieve same origin. You should probably restore this route and point your browser to http://localhost:8080/ui instead of http://localhost:1000.

This requires to set next.config.js with:

const nextConfig = {
    basePath: '/ui',
    assetPrefix: '/ui',
}

You should also probably restore the post-login & post-logout properties to redirect to your UI through the reverse-proxy (the default for a Spring OAuth2 client is itself and redirecting to the BFF will be problematic)

CSRF

In the case where the HTTP client you use in Vue does not handle CSRF tokens transparently (like Angular one does), you have to read the XSRF-TOKEN value (at least one GET requests to the backend must have been done for this cookie to be set) and provide it as X-XSRF-TOKEN header to your POST, PUT, PATCH and DELETE requests.

@TheNullablePrototype
Copy link
Author

Thanks for the answer, I will try to fix the errors and unsubscribe about the result.
Is it necessary for my frontend application to have the /ui suffix? I use Vite to build without Nuxt and TS

@ch4mpy
Copy link
Owner

ch4mpy commented Jan 21, 2024

you need something for the reverse-proxy to know that a request is for a Vue asset and that it should be routed to the whatever serves it (Vue dev-server on your dev machine). A path prefix is the easiest solution. Refer to Vite doc for how to set a baseHref (called basePath in next.js, so it's probably the same for Vite), I never used Vite.

@TheNullablePrototype
Copy link
Author

TheNullablePrototype commented Jan 21, 2024

I restored the configurations according to the tutorial, set the frontend base path of the application /ui
vite.config.mjs:

export default defineConfig({
  base: '/ui',
  // ...
  server: {
    proxy: {
      '/api': 'http://localhost:8080/bff/v1/'
    }
  },
  // ...
})

restored Gateway application.yaml:

scheme: http
issuer: http://localhost:9090/realms/client
client-id: 'client-id'
client-secret: 'client-secret'
user-name-attribute: 'preferred_username'
gateway-uri: ${scheme}://localhost:${server.port}
api-uri: ${scheme}://localhost:8090/api
ui-uri: ${scheme}://localhost:1000

spring:
  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: ${issuer}
            user-name-attribute: ${user-name-attribute}
        registration:
          keycloak:
            provider: keycloak
            client-id: ${client-id}
            client-secret: ${client-secret}
            authorization-grant-type: authorization_code
            scope:
              - openid
              - profile
              - email
              - offline_access
              - roles
  cloud:
    gateway:
      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
        - SaveSession
      routes:
        # set a redirection from / to the UI
        - id: home
          uri: ${gateway-uri}
          predicates:
            - Path=/
          filters:
            - RedirectTo=301,${gateway-uri}/ui/
        # BFF access to greetings API (with TokenRelay replacing session cookies with access tokens)
        # To be used by SPAs (Vue app in our case)
        - id: api-bff
          uri: ${api-uri}
          predicates:
            - Path=/bff/v1/**
          filters:
            - TokenRelay=
            - StripPrefix=2
        - id: ui
          uri: ${ui-uri}
          predicates:
            - Path=/ui/**

com:
  c4-soft:
    springaddons:
      oidc:
        ops:
          - iss: ${issuer}
            authorities:
              - path: $.realm_access.roles
            username-claim: ${user-name-attribute}
        client:
          client-uri: ${gateway-uri}
          security-matchers:
            - /login/**
            - /oauth2/**
            - /logout
            - /bff/**
          permit-all:
            - /login/**
            - /oauth2/**
            - /bff/**
          cors:
            - path: /bff/**
              allowed-origin-patterns:
                - ${gateway-uri}
                - https://localhost/
          csrf: cookie-accessible-from-js
          login-path: /ui/
          post-login-redirect-path: /ui/
          post-logout-redirect-path: /ui/
          oauth2-redirections:
            rp-initiated-logout: NO_CONTENT
        resourceserver:
          permit-all:
            - /
            - /login-options
            - /ui/**
            - /actuator/health/readiness
            - /actuator/health/liveness
            - /favicon.ico
          cors:
            - path: /login-options
              allowed-origin-patterns:
                - ${gateway-uri}
                - https://localhost/

Current application behavior:
frontend: browser -> localhost:1000 -> redirect -> localhost:1000/ui
backend: browser -> localhost:8080 -> redirect -> localhost:8080/ui // route with id home redirect

BUT i got 500 server error when reach localhost:8080/ui :
I really can't figure out why this is happening.

Whitelabel Error Page
This application has no configured error view, so you are seeing this as a fallback.

Sun Jan 21 21:09:11 MSK 2024
[07e90b85-16] There was an unexpected error (type=Internal Server Error, status=500).
Connection refused: getsockopt: localhost/127.0.0.1:1000
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: getsockopt: localhost/127.0.0.1:1000
	Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below: 
Assembly trace from producer [reactor.core.publisher.MonoError] :
	reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)
	reactor.netty.transport.TransportConnector$MonoChannelPromise.tryFailure(TransportConnector.java:576)
Error has been observed at the following site(s):
	*__FluxOnErrorResume$ResumeSubscriber.onError ⇢ at reactor.netty.transport.TransportConnector$MonoChannelPromise.tryFailure(TransportConnector.java:576)
	*__________________________Mono.onErrorResume ⇢ at reactor.netty.transport.TransportConnector.lambda$connect$6(TransportConnector.java:166)
	*________________________________Mono.flatMap ⇢ at reactor.netty.transport.TransportConnector.connect(TransportConnector.java:165)
	*_________________________________Mono.create ⇢ at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnectionAllocator.connectChannel(DefaultPooledConnectionProvider.java:535)
	*_________________________________Mono.create ⇢ at reactor.netty.resources.PooledConnectionProvider.acquire(PooledConnectionProvider.java:126)
	*_________________________________Mono.create ⇢ at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:210)
	|_                             Mono.retryWhen ⇢ at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:275)
	*______________________________Flux.concatMap ⇢ at reactor.util.retry.RetrySpec.lambda$generateCompanion$6(RetrySpec.java:360)
	|_                           Flux.onErrorStop ⇢ at reactor.util.retry.RetrySpec.lambda$generateCompanion$6(RetrySpec.java:379)
	*________________________Flux.deferContextual ⇢ at reactor.util.retry.RetrySpec.generateCompanion(RetrySpec.java:357)
	*____________________________Mono.flatMapMany ⇢ at reactor.netty.http.client.HttpClientFinalizer.responseConnection(HttpClientFinalizer.java:102)
	*___________________________________Flux.then ⇢ at org.springframework.cloud.gateway.filter.NettyRoutingFilter.filter(NettyRoutingFilter.java:198)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory$1.filter(SaveSessionGatewayFilterFactory.java:45)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory$1.filter(DedupeResponseHeaderGatewayFilterFactory.java:93)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.filter(NettyWriteResponseFilter.java:69)
	|_                            Mono.doOnCancel ⇢ at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.filter(NettyWriteResponseFilter.java:101)
	|_                             Mono.doOnError ⇢ at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.filter(NettyWriteResponseFilter.java:102)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	|_                             Mono.doFinally ⇢ at org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter.filter(RemoveCachedBodyFilter.java:35)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.web.reactive.result.SimpleHandlerAdapter.handle(SimpleHandlerAdapter.java:46)
	|_                         Mono.onErrorResume ⇢ at org.springframework.web.reactive.DispatcherHandler.handleResultMono(DispatcherHandler.java:168)
	|_                               Mono.flatMap ⇢ at org.springframework.web.reactive.DispatcherHandler.handleResultMono(DispatcherHandler.java:172)
	*__________________________________Mono.error ⇢ at org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handleException(RequestMappingHandlerAdapter.java:321)
	*________________________________Mono.flatMap ⇢ at org.springframework.web.reactive.DispatcherHandler.handle(DispatcherHandler.java:154)
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ com.c4_soft.springaddons.security.oidc.starter.reactive.client.ReactiveSpringAddonsOidcClientBeans$$Lambda/0x00000238cd5fc670 [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authorization.AuthorizationWebFilter.filter(AuthorizationWebFilter.java:56)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                         Mono.onErrorResume ⇢ at org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter.filter(ExceptionTranslationWebFilter.java:53)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*___________________________________Mono.then ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:63)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:63)
	|_                                   Mono.map ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:64)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:65)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:66)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*________________________________Mono.flatMap ⇢ at org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter.filter(ServerRequestCacheWebFilter.java:41)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                          Mono.contextWrite ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.lambda$filter$0(AnonymousAuthenticationWebFilter.java:86)
	*___________________________________Mono.then ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.lambda$filter$0(AnonymousAuthenticationWebFilter.java:87)
	*__________________________________Mono.defer ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.filter(AnonymousAuthenticationWebFilter.java:81)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.filter(AnonymousAuthenticationWebFilter.java:81)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.filter(AnonymousAuthenticationWebFilter.java:88)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*___________________________________Mono.then ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:114)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:114)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:115)
	|_                         Mono.onErrorResume ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:116)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                          Mono.contextWrite ⇢ at org.springframework.security.web.server.context.ReactorContextWebFilter.filter(ReactorContextWebFilter.java:48)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                          Mono.contextWrite ⇢ at org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter.filter(ServerHttpSecurity.java:3579)
	|_                                 checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*________________________________Mono.flatMap ⇢ at org.springframework.security.web.server.WebFilterChainProxy.filter(WebFilterChainProxy.java:63)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                             Mono.doOnError ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler.handle(ExceptionHandlingWebHandler.java:84)
	|_                         Mono.onErrorResume ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler.handle(ExceptionHandlingWebHandler.java:85)
	|_                             Mono.doOnError ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler.handle(ExceptionHandlingWebHandler.java:84)
	*__________________________________Mono.error ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler$CheckpointInsertingHandler.handle(ExceptionHandlingWebHandler.java:106)
	|_                                 checkpoint ⇢ HTTP GET "/ui/" [ExceptionHandlingWebHandler]
Original Stack Trace:
Caused by: java.net.ConnectException: Connection refused: getsockopt
	at java.base/sun.nio.ch.Net.pollConnect(Native Method)
	at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682)
	at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:973)
	at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337)
	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:335)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:776)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

@ch4mpy
Copy link
Owner

ch4mpy commented Jan 21, 2024

You don't want a proxy in your Vue conf, the BFF already is the proxy.

ui-uri should be set with ${scheme}://localhost:1000/ui, not with ${scheme}://localhost:1000.

It is expected that you get an exception on the BFF when you try to get ${scheme}:localhost:8080/ui with your current conf: it is trying to route to ${ui-uri} which is set to ${scheme}://localhost:1000 in your BFF conf, which is wrong because the dev server is configured to listen to http://localhost:1000/ui (which is right)

@TheNullablePrototype
Copy link
Author

TheNullablePrototype commented Jan 22, 2024

I have removed the proxy in the Vue configuration.

Current status of request execution:
image
image
I understand that I was making requests from localhost:1000, since localhost:8080 still does not allow a connection to /ui (see below)

Please note that there is no /ui in your example

Also added /ui to the parameter ui-uri:
ui-uri: ${scheme}://localhost:1000/ui
The error remained unchanged:

Whitelabel Error Page
This application has no configured error view, so you are seeing this as a fallback.

Mon Jan 22 12:00:05 MSK 2024
[72f050a6-4] There was an unexpected error (type=Internal Server Error, status=500).
Connection refused: getsockopt: localhost/127.0.0.1:1000
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: getsockopt: localhost/127.0.0.1:1000
	Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below: 
Assembly trace from producer [reactor.core.publisher.MonoError] :
	reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94)
	reactor.netty.transport.TransportConnector$MonoChannelPromise.tryFailure(TransportConnector.java:576)
Error has been observed at the following site(s):
	*__FluxOnErrorResume$ResumeSubscriber.onError ⇢ at reactor.netty.transport.TransportConnector$MonoChannelPromise.tryFailure(TransportConnector.java:576)
	*__________________________Mono.onErrorResume ⇢ at reactor.netty.transport.TransportConnector.lambda$connect$6(TransportConnector.java:166)
	*________________________________Mono.flatMap ⇢ at reactor.netty.transport.TransportConnector.connect(TransportConnector.java:165)
	*_________________________________Mono.create ⇢ at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnectionAllocator.connectChannel(DefaultPooledConnectionProvider.java:535)
	*_________________________________Mono.create ⇢ at reactor.netty.resources.PooledConnectionProvider.acquire(PooledConnectionProvider.java:126)
	*_________________________________Mono.create ⇢ at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:210)
	|_                             Mono.retryWhen ⇢ at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:275)
	*______________________________Flux.concatMap ⇢ at reactor.util.retry.RetrySpec.lambda$generateCompanion$6(RetrySpec.java:360)
	|_                           Flux.onErrorStop ⇢ at reactor.util.retry.RetrySpec.lambda$generateCompanion$6(RetrySpec.java:379)
	*________________________Flux.deferContextual ⇢ at reactor.util.retry.RetrySpec.generateCompanion(RetrySpec.java:357)
	*____________________________Mono.flatMapMany ⇢ at reactor.netty.http.client.HttpClientFinalizer.responseConnection(HttpClientFinalizer.java:102)
	*___________________________________Flux.then ⇢ at org.springframework.cloud.gateway.filter.NettyRoutingFilter.filter(NettyRoutingFilter.java:198)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory$1.filter(SaveSessionGatewayFilterFactory.java:45)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory$1.filter(DedupeResponseHeaderGatewayFilterFactory.java:93)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.filter(NettyWriteResponseFilter.java:69)
	|_                            Mono.doOnCancel ⇢ at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.filter(NettyWriteResponseFilter.java:101)
	|_                             Mono.doOnError ⇢ at org.springframework.cloud.gateway.filter.NettyWriteResponseFilter.filter(NettyWriteResponseFilter.java:102)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	|_                             Mono.doFinally ⇢ at org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter.filter(RemoveCachedBodyFilter.java:35)
	*__________________________________Mono.defer ⇢ at org.springframework.cloud.gateway.handler.FilteringWebHandler$DefaultGatewayFilterChain.filter(FilteringWebHandler.java:113)
	*___________________________________Mono.then ⇢ at org.springframework.web.reactive.result.SimpleHandlerAdapter.handle(SimpleHandlerAdapter.java:46)
	|_                         Mono.onErrorResume ⇢ at org.springframework.web.reactive.DispatcherHandler.handleResultMono(DispatcherHandler.java:168)
	|_                               Mono.flatMap ⇢ at org.springframework.web.reactive.DispatcherHandler.handleResultMono(DispatcherHandler.java:172)
	*__________________________________Mono.error ⇢ at org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter.handleException(RequestMappingHandlerAdapter.java:321)
	*________________________________Mono.flatMap ⇢ at org.springframework.web.reactive.DispatcherHandler.handle(DispatcherHandler.java:154)
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ com.c4_soft.springaddons.security.oidc.starter.reactive.client.ReactiveSpringAddonsOidcClientBeans$$Lambda/0x00000239815f7900 [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authorization.AuthorizationWebFilter.filter(AuthorizationWebFilter.java:56)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                         Mono.onErrorResume ⇢ at org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter.filter(ExceptionTranslationWebFilter.java:53)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*___________________________________Mono.then ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:63)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:63)
	|_                                   Mono.map ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:64)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:65)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.logout.LogoutWebFilter.filter(LogoutWebFilter.java:66)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*________________________________Mono.flatMap ⇢ at org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter.filter(ServerRequestCacheWebFilter.java:41)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                          Mono.contextWrite ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.lambda$filter$0(AnonymousAuthenticationWebFilter.java:86)
	*___________________________________Mono.then ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.lambda$filter$0(AnonymousAuthenticationWebFilter.java:87)
	*__________________________________Mono.defer ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.filter(AnonymousAuthenticationWebFilter.java:81)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.filter(AnonymousAuthenticationWebFilter.java:81)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter.filter(AnonymousAuthenticationWebFilter.java:88)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authentication.AnonymousAuthenticationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*___________________________________Mono.then ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:114)
	*__________________________Mono.switchIfEmpty ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:114)
	|_                               Mono.flatMap ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:115)
	|_                         Mono.onErrorResume ⇢ at org.springframework.security.web.server.authentication.AuthenticationWebFilter.filter(AuthenticationWebFilter.java:116)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                          Mono.contextWrite ⇢ at org.springframework.security.web.server.context.ReactorContextWebFilter.filter(ReactorContextWebFilter.java:48)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                          Mono.contextWrite ⇢ at org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter.filter(ServerHttpSecurity.java:3579)
	|_                                 checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	*________________________________Mono.flatMap ⇢ at org.springframework.security.web.server.WebFilterChainProxy.filter(WebFilterChainProxy.java:63)
	|_                                 checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
	*__________________________________Mono.defer ⇢ at org.springframework.web.server.handler.DefaultWebFilterChain.filter(DefaultWebFilterChain.java:106)
	|_                             Mono.doOnError ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler.handle(ExceptionHandlingWebHandler.java:84)
	|_                         Mono.onErrorResume ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler.handle(ExceptionHandlingWebHandler.java:85)
	|_                             Mono.doOnError ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler.handle(ExceptionHandlingWebHandler.java:84)
	*__________________________________Mono.error ⇢ at org.springframework.web.server.handler.ExceptionHandlingWebHandler$CheckpointInsertingHandler.handle(ExceptionHandlingWebHandler.java:106)
	|_                                 checkpoint ⇢ HTTP GET "/ui" [ExceptionHandlingWebHandler]
Original Stack Trace:
Caused by: java.net.ConnectException: Connection refused: getsockopt
	at java.base/sun.nio.ch.Net.pollConnect(Native Method)
	at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682)
	at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:973)
	at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:337)
	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:335)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:776)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

@ch4mpy
Copy link
Owner

ch4mpy commented Jan 22, 2024

Am I supposed to teach you programming or do your job (for free)? Also, should I really repeat myself?

Access to http://localhost:8080/login-options from origin http://localhost:1000 I wrote "point your browser to http://localhost:8080/ui instead of http://localhost:1000/.", but you(re still using http://localhost:1000...

Access to http://localhost:8080/api/users/me origin http://localhost:1000 same as above plus you are sending a request to /api/users/me when the prefix define for the BFF route is /bff/v1 and not /api

@ch4mpy ch4mpy closed this as completed Jan 22, 2024
@TheNullablePrototype
Copy link
Author

I apologize for the annoyance, the last thing I wanted to say is that I understood you perfectly, about the need to log into the browser localhost:8080/ui
I wrote about it above:
image
I just get the error when switching to localhost:8080/ui
What I wrote above about localhost:1000 is just a note that I have successfully added the base path/ui

As for the api/users/me, I completely agree, due to my carelessness, after deleting the proxy, I did not change the API links
Once again, I apologize for the inconvenience.

@TheNullablePrototype
Copy link
Author

Everything worked as it should, it turns out the frontend application needed to be launched --host

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

2 participants