Reputation: 2252
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
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 sessionSpring-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.
With sample impls for Angular, React (Next.js) et Vue
Upvotes: 2
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