1. erro 401. Não consigo gerar o token usando o JS client, com authorization code

    Solucionada
    Boa tarde pessoal, tudo bem? Estou há 2 dias travado nessa aula, pois o meu foodanalytics não obtem sucesso na tentativa de gerar o token. Consigo só gerar o Código, porém depois dá a mensagem de erro em seguida "erro ao gerar token". Abaixo colocarei a stacktrace em modo debug, em seguida o código do meu client.js ( o front end nao mandarei pois está igual ao do curso) , em seguida o link do GIT Hub do meu projeto. OBS: todos os outros fluxos testei no postman e funcionam normal. Apenas esse usando o Client javascript, que dá problema. Testei tanto no Edge como Mozilla ou chrome. Ah, tentei fazer tudo o que os colegas já postaram aqui no fórum também ( da data de hoje para trás). Outra observação: as senhas que antes eram todas web123, mudei para 123 no meu projeto. meu github: https://github.com/antoniotnn/algafood-api-course client.js:
    const config = {
      clientId: "foodanalytics",
      clientSecret: "123",
      authorizeUrl: "http://auth.algafood.local:8080/oauth/authorize",
      tokenUrl: "http://localhost:8080/oauth/token",
      callbackUrl: "http://www.foodanalytics.local:8082",
      cozinhasUrl: "http://api.algafood.local:8080/v1/cozinhas"
    };
    
    let accessToken = "";
    
    function generateCodeVerifier() {
      let codeVerifier = generateRandomString(128);
      localStorage.setItem("codeVerifier", codeVerifier);
    
      return codeVerifier;
    }
    
    function generateRandomString(length) {
      let text = "";
      let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      
      for (let i = 0; i < length; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
      }
      
      return text;
    }
    
    function generateCodeChallenge(codeVerifier) {
      return base64URL(CryptoJS.SHA256(codeVerifier));
    }
    
    function getCodeVerifier() {
      return localStorage.getItem("codeVerifier");
    }
    
    function base64URL(string) {
      return string.toString(CryptoJS.enc.Base64).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
    }
    
    function consultar() {
      alert("Consultando recurso com access token " + accessToken);
    
      $.ajax({
        url: config.cozinhasUrl,
        type: "get",
    
        beforeSend: function(request) {
          request.setRequestHeader("Authorization", "Bearer " + accessToken);
        },
    
        success: function(response) {
          var json = JSON.stringify(response);
          $("#resultado").text(json);
        },
    
        error: function(error) {
          alert("Erro ao consultar recurso");
        }
      });
    }
    
    function gerarAccessToken(code) {
      alert("Gerando access token com code " + code);
     
      let codeVerifier = getCodeVerifier();
    
      let params = new URLSearchParams();
      params.append("grant_type", "authorization_code");
      params.append("code", code);
      params.append("redirect_uri", config.callbackUrl);
      params.append("client_id", config.clientId);
      params.append("code_verifier", codeVerifier);
    
      $.ajax({
        url: config.tokenUrl,
        type: "post",
        data: params.toString(),
        contentType: "application/x-www-form-urlencoded",
    
        success: function(response) {
          accessToken = response.access_token;
    
          alert("Access token gerado: " + accessToken);
        },
    
        error: function(error) {
          alert("Erro ao gerar access key");
        }
      });
    }
    
    function login() {
      let codeVerifier = generateCodeVerifier();
      let codeChallenge = generateCodeChallenge(codeVerifier);
    
      window.location.href = `${config.authorizeUrl}?response_type=code&client_id=${config.clientId}&redirect_uri=${config.callbackUrl}&code_challenge_method=s256&code_challenge=${codeChallenge}`;
    }
    
    $(document).ready(function() {
      let params = new URLSearchParams(window.location.search);
    
      let code = params.get("code");
    
      if (code) {
        // window.history.replaceState(null, null, "/");
        gerarAccessToken(code);
      }
    });
    
    $("#btn-consultar").click(consultar);
    $("#btn-login").click(login);
    STACK TRACE:
    2021-11-07 19:37:49.330 DEBUG 15868 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Securing GET /oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY
    2021-11-07 19:37:49.331 DEBUG 15868 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
    2021-11-07 19:37:49.335 DEBUG 15868 --- [nio-8080-exec-2] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint#authorize(Map, Map, SessionStatus, Principal)
    2021-11-07 19:37:49.335 DEBUG 15868 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
    2021-11-07 19:37:49.335 DEBUG 15868 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [GET /oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY] with attributes [authenticated]
    2021-11-07 19:37:49.336 DEBUG 15868 --- [nio-8080-exec-2] o.s.s.w.s.HttpSessionRequestCache        : Saved request http://api.algafood.local:8080/oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY to session
    2021-11-07 19:37:49.336 DEBUG 15868 --- [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@de748a0, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]
    2021-11-07 19:37:49.336 DEBUG 15868 --- [nio-8080-exec-2] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@2b64ae7b
    2021-11-07 19:37:49.336 DEBUG 15868 --- [nio-8080-exec-2] o.s.s.web.DefaultRedirectStrategy        : Redirecting to http://api.algafood.local:8080/login
    2021-11-07 19:37:49.336 DEBUG 15868 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
    2021-11-07 19:37:49.336 DEBUG 15868 --- [nio-8080-exec-2] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
    2021-11-07 19:37:49.337 DEBUG 15868 --- [nio-8080-exec-2] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    2021-11-07 19:37:49.341 DEBUG 15868 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing GET /login
    2021-11-07 19:37:49.341 DEBUG 15868 --- [nio-8080-exec-3] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
    2021-11-07 19:37:49.343 DEBUG 15868 --- [nio-8080-exec-3] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
    2021-11-07 19:37:49.344 DEBUG 15868 --- [nio-8080-exec-3] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
    2021-11-07 19:37:49.344 DEBUG 15868 --- [nio-8080-exec-3] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    2021-11-07 19:37:49.806 DEBUG 15868 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy        : Securing GET /favicon.ico
    2021-11-07 19:37:49.814 DEBUG 15868 --- [nio-8080-exec-4] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
    2021-11-07 19:37:49.815 DEBUG 15868 --- [nio-8080-exec-4] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
    2021-11-07 19:37:49.815 DEBUG 15868 --- [nio-8080-exec-4] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorized public object filter invocation [GET /favicon.ico]
    2021-11-07 19:37:49.815 DEBUG 15868 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy        : Secured GET /favicon.ico
    2021-11-07 19:37:49.815 DEBUG 15868 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : GET "/favicon.ico", parameters={}
    2021-11-07 19:37:49.816  WARN 15868 --- [nio-8080-exec-4] o.s.web.servlet.PageNotFound             : No mapping for GET /favicon.ico
    2021-11-07 19:37:49.816 DEBUG 15868 --- [nio-8080-exec-4] .m.m.a.ExceptionHandlerExceptionResolver : Using @ExceptionHandler com.algaworks.algafood.api.exceptionhandler.ApiExceptionHandler#handleException(Exception, WebRequest)
    2021-11-07 19:37:49.816 DEBUG 15868 --- [nio-8080-exec-4] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json;q=0.8', given [image/webp, image/apng, image/svg+xml, image/*, */*;q=0.8] and supported [application/json, application/*+json, application/json, application/*+json, application/cbor]
    2021-11-07 19:37:49.817 DEBUG 15868 --- [nio-8080-exec-4] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [com.algaworks.algafood.api.exceptionhandler.Problem@5601029d]
    2021-11-07 19:37:49.818  WARN 15868 --- [nio-8080-exec-4] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.web.servlet.NoHandlerFoundException: No handler found for GET /favicon.ico]
    2021-11-07 19:37:49.818 DEBUG 15868 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND
    2021-11-07 19:37:49.818 DEBUG 15868 --- [nio-8080-exec-4] w.c.HttpSessionSecurityContextRepository : Did not store anonymous SecurityContext
    2021-11-07 19:37:49.819 DEBUG 15868 --- [nio-8080-exec-4] w.c.HttpSessionSecurityContextRepository : Did not store anonymous SecurityContext
    2021-11-07 19:37:49.819 DEBUG 15868 --- [nio-8080-exec-4] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    2021-11-07 19:37:52.478 DEBUG 15868 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : Securing POST /login
    2021-11-07 19:37:52.479 DEBUG 15868 --- [nio-8080-exec-5] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
    2021-11-07 19:37:52.482 DEBUG 15868 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [com.algaworks.algafood.core.security.authorizationserver.JpaUserDetailsService.loadUserByUsername]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
    2021-11-07 19:37:52.482 DEBUG 15868 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1608307093<open>)] for JPA transaction
    2021-11-07 19:37:52.483 DEBUG 15868 --- [nio-8080-exec-5] o.s.jdbc.datasource.DataSourceUtils      : Setting JDBC Connection [HikariProxyConnection@1027700212 wrapping com.mysql.cj.jdbc.ConnectionImpl@470ff5cc] read-only
    2021-11-07 19:37:52.484 DEBUG 15868 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@2fc48d92]
    Hibernate: select usuario0_.id as id1_14_, usuario0_.data_cadastro as data_cad2_14_, usuario0_.email as email3_14_, usuario0_.nome as nome4_14_, usuario0_.senha as senha5_14_ from usuario usuario0_ where usuario0_.email=?
    Hibernate: select grupos0_.usuario_id as usuario_1_15_0_, grupos0_.grupo_id as grupo_id2_15_0_, grupo1_.id as id1_5_1_, grupo1_.nome as nome2_5_1_ from usuario_grupo grupos0_ inner join grupo grupo1_ on grupos0_.grupo_id=grupo1_.id where grupos0_.usuario_id=?
    Hibernate: select permissoes0_.grupo_id as grupo_id1_6_0_, permissoes0_.permissao_id as permissa2_6_0_, permissao1_.id as id1_9_1_, permissao1_.descricao as descrica2_9_1_, permissao1_.nome as nome3_9_1_ from grupo_permissao permissoes0_ inner join permissao permissao1_ on permissoes0_.permissao_id=permissao1_.id where permissoes0_.grupo_id=?
    Hibernate: select permissoes0_.grupo_id as grupo_id1_6_0_, permissoes0_.permissao_id as permissa2_6_0_, permissao1_.id as id1_9_1_, permissao1_.descricao as descrica2_9_1_, permissao1_.nome as nome3_9_1_ from grupo_permissao permissoes0_ inner join permissao permissao1_ on permissoes0_.permissao_id=permissao1_.id where permissoes0_.grupo_id=?
    2021-11-07 19:37:52.493 DEBUG 15868 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
    2021-11-07 19:37:52.493 DEBUG 15868 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1608307093<open>)]
    2021-11-07 19:37:52.494 DEBUG 15868 --- [nio-8080-exec-5] o.s.jdbc.datasource.DataSourceUtils      : Resetting read-only flag of JDBC Connection [HikariProxyConnection@1027700212 wrapping com.mysql.cj.jdbc.ConnectionImpl@470ff5cc]
    2021-11-07 19:37:52.495 DEBUG 15868 --- [nio-8080-exec-5] o.s.orm.jpa.JpaTransactionManager        : Closing JPA EntityManager [SessionImpl(1608307093<open>)] after transaction
    2021-11-07 19:37:52.951 DEBUG 15868 --- [nio-8080-exec-5] o.s.s.a.dao.DaoAuthenticationProvider    : Authenticated user
    2021-11-07 19:37:52.951 DEBUG 15868 --- [nio-8080-exec-5] .s.ChangeSessionIdAuthenticationStrategy : Changed session id from D2353697F745779ACE47C5D8E037B16C
    2021-11-07 19:37:52.952 DEBUG 15868 --- [nio-8080-exec-5] w.a.UsernamePasswordAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=com.algaworks.algafood.core.security.authorizationserver.AuthUser [Username=joao.ger@algafood.com.br, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=D2353697F745779ACE47C5D8E037B16C], Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]]
    2021-11-07 19:37:52.952 DEBUG 15868 --- [nio-8080-exec-5] o.s.s.web.DefaultRedirectStrategy        : Redirecting to http://api.algafood.local:8080/oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY
    2021-11-07 19:37:52.953 DEBUG 15868 --- [nio-8080-exec-5] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=com.algaworks.algafood.core.security.authorizationserver.AuthUser [Username=joao.ger@algafood.com.br, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=D2353697F745779ACE47C5D8E037B16C], Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@27af8ae1]
    2021-11-07 19:37:52.953 DEBUG 15868 --- [nio-8080-exec-5] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=com.algaworks.algafood.core.security.authorizationserver.AuthUser [Username=joao.ger@algafood.com.br, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=D2353697F745779ACE47C5D8E037B16C], Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]]] to HttpSession [org.apache.catalina.session.StandardSessionFacade@27af8ae1]
    2021-11-07 19:37:52.953 DEBUG 15868 --- [nio-8080-exec-5] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    2021-11-07 19:37:52.956 DEBUG 15868 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy        : Securing GET /oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY
    2021-11-07 19:37:52.957 DEBUG 15868 --- [nio-8080-exec-6] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=com.algaworks.algafood.core.security.authorizationserver.AuthUser [Username=joao.ger@algafood.com.br, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=D2353697F745779ACE47C5D8E037B16C], Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]]]
    2021-11-07 19:37:52.957 DEBUG 15868 --- [nio-8080-exec-6] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=com.algaworks.algafood.core.security.authorizationserver.AuthUser [Username=joao.ger@algafood.com.br, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=D2353697F745779ACE47C5D8E037B16C], Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]]]
    2021-11-07 19:37:52.958 DEBUG 15868 --- [nio-8080-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint#authorize(Map, Map, SessionStatus, Principal)
    2021-11-07 19:37:52.958 DEBUG 15868 --- [nio-8080-exec-6] o.s.s.w.s.HttpSessionRequestCache        : Loaded matching saved request http://api.algafood.local:8080/oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY
    2021-11-07 19:37:52.958 DEBUG 15868 --- [nio-8080-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorized filter invocation [GET /oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY] with attributes [authenticated]
    2021-11-07 19:37:52.958 DEBUG 15868 --- [nio-8080-exec-6] o.s.security.web.FilterChainProxy        : Secured GET /oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY
    2021-11-07 19:37:52.959 DEBUG 15868 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : GET "/oauth/authorize?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY", parameters={masked}
    2021-11-07 19:37:52.960 DEBUG 15868 --- [nio-8080-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint#authorize(Map, Map, SessionStatus, Principal)
    2021-11-07 19:37:52.960 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
    2021-11-07 19:37:52.960 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]
    2021-11-07 19:37:52.960 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.datasource.DataSourceUtils      : Fetching JDBC Connection from DataSource
    2021-11-07 19:37:52.962 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
    2021-11-07 19:37:52.962 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]
    2021-11-07 19:37:52.962 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.datasource.DataSourceUtils      : Fetching JDBC Connection from DataSource
    2021-11-07 19:37:52.964 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
    2021-11-07 19:37:52.964 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]
    2021-11-07 19:37:52.964 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.datasource.DataSourceUtils      : Fetching JDBC Connection from DataSource
    2021-11-07 19:37:52.966 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
    2021-11-07 19:37:52.966 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]
    2021-11-07 19:37:52.966 DEBUG 15868 --- [nio-8080-exec-6] o.s.jdbc.datasource.DataSourceUtils      : Fetching JDBC Connection from DataSource
    2021-11-07 19:37:52.968 DEBUG 15868 --- [nio-8080-exec-6] s.o.p.a.ApprovalStoreUserApprovalHandler : Looking up user approved authorizations for client_id=foodanalytics and username=joao.ger@algafood.com.br
    2021-11-07 19:37:52.968 DEBUG 15868 --- [nio-8080-exec-6] s.o.p.a.ApprovalStoreUserApprovalHandler : Valid user approved/denied scopes are []
    2021-11-07 19:37:52.968 DEBUG 15868 --- [nio-8080-exec-6] o.s.s.o.p.e.AuthorizationEndpoint        : Loading user approval page: forward:/oauth/confirm_access
    2021-11-07 19:37:52.968 DEBUG 15868 --- [nio-8080-exec-6] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.9, */*;q=0.8]
    2021-11-07 19:37:52.968 DEBUG 15868 --- [nio-8080-exec-6] o.s.w.servlet.view.InternalResourceView  : View name 'forward:', model {authorizationRequest=org.springframework.security.oauth2.provider.AuthorizationRequest@857f1e32, org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.ORIGINAL_AUTHORIZATION_REQUEST={approved=false, scope=[READ, WRITE], response_type=[code], state=null, redirect_uri=http://www.foodanalytics.local:8082, client_id=foodanalytics, authorities=[], resourceIds=[]}, response_type=code, redirect_uri=http://www.foodanalytics.local:8082, code_challenge_method=s256, scopes={scope.READ=false, scope.WRITE=false}, client_id=foodanalytics, code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY, org.springframework.validation.BindingResult.authorizationRequest=org.springframework.validation.BeanPropertyBindingResult: 0 errors, org.springframework.validation.BindingResult.org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.ORIGINAL_AUTHORIZATION_REQUEST=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
    2021-11-07 19:37:52.969 DEBUG 15868 --- [nio-8080-exec-6] o.s.w.servlet.view.InternalResourceView  : Forwarding to [/oauth/confirm_access]
    2021-11-07 19:37:52.969 DEBUG 15868 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : "FORWARD" dispatch for GET "/oauth/confirm_access?response_type=code&client_id=foodanalytics&redirect_uri=http://www.foodanalytics.local:8082&code_challenge_method=s256&code_challenge=VQ9YR1wxVKm_pTXVFCLl903Q_JKT9RUW4Og328mzwkY", parameters={masked}
    2021-11-07 19:37:52.970 DEBUG 15868 --- [nio-8080-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint#getAccessConfirmation(Map, HttpServletRequest)
    2021-11-07 19:37:52.970 DEBUG 15868 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : Exiting from "FORWARD" dispatch, status 200
    2021-11-07 19:37:52.971 DEBUG 15868 --- [nio-8080-exec-6] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
    2021-11-07 19:37:52.971 DEBUG 15868 --- [nio-8080-exec-6] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    2021-11-07 19:37:56.679 DEBUG 15868 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : Securing POST /oauth/authorize
    2021-11-07 19:37:56.679 DEBUG 15868 --- [nio-8080-exec-7] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=com.algaworks.algafood.core.security.authorizationserver.AuthUser [Username=joao.ger@algafood.com.br, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=D2353697F745779ACE47C5D8E037B16C], Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]]]
    2021-11-07 19:37:56.679 DEBUG 15868 --- [nio-8080-exec-7] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=com.algaworks.algafood.core.security.authorizationserver.AuthUser [Username=joao.ger@algafood.com.br, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=D2353697F745779ACE47C5D8E037B16C], Granted Authorities=[CONSULTAR_PEDIDOS, CONSULTAR_USUARIOS_GRUPOS_PERMISSOES, EDITAR_CIDADES, EDITAR_COZINHAS, EDITAR_ESTADOS, EDITAR_FORMAS_PAGAMENTO, EDITAR_RESTAURANTES, EDITAR_USUARIOS_GRUPOS_PERMISSOES, GERAR_RELATORIOS, GERENCIAR_PEDIDOS]]]
    2021-11-07 19:37:56.680 DEBUG 15868 --- [nio-8080-exec-7] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint#approveOrDeny(Map, Map, SessionStatus, Principal)
    2021-11-07 19:37:56.681 DEBUG 15868 --- [nio-8080-exec-7] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorized filter invocation [POST /oauth/authorize] with attributes [authenticated]
    2021-11-07 19:37:56.681 DEBUG 15868 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : Secured POST /oauth/authorize
    2021-11-07 19:37:56.681 DEBUG 15868 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : POST "/oauth/authorize", parameters={masked}
    2021-11-07 19:37:56.681 DEBUG 15868 --- [nio-8080-exec-7] .s.o.p.e.FrameworkEndpointHandlerMapping : Mapped to org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint#approveOrDeny(Map, Map, SessionStatus, Principal)
    2021-11-07 19:37:56.682 DEBUG 15868 --- [nio-8080-exec-7] o.s.web.servlet.view.RedirectView        : View [RedirectView], model {}
    2021-11-07 19:37:56.682 DEBUG 15868 --- [nio-8080-exec-7] o.s.web.servlet.DispatcherServlet        : Completed 303 SEE_OTHER
    2021-11-07 19:37:56.682 DEBUG 15868 --- [nio-8080-exec-7] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    2021-11-07 19:37:58.674 DEBUG 15868 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : Securing POST /oauth/token
    2021-11-07 19:37:58.674 DEBUG 15868 --- [nio-8080-exec-9] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
    2021-11-07 19:37:58.675 DEBUG 15868 --- [nio-8080-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
    2021-11-07 19:37:58.675 DEBUG 15868 --- [nio-8080-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [POST /oauth/token] with attributes [fullyAuthenticated]
    2021-11-07 19:37:58.675 DEBUG 15868 --- [nio-8080-exec-9] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@de748a0, matchingMediaTypes=[application/atom+xml, application/x-www-form-urlencoded, application/json, application/octet-stream, application/xml, multipart/form-data, text/xml], useEquals=false, ignoredMediaTypes=[*/*]]
    2021-11-07 19:37:58.675 DEBUG 15868 --- [nio-8080-exec-9] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using Or [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest], And [Not [MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@de748a0, matchingMediaTypes=[text/html], useEquals=false, ignoredMediaTypes=[]]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@de748a0, matchingMediaTypes=[application/atom+xml, application/x-www-form-urlencoded, application/json, application/octet-stream, application/xml, multipart/form-data, text/xml], useEquals=false, ignoredMediaTypes=[*/*]]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@de748a0, matchingMediaTypes=[*/*], useEquals=true, ignoredMediaTypes=[]]]
    2021-11-07 19:37:58.675 DEBUG 15868 --- [nio-8080-exec-9] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint@79ebe255
    2021-11-07 19:37:58.675 DEBUG 15868 --- [nio-8080-exec-9] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    2021-11-07 19:37:58.676 DEBUG 15868 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : Securing POST /error
    2021-11-07 19:37:58.676 DEBUG 15868 --- [nio-8080-exec-9] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
    2021-11-07 19:37:58.676 DEBUG 15868 --- [nio-8080-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
    2021-11-07 19:37:58.676 DEBUG 15868 --- [nio-8080-exec-9] o.s.security.web.FilterChainProxy        : Secured POST /error
    2021-11-07 19:37:58.676 DEBUG 15868 --- [nio-8080-exec-9] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for POST "/error", parameters={masked}
    2021-11-07 19:37:58.676 DEBUG 15868 --- [nio-8080-exec-9] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
    2021-11-07 19:37:58.676 DEBUG 15868 --- [nio-8080-exec-9] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
    2021-11-07 19:37:58.677 DEBUG 15868 --- [nio-8080-exec-9] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json, application/cbor]
    2021-11-07 19:37:58.678 DEBUG 15868 --- [nio-8080-exec-9] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [{timestamp=Sun Nov 07 19:37:58 UTC 2021, status=401, error=Unauthorized, message=Unauthorized, path= (truncated)...]
    2021-11-07 19:37:58.678 DEBUG 15868 --- [nio-8080-exec-9] w.c.HttpSessionSecurityContextRepository : Did not store anonymous SecurityContext
    2021-11-07 19:37:58.679 DEBUG 15868 --- [nio-8080-exec-9] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
    2021-11-07 19:37:58.679 DEBUG 15868 --- [nio-8080-exec-9] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 401
    2021-11-07 19:37:58.679 DEBUG 15868 --- [nio-8080-exec-9] w.c.HttpSessionSecurityContextRepository : Did not store anonymous SecurityContext
    2021-11-07 19:37:58.679 DEBUG 15868 --- [nio-8080-exec-9] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
    Log do Browser quando clico no token e deu o 401:
    URL da Solicitação: http://localhost:8080/oauth/token
    Método de solicitação: POST
    Código do status: 401 
    Endereço Remoto: [::1]:8080
    Política de referenciador: strict-origin-when-cross-origin
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Origin: http://www.foodanalytics.local:8082
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Connection: keep-alive
    Content-Encoding: gzip
    Content-Type: application/json
    Date: Sun, 07 Nov 2021 19:37:58 GMT
    Expires: 0
    Keep-Alive: timeout=60
    Pragma: no-cache
    Transfer-Encoding: chunked
    Vary: origin,access-control-request-method,access-control-request-headers,accept-encoding
    WWW-Authenticate: Basic realm="oauth2/client"
    X-Content-Type-Options: nosniff
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    Accept: */*
    Accept-Encoding: gzip, deflate, br
    Accept-Language: pt-BR,pt;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
    Connection: keep-alive
    Content-Length: 265
    Content-Type: application/x-www-form-urlencoded
    Host: localhost:8080
    Origin: http://www.foodanalytics.local:8082
    Referer: http://www.foodanalytics.local:8082/
    sec-ch-ua: "Microsoft Edge";v="95", "Chromium";v="95", ";Not A Brand";v="99"
    sec-ch-ua-mobile: ?0
    sec-ch-ua-platform: "Windows"
    Sec-Fetch-Dest: empty
    Sec-Fetch-Mode: cors
    Sec-Fetch-Site: cross-site
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 Edg/95.0.1020.44
    grant_type: authorization_code
    code: ZnuUi7
    redirect_uri: http://www.foodanalytics.local:8082
    client_id: foodanalytics
    code_verifier: 5Qv7B6LXaFApN3NdVghhIBz55n4L1NJgzYhLgLe7UUytx4uu6eI6cIoiQoPERRNwUzbxOtUHpJ5XvgJvlpvH7R933BjzRqy04jVRP6h3kv6VC106ve7CcDKj8pi0JZmA
    2 Respostas
  2. Olá Antonio, obrigado pelos detalhes! Gravei um vídeo explicando os problemas, basicamente existia um erro de configuração de CORS na API, e no front-end faltou enviar a autenticação Basic referente ao client Oauth2, na hora de pedir o token. https://www.loom.com/share/32b9914c80714162b9e7b05a9df6fd18 Segue o código-fonte corrigido:
    const config = {
        clientId: "foodanalytics",
        clientSecret: "food123",
        authorizeUrl: "http://auth.algafood.local:8080/oauth/authorize",
        tokenUrl: "http://localhost:8080/oauth/token",
        callbackUrl: "http://www.foodanalytics.local:8082",
        cozinhasUrl: "http://api.algafood.local:8080/v1/cozinhas"
    };
    
    let accessToken = "";
    
    function generateCodeVerifier() {
        let codeVerifier = generateRandomString(128);
        localStorage.setItem("codeVerifier", codeVerifier);
    
        return codeVerifier;
    }
    
    function generateRandomString(length) {
        let text = "";
        let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    
        for (let i = 0; i < length; i++) {
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        }
    
        return text;
    }
    
    function generateCodeChallenge(codeVerifier) {
        return base64URL(CryptoJS.SHA256(codeVerifier));
    }
    
    function getCodeVerifier() {
        return localStorage.getItem("codeVerifier");
    }
    
    function base64URL(string) {
        return string.toString(CryptoJS.enc.Base64).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
    }
    
    function consultar() {
        alert("Consultando recurso com access token " + accessToken);
    
        $.ajax({
            url: config.cozinhasUrl,
            type: "get",
    
            beforeSend: function (request) {
                request.setRequestHeader("Authorization", "Bearer " + accessToken);
            },
    
            success: function (response) {
                var json = JSON.stringify(response);
                $("#resultado").text(json);
            },
    
            error: function (error) {
                alert("Erro ao consultar recurso");
            }
        });
    }
    
    function gerarAccessToken(code) {
        alert("Gerando access token com code " + code);
    
        let codeVerifier = getCodeVerifier();
    
        let clientAuth = btoa(config.clientId + ":" + config.clientSecret);
    
        let params = new URLSearchParams();
        params.append("grant_type", "authorization_code");
        params.append("code", code);
        params.append("redirect_uri", config.callbackUrl);
        params.append("code_verifier", codeVerifier);
    
        $.ajax({
            url: config.tokenUrl,
            type: "post",
            data: params.toString(),
            contentType: "application/x-www-form-urlencoded",
    
            beforeSend: function(request) {
                request.setRequestHeader("Authorization", "Basic " + clientAuth);
            },    
    
            success: function (response) {
                accessToken = response.access_token;
    
                alert("Access token gerado: " + accessToken);
            },
    
            error: function (error) {
                alert("Erro ao gerar access key");
            }
        });
    }
    
    function login() {
        let codeVerifier = generateCodeVerifier();
        let codeChallenge = generateCodeChallenge(codeVerifier);
    
        window.location.href = `${config.authorizeUrl}?response_type=code&client_id=${config.clientId}&redirect_uri=${config.callbackUrl}&code_challenge_method=s256&code_challenge=${codeChallenge}`;
    }
    
    $(document).ready(function () {
        let params = new URLSearchParams(window.location.search);
    
        let code = params.get("code");
    
        if (code) {
            // window.history.replaceState(null, null, "/");
            gerarAccessToken(code);
        }
    });
    
    $("#btn-consultar").click(consultar);
    $("#btn-login").click(login);
    CorsConfig
    package com.algaworks.algafood.core.security;
    // Fonte: https://spring.io/blog/2015/06/08/cors-support-in-spring-framework#filter-based-cors-support
    
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.Ordered;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    import java.util.Arrays;
    import java.util.Collections;
    
    @Configuration
    public class CorsConfig {
    
    	@Bean
    	public FilterRegistrationBean<CorsFilter> corsFilterRegistrationBean() {
    		CorsConfiguration config = new CorsConfiguration();
    		config.setAllowCredentials(true);
    		config.addAllowedOriginPattern("*");
    		config.setAllowedOrigins(Arrays.asList("http://api.algafood.local:8080", "http://www.foodanalytics.local:5500"));
    		config.setAllowedMethods(Collections.singletonList("*"));
    		config.setAllowedHeaders(Collections.singletonList("*"));
    		
    		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    		source.registerCorsConfiguration("/**", config);
    
    		FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
    		bean.setFilter(new CorsFilter(source));
    		bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    		
    		return bean;
    	}
    
    }
    Insert do client no banco por conta da senha alterada.
    insert into oauth_client_details (
      client_id, resource_ids, client_secret, 
      scope, authorized_grant_types, web_server_redirect_uri, authorities,
      access_token_validity, refresh_token_validity, autoapprove
    )
    values (
      'foodanalytics', null, '$2a$10$TZErgO5Jbirt2GZh8MU/yukRgr/lIoAbL1Ea2bZRuyXOP7SrXwcDG',
      'READ,WRITE', 'authorization_code', 'http://www.foodanalytics.local:8082', null,
      null, null, null
    );
    Aguardo o seu retorno!
  3. Boa noite Alex, tudo bem? Primeiramente , muito obrigado pelo detalhamento técnico e por ter gravado um vídeo. Sempre obtive suporte muito bom no curso em texto, mas essa é a primeira vez que recebo um feedback personalizado assim. Fiquei muito contente com os resultados: isso mostra o quão qualidade a Algaworks tem. Já tinha visto vídeo para outros alunos, mas agora comigo a sensação foi diferente. Sobre o retorno, em relação a Classe CorsConfig, já tinha tentado de tudo e nada dado certo. Inclusive a passagem desse parâmetro ( source.registerCorsConfiguration("/**", config); que registra Todas as origens, mas mesmo assim sem sucesso, por isso deixei como melhor funcionava a api que era "/oauth/token" . Acredito que nessa classe, o que corrigiu mesmo foi o set config.setAllowedOrigins(Arrays.asList("http://api.algafood.local:8080", "http://www.foodanalytics.local:8082) , passando um Arrays.asList ao invés de "*" como já tinha passado antes ( por algum motivo não funcionava assim, tanto que estava comentada essa linha no meu projeto). Já no Front end o meu erro (ausência de passar o Basic) foi o crucial pra não funcionar. Corrigi toda a minha api baseado em suas alterações e agora funcionou tudo normalmente. Mais uma vez, muito obrigado pelo retorno e riqueza em detalhes na correção. Um abraço!