I am trying to fetch my API (Spring Boot) in React. I am trying to get the name of the logged in user and display it on the frontend.
Dashboard.js
import React, { useState, useEffect } from 'react';
import { httpClient } from '../HttpClient';
import Keycloak from 'keycloak-js';
import '../stylesheets/Dashboard.css';
import Button from "../components/Button"
let initOptions = {
url: 'http://localhost:8081/',
realm: 'BlacklightsRealm',
clientId: 'client1',
}
let kc = new Keycloak(initOptions);
kc.init({
onLoad: 'login-required',
checkLoginIframe: true,
pkceMethod: 'S256'
})
.then((auth) => {
if (!auth) {
window.location.reload();
} else {
httpClient.defaults.headers.common['Authorization'] = `Bearer ${kc.token}`;
kc.onTokenExpired = () => {
console.log('token expired')
}
}
}, () => {
console.error("Authentication Failed");
});
const Dashboard = () => {
const [name, setName] = useState('')
useEffect(() => {
getUserInfo();
}, []);
const getUserInfo = () => {
fetch('http://localhost:8080/info', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${kc.token}`
}
})
.then(res => res.json())
.then(data => {
console.log(data.name);
setName(data.name);
})
.catch(error => console.error('Error fetching user info:', error));
};
const [infoMessage, setInfoMessage] = useState('');
const logout = () => {
kc.logout({ redirectUri: 'http://localhost:3000/' });
setInfoMessage('Logging out...');
}
return (
<>
<div className="container">
<div className="header">Welcome, {name}!</div>
<div className="content"><h3>{infoMessage}</h3></div>
<div className="footer">
<Button onClick={logout}>Logout</Button>
</div>
</div>
</>
);
}
export default Dashboard;
HomeController.java
package com.blacklight.cloudgallery.controllers;
import com.blacklight.cloudgallery.services.UserService;
import org.keycloak.KeycloakPrincipal;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.representations.AccessToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
@RestController
@CrossOrigin("*")
public class HomeController {
@Autowired
private UserService userService;
public HomeController(UserService userService) {
this.userService = userService;
}
@GetMapping("/info")
public ResponseEntity<UserInfo> getUserInfo(Principal principal) {
KeycloakPrincipal<KeycloakSecurityContext> keycloakPrincipal = (KeycloakPrincipal<KeycloakSecurityContext>) principal;
AccessToken accessToken = keycloakPrincipal.getKeycloakSecurityContext().getToken();
String name = accessToken.getName();
UserInfo userInfo = new UserInfo(name);
return ResponseEntity.ok(userInfo);
}
public class UserInfo {
private String name;
public UserInfo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
SecurityConfig
package com.blacklight.cloudgallery.config;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.List;
import static org.springframework.security.config.Customizer.withDefaults;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.cors(withDefaults())
.authorizeHttpRequests(auth -> {
auth.requestMatchers("/").permitAll();
//auth.requestMatchers("/images").hasAuthority("SCOPE_admin");
auth.anyRequest().authenticated();
})
.oauth2ResourceServer((oauth2) -> oauth2
.jwt(withDefaults())
)
.oauth2Client(withDefaults())
//.oauth2Login(withDefaults())
//.formLogin(withDefaults())
.build();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(List.of("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
enter image description here
I tried to find some blockades in my Keycloak configuration but didn’t find anything. I expect that the name is displayed. I already handled CORS-error with the ‘CorsConfigurationSource’. I really don’t know how to solve the problem. Please tell me if you need more details.
Thank you.
Blacklight is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.