- Added sample JWT authentication service

- Added jwt secret and duration to properties
- Added jwt dependencies
- Added SecureApiRestController
- Added UserEntity
- Added UserRepository.java
This commit is contained in:
Max W. 2024-04-07 18:25:39 +02:00
parent da5abba5b9
commit a93288e31c
8 changed files with 123 additions and 3 deletions

View File

@ -40,6 +40,10 @@ dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '3.2.4' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '3.2.4'
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api // https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.12.5' implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.12.5'
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.12.5'
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-orgjson
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-orgjson', version: '0.12.5'
} }

View File

@ -15,11 +15,11 @@ public class SecurityConfig {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http http
.authorizeHttpRequests(authorize -> authorize .authorizeHttpRequests(authorize -> authorize
.requestMatchers("/admin/**").authenticated() .requestMatchers("/api/v1/secure/**").authenticated()
.anyRequest().permitAll() .anyRequest().permitAll()
) )
.formLogin(formLogin -> formLogin .formLogin(formLogin -> formLogin
.loginPage("/login") .loginPage("/management/login")
.permitAll() .permitAll()
) )
.logout(LogoutConfigurer::permitAll) .logout(LogoutConfigurer::permitAll)

View File

@ -0,0 +1,4 @@
package de.w665.sharepulse.db.repo;
public class UserRepository {
}

View File

@ -0,0 +1,17 @@
package de.w665.sharepulse.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String username;
private String password;
private String email;
private String role;
}

View File

@ -0,0 +1,9 @@
package de.w665.sharepulse.rest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/v1/secure")
public abstract class SecureApiRestController {
}

View File

@ -0,0 +1,33 @@
package de.w665.sharepulse.rest.mappings;
import de.w665.sharepulse.service.AuthenticationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/api/v1/auth")
public class AuthenticationController {
private final AuthenticationService authenticationService;
public AuthenticationController(AuthenticationService authenticationService) {
this.authenticationService = authenticationService;
}
@PostMapping("/login")
public ResponseEntity<Object> createAuthenticationToken() {
String token = authenticationService.authenticate("test", "test");
Map<String, Object> response = new HashMap<>();
response.put("token", token);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}

View File

@ -0,0 +1,51 @@
package de.w665.sharepulse.service;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.crypto.SecretKey;
import java.util.Base64;
import java.util.Date;
@Slf4j
@Service
public class AuthenticationService {
@Value("${secureapi.jwt.secret}")
private String secretString;
@Value("${secureapi.jwt.expiration}")
private long expirationTime; // in milliseconds
private SecretKey secretKey;
@PostConstruct
public void init() {
System.out.println("Initializing secret key");
byte[] encodedKey = Base64.getEncoder().encode(secretString.getBytes()); // encode the secret key
this.secretKey = Keys.hmacShaKeyFor(encodedKey);
}
public String authenticate(String username, String password) {
// validate user credentials with repository and password hash algorithm
return generateToken(username);
// throw new RuntimeException("User authentication failed");
}
private String generateToken(String username) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
Date expiryDate = new Date(nowMillis + expirationTime);
return Jwts.builder()
.subject(username)
.issuedAt(now)
.expiration(expiryDate)
.signWith(secretKey)
.compact();
}
}

View File

@ -26,3 +26,5 @@ spring.data.rest.base-path=/api/v1
# Miscellaneous # Miscellaneous
server.port=80 server.port=80
spring.application.name=sharepulse spring.application.name=sharepulse
secureapi.jwt.secret=sampleKeyToChangeInProduction
secureapi.jwt.expiration=3600000