usertest
usertest

Reputation: 2252

How a react application connect to an OAuth 2 Spring authorization server/ resource server / oauth client Backend

I have implemented an OAuth 2 spring autorization server that generate tokens. port 4002

a spring resource server for api calls. port 4003

a spring oauth client that handles communication with the authorization server. port 4004

everything works. 1 enterting http://127.0.0.1:4004 (client) redirect you to http://127.0.0.1:4002/login (authorization server) after entering correct email and password, the authorization server redirect you to http://127.0.0.1:4004 (client), which on succusfull authentication show a simple static html file. here is a video of the whole process https://imgur.com/a/8uaTcZk

now this is all good and well, the backend of OAuth 2 is fully implemented. Now I would like to write a React application that uses this backend. how am I supposed to do that?

After researching this people said use Backend for frontend BFF. but I cannot find any tutorial or article that explain how to connect to spring oauth client.

Before the react application sends email/password and gets back a token that I save in localStorage. which I programmed axios to use, so every call to the backend has the token attached.

Now I would like to move to OAuth 2. but even though I implemented all the parts in Spring according to the specification. I'm stuck at what should I do to connect the react app to OAuth process.

Currently the the authorization server is set to redirect to http://localhost:4004/login/oauth2/code/token-generator which is the oauth client after successful login. that's not what I want. I want it to redirect to the react app. but the spring docs says that the redirect path should be /login/oauth2/code/{authorization-server} I'm not interesseted in the oauth client showing a .html . I would like it to redirect to the frontend. But I have no idea how the front is supposed to get the token or if the token should not leave the oauth client!!??

Can anyone help with this?

here is some parts of the code: authorization server RegisteredClientRepository (4002)

@Bean
    public RegisteredClientRepository registeredClientRepository() {
        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("client")
                .clientSecret("{bcrypt}$2a$10$.ld6BfZescPDfVVduvu.6O9.7FLMI64l4PfvnBZJQEBhTLFFbeKei") //secret
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                .redirectUri("http://localhost:4004/login/oauth2/code/token-generator")
                .scope(OidcScopes.OPENID)       .tokenSettings(TokenSettings.builder().accessTokenTimeToLive(Duration.ofHours(12)).build())
                .build();
        return new InMemoryRegisteredClientRepository(registeredClient);
    }

client config (4004)

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http.oauth2Login(Customizer.withDefaults());
        http.authorizeHttpRequests(
                c -> c.anyRequest().authenticated());

        return http.build();
    }
}

client "/" path, that show Home at the end of the video

@Controller
public class HomeController {

    @GetMapping("/")
    public String home(OAuth2AuthenticationToken authentication) {
        return "index.html";
    }
}

Upvotes: 1

Views: 2232

Answers (2)

ch4mp
ch4mp

Reputation: 12564

You are almost there: when OAuth2 and Spring are involved, a BFF is an OAuth2 client with:

  • oauth2Login(), just as your app running on port 4004 is, to fetch tokens from the authorization server and store it in session
  • a mechanism to bridge between session security (your React app will authorize its requests to the BFF with session cookies) and Bearer token security (the requests forwarded from the BFF to a resource server will be authorized with the access token in session)

Spring-cloud-gateway has a TokenRelay filter to achieve exactly the second point.

I have written a tutorial to help you implement a BFF with spring-cloud-gateway which should soon be available from Baeldung.

Edit: the tutorial is now available from Baeldung

With sample impls for Angular, React (Next.js) et Vue

Upvotes: 2

Toerktumlare
Toerktumlare

Reputation: 14712

The misstake you are making is that you are doing some poor assumptions that most people that have not read the specification do.

What you have implemented is called a private client, this means that your sprihng security server is the only one that is communicating with the issuer.

During an oauth2 flow, the token if in for example a JWT format is never going to leave your backend of the simple fact that there is no way of storing a JWT securely in the browser.

So when implementing the flow you have done, the JWT is always only stored on the server side, and your oauth2 client server will return a cookie to the calling client.

Your webpage is a client against the server, the server is a oauth2 client against the issuer.

You have not disclosed what issuer you are using, and what your intentions are. You need to realize that the oauth2 spec is a quite large spec with several different flows, several different implementation etc. and you are very vague in your statements of what it is you want to achieve.

The BFF pattern basically means what you have implemented, its just that you think that the token should be handed out the the web client which it will not.

The spec is quite large, which means i cant in a simple answer on stack overflow explain the spec for you so my actual proper suggest is that if you are serious about understanding this you should definitely read the spec.

Also not all issuers support the full spec, for instance, if you are integrating againt google, github, facebook, they will not support the resource server part of the specification.

We can't have a proper discussion unless you read the specification, and thats why i can't give you a deeper answer than this.

https://datatracker.ietf.org/doc/html/rfc6749

Upvotes: 0

Related Questions