Filtro de Seguridad Spring con integración OIDC para Casdoor
Casdoor es un IDP de código abierto que soporta OIDC y varios otros protocolos. En este artículo, veremos cómo integrar Casdoor con tu aplicación usando el Filtro de Seguridad Spring y OIDC.
Paso 1: Desplegar Casdoor
Primero, necesitas desplegar el servidor Casdoor. Consulta la documentación oficial para instrucciones de instalación del servidor. Después del despliegue exitoso, asegúrate de que:
- El servidor Casdoor está funcionando en http://localhost:8000.
- Puedes ver la página de inicio de sesión de Casdoor en http://localhost:7001.
- Puedes probar la funcionalidad de inicio de sesión iniciando sesión con las credenciales
admin
y123
.
Después de verificar estos pasos, sigue los pasos a continuación para integrar Casdoor con tu aplicación.
Paso 2: Configurar la Aplicación Casdoor
- Crea una nueva aplicación Casdoor o usa una existente.
- Agrega tu URL de redirección. Puedes encontrar más información sobre cómo obtener la URL de redirección en la siguiente sección.
- Obtén tu
Certificado
en la página de edición de certificados. - Agrega el proveedor y otros ajustes según sea necesario.
Puedes obtener los valores para Nombre de la Aplicación
, Nombre de la Organización
, URL de Redirección
, ID del Cliente
, Secreto del Cliente
y Certificado
en la página de configuración de la aplicación. Los usaremos en el siguiente paso.
Paso 3: Configurar Spring Security
Puedes personalizar la configuración de los filtros de Spring Security para procesar tokens:
Asegúrate de reemplazar los valores de configuración con los de tu propia instancia de Casdoor, especialmente <Client ID>
y los demás.
server:
port: 8080
casdoor:
endpoint: http://CASDOOR_HOSTNAME:8000
client-id: <Client ID>
client-secret: <Client Secret>
certificate: <Certificate>
organization-name: <Organization Name>
application-name: <Application Name>
redirect-url: http://FRONTEND_HOSTNAME/callback
Para aplicaciones frontend, el valor predeterminado de <FRONTEND_HOSTNAME>
es localhost:3000
. En esta demostración, la URL de redirección es http://localhost:3000/callback
. Asegúrate de configurar esto en tu aplicación casdoor
.
Paso 4: Configurar Frontend
Necesitas instalar casdoor-js-sdk
y configurar el SDK de la siguiente manera:
Instalar
casdoor-js-sdk
.npm i casdoor-js-sdk
# or
yarn add casdoor-js-sdkConfigurar
SDK
.import Sdk from "casdoor-js-sdk";
// Serverurl is the URL where spring security is deployed
export const ServerUrl = "http://BACKEND_HOSTNAME:8080";
const sdkConfig = {
serverUrl: "http://CASDOOR_HOSTNAME:8000",
clientId: "<your client id>",
appName: "<your application name>",
organizationName: "<your organization name>",
redirectPath: "/callback",
};
export const CasdoorSDK = new Sdk(sdkConfig);
Paso 5: Configurar una Demostración
Crea una aplicación Spring Boot.
Agrega algunas configuraciones para manejar JWT.
@EnableWebSecurity
public class SecurityConfig {
private final JwtTokenFilter jwtTokenFilter;
public SecurityConfig(JwtTokenFilter jwtTokenFilter) {
this.jwtTokenFilter = jwtTokenFilter;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// enable CORS and disable CSRF
http = http.cors(corsConfig -> corsConfig
.configurationSource(configurationSource())
).csrf().disable();
// set session management to stateless
http = http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and();
// set permissions on endpoints
http.authorizeHttpRequests(authorize -> authorize
.mvcMatchers("/api/redirect-url", "/api/signin").permitAll()
.mvcMatchers("/api/**").authenticated()
);
// set unauthorized requests exception handler
http = http
.exceptionHandling()
.authenticationEntryPoint(
(request, response, ex) -> ResponseUtils.fail(response, "unauthorized")
)
.and();
// add JWT token filter
http.addFilterBefore(
jwtTokenFilter,
UsernamePasswordAuthenticationFilter.class
);
return http.build();
}
// ...
}
```
Agrega un filtro JWT simple para interceptar solicitudes que requieren verificación de token.
@Component
public class JwtTokenFilter extends OncePerRequestFilter {
private final CasdoorAuthService casdoorAuthService;
public JwtTokenFilter(CasdoorAuthService casdoorAuthService) {
this.casdoorAuthService = casdoorAuthService;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain)
throws ServletException, IOException {
// get authorization header and validate
final String header = request.getHeader(HttpHeaders.AUTHORIZATION);
if (!StringUtils.hasText(header) || !header.startsWith("Bearer ")) {
chain.doFilter(request, response);
return;
}
// get jwt token and validate
final String token = header.split(" ")[1].trim();
// get user identity and set it on the spring security context
UserDetails userDetails = null;
try {
CasdoorUser casdoorUser = casdoorAuthService.parseJwtToken(token);
userDetails = new CustomUserDetails(casdoorUser);
} catch (CasdoorAuthException exception) {
logger.error("casdoor auth exception", exception);
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails,
null,
AuthorityUtils.createAuthorityList("ROLE_casdoor")
);
authentication.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
}Cuando el usuario accede a la interfaz que requiere autenticación,
JwtTokenFilter
obtendrá el token del encabezado de la solicitudAuthorization
y lo verificará.Define un
Controller
para manejar cuando el usuario inicia sesión en Casdoor. Después de que el usuario inicie sesión, será redirigido al servidor y llevará elcode
y elstate
. El servidor entonces necesita verificar la identidad del usuario desde Casdoor y obtener eltoken
a través de estos dos parámetros.@RestController
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
private final CasdoorAuthService casdoorAuthService;
// ...
@PostMapping("/api/signin")
public Result signin(@RequestParam("code") String code, @RequestParam("state") String state) {
try {
String token = casdoorAuthService.getOAuthToken(code, state);
return Result.success(token);
} catch (CasdoorAuthException exception) {
logger.error("casdoor auth exception", exception);
return Result.failure(exception.getMessage());
}
}
// ...
}
```
Paso 6: Probar la Demostración
Puedes acceder a la aplicación frontend a través de tu navegador. Si no has iniciado sesión, verás un botón de inicio de sesión. Haz clic en él, y serás redirigido a la página de inicio de sesión de Casdoor.
Si visitas tu página raíz,
Haz clic en el botón Iniciar Sesión Casdoor
, y la página te redirigirá a la página de inicio de sesión de Casdoor.
Después de iniciar sesión, serás redirigido a /
.