Documentation Index
Fetch the complete documentation index at: https://docs.fitlocus.com/llms.txt
Use this file to discover all available pages before exploring further.
Autenticação e Autorização
O FitLocus implementa um sistema robusto de autenticação e autorização para proteger os dados dos usuários e garantir que apenas usuários autorizados possam acessar recursos específicos.
Visão Geral
O sistema de autenticação do FitLocus combina:
- Autenticação Tradicional: Login com email e senha
- Autenticação Social: Login com Google via Firebase Auth
- Tokens JWT: Para autenticação stateless entre cliente e servidor
- Controle de Acesso: Baseado em tipos de usuário e níveis de assinatura
Fluxo de Autenticação
Implementação no Backend
Configuração de Segurança
O backend utiliza Spring Security para configurar a segurança da API:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
// Outros beans e configurações...
}
Filtro JWT
Um filtro personalizado processa e valida os tokens JWT em cada requisição:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String token = extractTokenFromRequest(request);
if (token != null && jwtService.validateToken(token)) {
Authentication authentication = jwtService.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
// Métodos auxiliares...
}
Serviço JWT
Um serviço dedicado gerencia a criação, validação e extração de informações dos tokens JWT:
@Service
public class JwtService {
@Value("${jwt.secret}")
private String jwtSecret;
@Value("${jwt.expiration}")
private long jwtExpiration;
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
User user = (User) userDetails;
claims.put("id", user.getId());
claims.put("email", user.getEmail());
claims.put("userType", user.getUserType());
claims.put("subscriptionType", user.getSubscriptionType());
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
// Métodos para validação e extração de informações...
}
Para autenticação social, o backend integra-se com o Firebase Auth:
@Service
public class FirebaseAuthService {
private final FirebaseAuth firebaseAuth;
public FirebaseAuthService(FirebaseAuth firebaseAuth) {
this.firebaseAuth = firebaseAuth;
}
public FirebaseToken verifyIdToken(String idToken) throws FirebaseAuthException {
return firebaseAuth.verifyIdToken(idToken);
}
// Outros métodos relacionados ao Firebase Auth...
}
Implementação no Frontend
Armazenamento de Token
No frontend, o token JWT é armazenado de forma segura:
// Web (Next.js)
export const TOKEN_NAME = "fitlocus_auth_token";
export const setToken = (token: string) => {
Cookies.set(TOKEN_NAME, token, { expires: 7, path: "/" });
};
export const getToken = () => {
return Cookies.get(TOKEN_NAME);
};
export const removeToken = () => {
Cookies.remove(TOKEN_NAME, { path: "/" });
};
// Mobile (React Native)
export const setToken = async (token: string) => {
await AsyncStorage.setItem(TOKEN_NAME, token);
};
export const getToken = async () => {
return await AsyncStorage.getItem(TOKEN_NAME);
};
export const removeToken = async () => {
await AsyncStorage.removeItem(TOKEN_NAME);
};
Contexto de Autenticação
Um contexto React gerencia o estado de autenticação:
export const AuthContext = createContext<AuthContextData>({} as AuthContextData);
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const loadUser = async () => {
const token = getToken();
if (token) {
try {
const user = await authService.getAuthenticatedUser();
setUser(user);
} catch (error) {
removeToken();
}
}
setLoading(false);
};
loadUser();
}, []);
const login = async (credentials: LoginCredentials) => {
const response = await authService.login(credentials);
setToken(response.token);
setUser(response);
return response;
};
const register = async (userData: RegisterData) => {
const response = await authService.register(userData);
setToken(response.token);
setUser(response);
return response;
};
const loginWithGoogle = async (token: string, userType: string) => {
const response = await authService.handleGoogleAuth(token, userType);
setToken(response.token);
setUser(response);
return response;
};
const logout = () => {
removeToken();
setUser(null);
};
return (
<AuthContext.Provider value={{ user, loading, login, logout, register, loginWithGoogle }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
Proteção de Rotas
Web (Next.js)
No Next.js, um middleware protege as rotas que requerem autenticação:
export function middleware(request: NextRequest) {
const token = request.cookies.get(TOKEN_NAME)?.value;
const isAuthRoute = request.nextUrl.pathname.startsWith('/login') ||
request.nextUrl.pathname.startsWith('/registro');
const isDashboardRoute = request.nextUrl.pathname.startsWith('/dashboard');
if (!token && isDashboardRoute) {
return NextResponse.redirect(new URL('/login', request.url));
}
if (token && isAuthRoute) {
return NextResponse.redirect(new URL('/dashboard', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/login', '/registro'],
};
Mobile (React Native)
No React Native, um componente de rota protegida controla o acesso:
const ProtectedRoute = ({ children }: { children: React.ReactNode }) => {
const { user, loading } = useAuth();
const navigation = useNavigation();
useEffect(() => {
if (!loading && !user) {
navigation.navigate('Login');
}
}, [user, loading, navigation]);
if (loading) {
return <LoadingScreen />;
}
return user ? <>{children}</> : null;
};
Autorização
Além da autenticação, o sistema implementa autorização baseada em:
Tipos de Usuário
O sistema suporta diferentes tipos de usuário com permissões específicas:
public enum EnumUserType {
ALUNO,
PERSONAL
}
Níveis de Assinatura
Os recursos disponíveis também dependem do nível de assinatura do usuário:
public enum SubscriptionType {
FREEMIUM,
TRIAL,
PREMIUM_MENSAL,
PREMIUM_SEMESTRAL,
PREMIUM_ANUAL,
PERSONAL_INICIANTE, // até 10
PERSONAL_BASIC, // até 50
PERSONAL_INTERMEDIARIO, // até 100
PERSONAL_AVANCADO, // até 200
PERSONAL_ILIMITADO // 201+
}
Validadores de Acesso
Validadores específicos controlam o acesso a recursos premium:
@Component
public class SubscriptionValidator {
public boolean canAccessPremiumFeature(User user) {
if (user.getSubscriptionType() == SubscriptionType.FREEMIUM) {
return false;
}
if (user.getSubscriptionType() == SubscriptionType.TRIAL) {
LocalDate trialStartDate = user.getTrialStartDate();
LocalDate now = LocalDate.now();
return trialStartDate != null &&
ChronoUnit.DAYS.between(trialStartDate, now) <= 7;
}
return true;
}
// Outros métodos de validação...
}
Segurança Adicional
O sistema implementa medidas adicionais de segurança:
Proteção contra CSRF
Configuração para proteção contra ataques CSRF em endpoints sensíveis.
Limitação de Taxa
Limitação de tentativas de login para prevenir ataques de força bruta:
@Component
public class LoginAttemptService {
private final LoadingCache<String, Integer> attemptsCache;
public LoginAttemptService() {
attemptsCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.DAYS)
.build(new CacheLoader<String, Integer>() {
@Override
public Integer load(String key) {
return 0;
}
});
}
public void loginSucceeded(String key) {
attemptsCache.invalidate(key);
}
public void loginFailed(String key) {
int attempts = 0;
try {
attempts = attemptsCache.get(key);
} catch (ExecutionException e) {
attempts = 0;
}
attempts++;
attemptsCache.put(key, attempts);
}
public boolean isBlocked(String key) {
try {
return attemptsCache.get(key) >= 5;
} catch (ExecutionException e) {
return false;
}
}
}
Validação de Entrada
Validação rigorosa de todas as entradas do usuário para prevenir injeções e outros ataques.
Logs de Segurança
Registro de eventos de segurança para auditoria e detecção de atividades suspeitas.
Fluxo de Recuperação de Senha
O sistema também implementa um fluxo de recuperação de senha:
- Usuário solicita redefinição de senha fornecendo email
- Sistema gera token de redefinição com expiração
- Email enviado com link contendo o token
- Usuário acessa o link e define nova senha
- Sistema valida o token e atualiza a senha
Considerações de Segurança
- Senhas armazenadas com hash usando BCrypt
- Tokens JWT com tempo de expiração curto (1 hora)
- Renovação de tokens para sessões mais longas
- Validação de origem de requisições (CORS)
- Sanitização de dados de entrada e saída