Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface ErrorDto {

export type Role = 'USER' | 'ADMIN' | 'BOT';

export interface MeResponse {
export interface UserAuthDto {
id: number;
name: string;
role: Role;
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/useAuth.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { createContext, useState, useContext, useEffect } from 'react';
import { JwtResponse, MeResponse } from "@/types.ts";
import { JwtResponse, UserAuthDto } from "@/types.ts";

interface Auth {
ready: boolean;
accessToken: string | null;
user: MeResponse | null;
user: UserAuthDto | null;
impersonating: string | null;
login: (token: string) => Promise<void>;
logout: () => Promise<void>;
Expand All @@ -18,15 +18,15 @@ const AuthContext = createContext<Auth | null>(null);
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [ready, setReady] = useState(false);
const [accessToken, setAccessToken] = useState<string | null>(null);
const [user, setUser] = useState<MeResponse | null>(null);
const [user, setUser] = useState<UserAuthDto | null>(null);
const [impersonating, setImpersonating] = useState<string | null>(null);

const fetchUserInfo = async (token: string): Promise<MeResponse> => {
const fetchUserInfo = async (token: string): Promise<UserAuthDto> => {
const response = await fetch('/api/auth/me', { headers: { 'Authorization': `Bearer ${token}` } });
if (!response.ok) {
throw new Error('Failed to fetch user info');
}
return await response.json() as MeResponse;
return await response.json() as UserAuthDto;
};

const login = async (token: string) => {
Expand All @@ -39,7 +39,7 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {

const logout = async () => {
try {
await fetch('/api/auth/logout', { method: 'POST', credentials: 'include' });
await fetch('/api/auth/refresh', { method: 'DELETE', credentials: 'include' });
} catch (error) {
console.error('Failed to call logout endpoint:', error);
}
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/icube/sim/tichu/auth/AuthController.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,22 @@ public JwtResponse refresh(
return new JwtResponse(jwtIssueResult.getAccessToken().toString());
}

@PostMapping("/logout")
// Mapped under /refresh (not /logout), so the refresh_token cookie, scoped to path /api/auth/refresh,
// is sent with the request.
@DeleteMapping("/refresh")
public ResponseEntity<@NonNull Void> logout(
@CookieValue(value = RefreshTokenCookieFactory.COOKIE_NAME, required = false) String refreshToken,
HttpServletResponse response
) {
authService.logout(refreshToken);
authService.destroyRefreshToken(refreshToken);
response.addCookie(refreshTokenCookieFactory.createExpired());
return ResponseEntity.noContent().build();
}

@GetMapping("/me")
public MeResponse getMe() {
public UserAuthDto getMe() {
var user = authService.getCurrentUser();
return new MeResponse(user.getId(), user.getName(), user.getRole());
return new UserAuthDto(user.getId(), user.getName(), user.getRole());
}

@GetMapping("/issue/web-socket-token")
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/icube/sim/tichu/auth/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public JwtIssueResult refreshTokens(String oldRefreshToken) {
return issueTokens(user);
}

public void logout(String refreshToken) {
public void destroyRefreshToken(String refreshToken) {
if (refreshToken == null) {
return;
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/icube/sim/tichu/auth/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) {
.authorizeHttpRequests(c -> c
.requestMatchers("/error").permitAll()
.requestMatchers(HttpMethod.POST, "/api/users").permitAll()
.requestMatchers(HttpMethod.POST, "/api/auth/login", "/api/auth/refresh", "/api/auth/logout").permitAll()
.requestMatchers(HttpMethod.POST, "/api/auth/login", "/api/auth/refresh").permitAll()
.requestMatchers(HttpMethod.DELETE, "/api/auth/refresh").permitAll()
.requestMatchers(HttpMethod.GET, "/api/auth/social/*/url").permitAll()
.requestMatchers(HttpMethod.POST, "/api/auth/social/*/login").permitAll()
.requestMatchers("/api/ws").permitAll()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@AllArgsConstructor
@Getter
public class MeResponse {
public class UserAuthDto {
private Long id;
private String name;
private Role role;
Expand Down