And now here is my secret, a very simple secret: It is only with the heart that one can see rightly; what is essential is invisible to the eye. : The Fox
Day-1#to-do-
Breakfast was Amazing !! overnight oats
So let’s experiment with the api keys
what do we need ?

We are api keys
We get decrypted and then gets matched with our SHA 256 Hash and then if matched we become responsible for the person i.e. ADMIN who created us
So we need
- Generate api key
- Delete Api key
- Get Api Key Roles
- Catch the key in the security config
- Decrypt for role
- Pass it to the controller
- Fetch the User
So This APi key thing Worked pretty Nicely What did i learn. All this Ai coding is complete bullshit.
East or West VsCode is the best.
Also In Spring boot there is this thing in Security Principal and Authorities are something what they call the caller of a particular api
So
- Access Token Means ⇒ User
- X-Api-Key ⇒ System
All we need is to do this
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singletonList(
new SimpleGrantedAuthority("ROLE_" + role.name())
);
}Add this to the model
And then add the role to the request thus and spring will map it to Authentication Proncipal
package io.saanvi.saanvibackend.shared.utils;
import io.saanvi.saanvibackend.auth.models.ApiKey;
import io.saanvi.saanvibackend.auth.services.ApiKeyService;
import io.saanvi.saanvibackend.auth.services.TokenService;
import io.saanvi.saanvibackend.user.model.User;
import io.saanvi.saanvibackend.user.services.UserService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException;
import java.io.IOException;
import java.util.Optional;
@Component
public class requestFilter extends OncePerRequestFilter {
@Autowired
protected UserService userService;
@Autowired
protected ApiKeyService apiKeyService;
private static final String[] EXCLUDED_PATHS = {
"/auth/login",
/**
* Fetches the Bearer token from the Authorization header of the request.
*
* @param request The HttpServletRequest object containing the request details.
* @return An Optional containing the Bearer token if present, otherwise an empty Optional.
*/
protected Optional<String> fetchBearerToken(HttpServletRequest request) {
String token = request.getHeader("Authorization");
return (token != null && token.startsWith("Bearer ")) ?
Optional.of(token.substring(7)) :
Optional.empty();
}
/**
* Fetches the API key from the request header.
*
* @param request The HttpServletRequest object containing the request details.
* @return An Optional containing the API key if present, otherwise an empty Optional.
*/
protected Optional<String> fetchApiKey(HttpServletRequest request) {
String apiKey = request.getHeader("X-API-KEY");
return (apiKey != null && !apiKey.isEmpty()) ?
Optional.of(apiKey) :
Optional.empty();
}
/**
* Filters incoming requests to check for a valid JWT token.
* If a valid token is found, it sets the authentication in the SecurityContext.
*
* @param request The HttpServletRequest object containing the request details.
* @param response The HttpServletResponse object for sending the response.
* @param filterChain The FilterChain to continue the request processing.
* @throws ServletException If an error occurs during request processing.
* @throws IOException If an I/O error occurs during request processing.
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain )throws ServletException, IOException {
String path = request.getRequestURI();
for (String excluded : EXCLUDED_PATHS) {
if (path.startsWith(excluded)) {
filterChain.doFilter(request, response);
return;
}
}
Optional<String> bearerToken = fetchBearerToken(request);
Optional<String> apiKey = fetchApiKey(request);
if(apiKey.isPresent()){
try {
logger.info(hashUtil.getHashedValue(apiKey.get()));
Optional<ApiKey> _apiKeyDetails = apiKeyService.findByApiKey(hashUtil.getHashedValue(apiKey.get()));
if (_apiKeyDetails.isEmpty()) throw new Error("Invalid API key");
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(_apiKeyDetails.get(), null, _apiKeyDetails.get().getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
throw new Error("Invalid API key");
}
filterChain.doFilter(request, response);
}
else if(bearerToken.isPresent()){
String token = bearerToken.get();
String userId;
try {
userId = TokenService.validateAccessToken(token);
User user = userService.findUserById(userId);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (Exception e) {
throw new Error("Invalid token");
}
}
filterChain.doFilter(request, response);
}
}
And wait to use it as a
@GetMapping("/users/me") // User Response
public ResponseEntity<User> getAuthenticatedUser(@AuthenticationPrincipal User user) {
return ResponseEntity.ok(user);
}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/users")
public List<User> getAllUsers(){ // [User Response]
logger.info("Fetching all users");
return userService.findAll();
}
Now Both From api key and Access-token we can call the Service and check the authority of that request
- Generate api key : Done
- Delete Api key : Done
- Get Api Key Roles : Done
- Catch the key in the security config : Done
- Decrypt for role : Done
- Pass it to the controller : Done
- Fetch the User : Done
To Do
- Make the login api Live
- Make Entity Use it
- Make Saanvi Live