Compare commits
No commits in common. "main" and "sample-java-jwt-auth-app" have entirely different histories.
main
...
sample-jav
@ -10,4 +10,12 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./sql-scripts:/docker-entrypoint-initdb.d
|
- ./sql-scripts:/docker-entrypoint-initdb.d
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
|
|
||||||
|
adminer:
|
||||||
|
image: adminer
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
ADMINER_DEFAULT_SERVER: biblenotes
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
@ -16,103 +16,4 @@ CREATE TABLE user_logins
|
|||||||
login_time TIMESTAMP NOT NULL,
|
login_time TIMESTAMP NOT NULL,
|
||||||
login_ip VARCHAR(255) NOT NULL,
|
login_ip VARCHAR(255) NOT NULL,
|
||||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
FOREIGN KEY (user_id) REFERENCES users (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE bible_reading_plans
|
|
||||||
(
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
plan_name VARCHAR(255) NOT NULL,
|
|
||||||
start_date TIMESTAMP NOT NULL,
|
|
||||||
chapter_per_day SMALLINT NOT NULL CHECK (chapter_per_day > 0),
|
|
||||||
creator_user_id BIGINT NOT NULL,
|
|
||||||
FOREIGN KEY (creator_user_id) REFERENCES users (id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE bible_books
|
|
||||||
(
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
book_name_en VARCHAR(255) NOT NULL,
|
|
||||||
book_name_de VARCHAR(255) NOT NULL,
|
|
||||||
chapter_count INT NOT NULL CHECK (chapter_count > 0),
|
|
||||||
is_new_testament BOOLEAN NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE user_statistics
|
|
||||||
(
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
user_id BIGINT NOT NULL,
|
|
||||||
current_book_id BIGINT,
|
|
||||||
current_chapter_id BIGINT,
|
|
||||||
bible_reading_plan_id BIGINT,
|
|
||||||
FOREIGN KEY (bible_reading_plan_id) REFERENCES bible_reading_plans (id),
|
|
||||||
FOREIGN KEY (current_chapter_id) REFERENCES bible_books (id),
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users (id)
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO bible_books (book_name_en, book_name_de, chapter_count, is_new_testament)
|
|
||||||
VALUES ('Genesis', '1. Mose (Genesis)', 50, FALSE),
|
|
||||||
('Exodus', '2. Mose (Exodus)', 40, FALSE),
|
|
||||||
('Leviticus', '3. Mose (Levitikus)', 27, FALSE),
|
|
||||||
('Numbers', '4. Mose (Numeri)', 36, FALSE),
|
|
||||||
('Deuteronomy', '5. Mose (Deuteronomium)', 34, FALSE),
|
|
||||||
('Joshua', 'Josua', 24, FALSE),
|
|
||||||
('Judges', 'Richter', 21, FALSE),
|
|
||||||
('Ruth', 'Ruth', 4, FALSE),
|
|
||||||
('1. Samuel', '1. Samuel', 31, FALSE),
|
|
||||||
('2. Samuel', '2. Samuel', 24, FALSE),
|
|
||||||
('1. Kings', '1. Könige', 22, FALSE),
|
|
||||||
('2. Kings', '2. Könige', 25, FALSE),
|
|
||||||
('1. Chronicles', '1. Chronik', 29, FALSE),
|
|
||||||
('2. Chronicles', '2. Chronik', 36, FALSE),
|
|
||||||
('Ezra', 'Esra', 10, FALSE),
|
|
||||||
('Nehemiah', 'Nehemia', 13, FALSE),
|
|
||||||
('Esther', 'Ester', 10, FALSE),
|
|
||||||
('Job', 'Hiob', 42, FALSE),
|
|
||||||
('Psalms', 'Psalmen', 150, FALSE),
|
|
||||||
('Proverbs', 'Sprüche', 31, FALSE),
|
|
||||||
('Ecclesiastes', 'Prediger', 12, FALSE),
|
|
||||||
('Song of Solomon', 'Hohelied', 8, FALSE),
|
|
||||||
('Isaiah', 'Jesaja', 66, FALSE),
|
|
||||||
('Jeremiah', 'Jeremia', 52, FALSE),
|
|
||||||
('Lamentations', 'Klagelieder', 5, FALSE),
|
|
||||||
('Ezekiel', 'Hesekiel', 48, FALSE),
|
|
||||||
('Daniel', 'Daniel', 12, FALSE),
|
|
||||||
('Hosea', 'Hosea', 14, FALSE),
|
|
||||||
('Joel', 'Joel', 3, FALSE),
|
|
||||||
('Amos', 'Amos', 9, FALSE),
|
|
||||||
('Obadiah', 'Obadja', 1, FALSE),
|
|
||||||
('Jonah', 'Jona', 4, FALSE),
|
|
||||||
('Micah', 'Micha', 7, FALSE),
|
|
||||||
('Nahum', 'Nahum', 3, FALSE),
|
|
||||||
('Habakkuk', 'Habakuk', 3, FALSE),
|
|
||||||
('Zephaniah', 'Zefanja', 3, FALSE),
|
|
||||||
('Haggai', 'Haggai', 2, FALSE),
|
|
||||||
('Zechariah', 'Sacharja', 14, FALSE),
|
|
||||||
('Malachi', 'Maleachi', 4, FALSE),
|
|
||||||
('Matthew', 'Matthäus', 28, TRUE),
|
|
||||||
('Mark', 'Markus', 16, TRUE),
|
|
||||||
('Luke', 'Lukas', 24, TRUE),
|
|
||||||
('John', 'Johannes', 21, TRUE),
|
|
||||||
('Acts', 'Apostelgeschichte', 28, TRUE),
|
|
||||||
('Romans', 'Römer', 16, TRUE),
|
|
||||||
('1. Corinthians', '1. Korinther', 16, TRUE),
|
|
||||||
('2. Corinthians', '2. Korinther', 13, TRUE),
|
|
||||||
('Galatians', 'Galater', 6, TRUE),
|
|
||||||
('Ephesians', 'Epheser', 6, TRUE),
|
|
||||||
('Philippians', 'Philipper', 4, TRUE),
|
|
||||||
('Colossians', 'Kolosser', 4, TRUE),
|
|
||||||
('1. Thessalonians', '1. Thessalonicher', 5, TRUE),
|
|
||||||
('2. Thessalonians', '2. Thessalonicher', 3, TRUE),
|
|
||||||
('1. Timothy', '1. Timotheus', 6, TRUE),
|
|
||||||
('2. Timothy', '2. Timotheus', 4, TRUE),
|
|
||||||
('Titus', 'Titus', 3, TRUE),
|
|
||||||
('Philemon', 'Philemon', 1, TRUE),
|
|
||||||
('Hebrews', 'Hebräer', 13, TRUE),
|
|
||||||
('James', 'Jakobus', 5, TRUE),
|
|
||||||
('1. Peter', '1. Petrus', 5, TRUE),
|
|
||||||
('2. Peter', '2. Petrus', 3, TRUE),
|
|
||||||
('1. John', '1. Johannes', 5, TRUE),
|
|
||||||
('2. John', '2. Johannes', 1, TRUE),
|
|
||||||
('3. John', '3. Johannes', 1, TRUE),
|
|
||||||
('Jude', 'Judas', 1, TRUE),
|
|
||||||
('Revelation', 'Offenbarung', 22, TRUE);
|
|
@ -39,13 +39,13 @@ public class SecurityConfig {
|
|||||||
|
|
||||||
http
|
http
|
||||||
.csrf(csrf -> csrf
|
.csrf(csrf -> csrf
|
||||||
.ignoringRequestMatchers("/**")
|
.ignoringRequestMatchers("/api/v1/**")
|
||||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())) // Disable CSRF for API routes
|
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())) // Disable CSRF for API routes
|
||||||
.sessionManagement(sessionManagement -> sessionManagement
|
.sessionManagement(sessionManagement -> sessionManagement
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // No session will be created by Spring Security
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // No session will be created by Spring Security
|
||||||
)
|
)
|
||||||
.authorizeHttpRequests(authorize -> authorize
|
.authorizeHttpRequests(authorize -> authorize
|
||||||
.requestMatchers("/secure/**").authenticated() // Secure these endpoints
|
.requestMatchers("/api/v1/secure/**").authenticated() // Secure these endpoints
|
||||||
.anyRequest().permitAll() // All other requests are allowed without authentication
|
.anyRequest().permitAll() // All other requests are allowed without authentication
|
||||||
)
|
)
|
||||||
.headers(headers -> headers
|
.headers(headers -> headers
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package de.w665.biblenotes.config;
|
|
||||||
|
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
public class WebConfig implements WebMvcConfigurer {
|
|
||||||
@Override
|
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
|
||||||
// Map static resources to the root path
|
|
||||||
registry.addResourceHandler("/**")
|
|
||||||
.addResourceLocations("classpath:/static/");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package de.w665.biblenotes.db.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "bible_books")
|
|
||||||
@Getter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@ToString
|
|
||||||
public class BibleBook {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Column(name = "book_name_en", nullable = false)
|
|
||||||
private String bookNameEn;
|
|
||||||
|
|
||||||
@Column(name = "book_name_de", nullable = false)
|
|
||||||
private String bookNameDe;
|
|
||||||
|
|
||||||
@Column(name = "chapter_count", nullable = false)
|
|
||||||
private int chapterCount;
|
|
||||||
|
|
||||||
@Column(name = "is_new_testament", nullable = false)
|
|
||||||
private boolean isNewTestament;
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package de.w665.biblenotes.db.entity;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "bible_reading_plans")
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@AllArgsConstructor
|
|
||||||
@ToString
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class BibleReadingPlan {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Column(name = "plan_name", nullable = false)
|
|
||||||
private String planName;
|
|
||||||
|
|
||||||
@Column(name = "start_date", nullable = false)
|
|
||||||
private LocalDateTime startDate;
|
|
||||||
|
|
||||||
@Column(name = "chapter_per_day", nullable = false)
|
|
||||||
private short chapterPerDay;
|
|
||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "creator_user_id", nullable = false)
|
|
||||||
private User creatorUser;
|
|
||||||
}
|
|
@ -4,6 +4,7 @@ import jakarta.persistence.*;
|
|||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "user_logins")
|
@Table(name = "user_logins")
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
package de.w665.biblenotes.db.entity;
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import lombok.*;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "user_statistics")
|
|
||||||
@Getter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@ToString
|
|
||||||
public class UserStatistics {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "user_id", nullable = false)
|
|
||||||
private User user;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "current_book_id")
|
|
||||||
private BibleBook currentBook;
|
|
||||||
|
|
||||||
@Column(name = "current_chapter_id")
|
|
||||||
private Long currentChapterId;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "bible_reading_plan_id")
|
|
||||||
private BibleReadingPlan bibleReadingPlan;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package de.w665.biblenotes.db.repo;
|
|
||||||
|
|
||||||
import de.w665.biblenotes.db.entity.BibleBook;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
public interface BibleBookRepository extends JpaRepository<BibleBook, Long> {
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package de.w665.biblenotes.db.repo;
|
|
||||||
|
|
||||||
import de.w665.biblenotes.db.entity.BibleReadingPlan;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface BibleReadingPlanRepository extends JpaRepository<BibleReadingPlan, Long> {
|
|
||||||
List<BibleReadingPlan> getBibleReadingPlanById(Long id);
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package de.w665.biblenotes.db.repo;
|
|
||||||
|
|
||||||
import de.w665.biblenotes.db.entity.UserStatistics;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
public interface UserStatisticsRepository extends JpaRepository<UserStatistics, Long> {
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
package de.w665.biblenotes.rest;
|
package de.w665.biblenotes.rest;
|
||||||
|
|
||||||
import de.w665.biblenotes.rest.dto.AuthenticationRequest;
|
import de.w665.biblenotes.rest.ro.AuthenticationRequest;
|
||||||
import de.w665.biblenotes.service.AuthenticationService;
|
import de.w665.biblenotes.service.AuthenticationService;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -16,7 +16,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/auth")
|
@RequestMapping("/api/v1/auth")
|
||||||
public class AuthenticationController {
|
public class AuthenticationController {
|
||||||
private final AuthenticationService authenticationService;
|
private final AuthenticationService authenticationService;
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package de.w665.biblenotes.rest.dto;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
public class BibleReadingPlanDTO {
|
|
||||||
private Long id;
|
|
||||||
private String planName;
|
|
||||||
private LocalDateTime startDate;
|
|
||||||
private short chapterPerDay;
|
|
||||||
private String creatorUserName;
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
package de.w665.biblenotes.rest.mappings;
|
|
||||||
|
|
||||||
import de.w665.biblenotes.db.entity.BibleReadingPlan;
|
|
||||||
import de.w665.biblenotes.db.entity.User;
|
|
||||||
import de.w665.biblenotes.db.repo.BibleReadingPlanRepository;
|
|
||||||
import de.w665.biblenotes.db.repo.UserRepository;
|
|
||||||
import de.w665.biblenotes.rest.SecureApiRestController;
|
|
||||||
import de.w665.biblenotes.rest.dto.BibleReadingPlanDTO;
|
|
||||||
import de.w665.biblenotes.rest.security.UserAuthenticationContext;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/secure/bible-reading-plan")
|
|
||||||
public class BibleReadingPlanMapping {
|
|
||||||
|
|
||||||
private final EntityManager entityManager;
|
|
||||||
private final BibleReadingPlanRepository bibleReadingPlanRepository;
|
|
||||||
|
|
||||||
public BibleReadingPlanMapping(UserRepository userRepository, EntityManager entityManager, BibleReadingPlanRepository bibleReadingPlanRepository) {
|
|
||||||
this.entityManager = entityManager;
|
|
||||||
this.bibleReadingPlanRepository = bibleReadingPlanRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping
|
|
||||||
public ResponseEntity<Object> getBibleReadingPlans(@RequestParam(name = "id", required = true) Long id) {
|
|
||||||
Optional<BibleReadingPlan> brp = bibleReadingPlanRepository.findById(id);
|
|
||||||
if(brp.isEmpty()) {
|
|
||||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
BibleReadingPlanDTO bibleReadingPlanDTO = new BibleReadingPlanDTO();
|
|
||||||
bibleReadingPlanDTO.setId(brp.get().getId());
|
|
||||||
bibleReadingPlanDTO.setPlanName(brp.get().getPlanName());
|
|
||||||
bibleReadingPlanDTO.setChapterPerDay(brp.get().getChapterPerDay());
|
|
||||||
bibleReadingPlanDTO.setStartDate(brp.get().getStartDate());
|
|
||||||
bibleReadingPlanDTO.setCreatorUserName(brp.get().getCreatorUser().getUsername());
|
|
||||||
|
|
||||||
return new ResponseEntity<>(bibleReadingPlanDTO, HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping
|
|
||||||
public ResponseEntity<Object> createBibleReadingPlan(@RequestBody BibleReadingPlanDTO bibleReadingPlanDTO) {
|
|
||||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
|
|
||||||
// Construct entity
|
|
||||||
BibleReadingPlan plan = new BibleReadingPlan();
|
|
||||||
plan.setPlanName(bibleReadingPlanDTO.getPlanName());
|
|
||||||
plan.setChapterPerDay(bibleReadingPlanDTO.getChapterPerDay());
|
|
||||||
plan.setStartDate(bibleReadingPlanDTO.getStartDate());
|
|
||||||
|
|
||||||
// Set user as creator in db entity
|
|
||||||
User userProxy = entityManager.getReference(User.class, ((UserAuthenticationContext) auth.getPrincipal()).getUserId());
|
|
||||||
plan.setCreatorUser(userProxy);
|
|
||||||
BibleReadingPlan createdPlan = bibleReadingPlanRepository.save(plan);
|
|
||||||
|
|
||||||
// Construct response (we do this because otherwise the user object would be serialized (which would fail because it's a proxy + i addition we don't want to send the users credentials))
|
|
||||||
BibleReadingPlanDTO responseDTO = new BibleReadingPlanDTO();
|
|
||||||
responseDTO.setPlanName(createdPlan.getPlanName());
|
|
||||||
responseDTO.setChapterPerDay(createdPlan.getChapterPerDay());
|
|
||||||
responseDTO.setStartDate(createdPlan.getStartDate());
|
|
||||||
responseDTO.setCreatorUserName(((UserAuthenticationContext) auth.getPrincipal()).getUsername());
|
|
||||||
responseDTO.setId(createdPlan.getId());
|
|
||||||
|
|
||||||
return new ResponseEntity<>(responseDTO, HttpStatus.OK);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package de.w665.biblenotes.rest.dto;
|
package de.w665.biblenotes.rest.ro;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
@ -1,6 +1,5 @@
|
|||||||
package de.w665.biblenotes.rest.security;
|
package de.w665.biblenotes.rest.security;
|
||||||
|
|
||||||
import de.w665.biblenotes.db.entity.Role;
|
|
||||||
import de.w665.biblenotes.service.AuthenticationService;
|
import de.w665.biblenotes.service.AuthenticationService;
|
||||||
import jakarta.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
@ -61,15 +60,12 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the role and username from the JWT and set it to Spring AuthenticationContext for access control
|
String username = authenticationService.extractSubject(jwt);
|
||||||
String username = authenticationService.getClaimValue(jwt, "username", String.class);
|
// Extract the role from the JWT and set it to Spring AuthenticationContext for access control
|
||||||
String role = authenticationService.getClaimValue(jwt, "role", String.class);
|
String role = authenticationService.getClaimValue(jwt, "role", String.class);
|
||||||
int userId = authenticationService.getClaimValue(jwt, "userId", Integer.class);
|
|
||||||
UserAuthenticationContext uac = new UserAuthenticationContext(username, userId, Role.valueOf(role));
|
|
||||||
|
|
||||||
List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role));
|
List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role));
|
||||||
|
|
||||||
JwtAuthenticationToken auth = new JwtAuthenticationToken(uac, jwt, authorities);
|
JwtAuthenticationToken auth = new JwtAuthenticationToken(username, jwt, authorities);
|
||||||
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package de.w665.biblenotes.rest.security;
|
package de.w665.biblenotes.rest.security;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
@ -8,24 +7,24 @@ import java.util.Collection;
|
|||||||
|
|
||||||
public class JwtAuthenticationToken extends AbstractAuthenticationToken {
|
public class JwtAuthenticationToken extends AbstractAuthenticationToken {
|
||||||
|
|
||||||
private final UserAuthenticationContext principal;
|
private final String principal;
|
||||||
@Getter
|
|
||||||
private final String token;
|
private final String token;
|
||||||
|
|
||||||
public JwtAuthenticationToken(UserAuthenticationContext principal, String token, Collection<? extends GrantedAuthority> authorities) {
|
public JwtAuthenticationToken(String principal, String token, Collection<? extends GrantedAuthority> authorities) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
this.token = token;
|
this.token = token;
|
||||||
super.setAuthenticated(true);
|
super.setAuthenticated(true); // Set this to true only if authentication is verified
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getCredentials() {
|
public Object getCredentials() {
|
||||||
return "Credentials are not stored.";
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserAuthenticationContext getPrincipal() {
|
public Object getPrincipal() {
|
||||||
return this.principal;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package de.w665.biblenotes.rest.security;
|
|
||||||
|
|
||||||
import de.w665.biblenotes.db.entity.Role;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class UserAuthenticationContext {
|
|
||||||
private String username;
|
|
||||||
private int userId;
|
|
||||||
private Role role;
|
|
||||||
}
|
|
@ -73,11 +73,10 @@ public class AuthenticationService {
|
|||||||
Date expiryDate = new Date(nowMillis + expirationTime);
|
Date expiryDate = new Date(nowMillis + expirationTime);
|
||||||
|
|
||||||
return Jwts.builder()
|
return Jwts.builder()
|
||||||
.subject("BibleNotes Authentication Token")
|
.subject("SharePulse Authentication Token")
|
||||||
.issuedAt(now)
|
.issuedAt(now)
|
||||||
.claim("role", user.getRole())
|
.claim("role", user.getRole())
|
||||||
.claim("username", user.getUsername())
|
.claim("username", user.getUsername())
|
||||||
.claim("userId", user.getId())
|
|
||||||
.expiration(expiryDate)
|
.expiration(expiryDate)
|
||||||
.signWith(secretKey)
|
.signWith(secretKey)
|
||||||
.compact();
|
.compact();
|
||||||
|
@ -15,7 +15,4 @@ spring.jpa.database=postgresql
|
|||||||
logging.level.de.w665.biblenotes=DEBUG
|
logging.level.de.w665.biblenotes=DEBUG
|
||||||
|
|
||||||
# Static path
|
# Static path
|
||||||
spring.web.resources.static-locations=classpath:/static/
|
spring.web.resources.static-locations=classpath:/static/
|
||||||
|
|
||||||
# If this is removed, this prefix must be added to the security config
|
|
||||||
spring.mvc.servlet.path=/api/v1
|
|
Loading…
x
Reference in New Issue
Block a user