Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth event #11

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2296ff4
implementation of Spring security Config
skrzeminski Jan 7, 2021
3f9676a
adding UserDetailsService
skrzeminski Jan 7, 2021
9d2f3e0
comment out property of defoult user of spring security
skrzeminski Jan 7, 2021
b5fcb49
added new user with customer role
skrzeminski Jan 7, 2021
be1257d
added new user with customer role
skrzeminski Jan 7, 2021
3b22bc2
PasswordEncodingTests
skrzeminski Jan 7, 2021
ebc8ed1
adding Auth filter
skrzeminski Jan 8, 2021
157321e
adding Auth filter
skrzeminski Jan 8, 2021
44a5130
implementing user details service
skrzeminski Jan 8, 2021
17190ee
implementing roles authorities
skrzeminski Jan 9, 2021
e7e6467
implementing roles authorities
skrzeminski Jan 9, 2021
28c0880
added BeerOrderController
skrzeminski Jan 11, 2021
bee778b
updated loader for new authority
skrzeminski Jan 11, 2021
037370b
updated user to implement userDetail Service
skrzeminski Jan 11, 2021
ba9bfd2
added mapping between customer and user
skrzeminski Jan 11, 2021
00145e3
added mapping between customer and user
skrzeminski Jan 11, 2021
e9b41bc
updated loader
skrzeminski Jan 11, 2021
fbadef7
deleted UserLoader
skrzeminski Jan 11, 2021
8a0fee6
added tests
skrzeminski Jan 11, 2021
aee1e4e
spring security with Spring data jpa
skrzeminski Jan 12, 2021
ab2dbb6
added crsf
skrzeminski Jan 13, 2021
b414d96
updated template
skrzeminski Jan 13, 2021
1840d47
updated template about logout
skrzeminski Jan 13, 2021
5022815
added configuration for login and logout
skrzeminski Jan 13, 2021
f0b0520
added eeror message handling
skrzeminski Jan 13, 2021
646963c
added authority check
skrzeminski Jan 13, 2021
be77efe
remember me configuration
skrzeminski Jan 13, 2021
8031d49
remember me configuration
skrzeminski Jan 13, 2021
b15c53d
added success and failure authentication events
skrzeminski Jan 14, 2021
ab4c4e3
added shecguling to unlock accounts
skrzeminski Jan 14, 2021
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
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,19 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-data</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
147 changes: 147 additions & 0 deletions src/main/java/guru/sfg/brewery/bootstrap/DefaultBreweryLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,42 @@
package guru.sfg.brewery.bootstrap;

import guru.sfg.brewery.domain.*;
import guru.sfg.brewery.domain.security.Authority;
import guru.sfg.brewery.domain.security.Role;
import guru.sfg.brewery.domain.security.User;
import guru.sfg.brewery.repositories.*;
import guru.sfg.brewery.repositories.security.AuthorityRepository;
import guru.sfg.brewery.repositories.security.RoleRepository;
import guru.sfg.brewery.repositories.security.UserRepository;
import guru.sfg.brewery.web.model.BeerStyleEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;


/**
* Created by jt on 2019-01-26.
*/
@Slf4j
@RequiredArgsConstructor
@Component
public class DefaultBreweryLoader implements CommandLineRunner {

public static final String TASTING_ROOM = "Tasting Room";
public static final String ST_PETE_DISTRIBUTING = "St Pete Distributing";
public static final String DUNEDIN_DISTRIBUTING = "Dunedin Distributing";
public static final String KEY_WEST_DISTRIBUTORS = "Key West Distributors";
public static final String STPETE_USER = "stpete";
public static final String DUNEDIN_USER = "dunedin";
public static final String KEYWEST_USER = "keywest";

public static final String BEER_1_UPC = "0631234200036";
public static final String BEER_2_UPC = "0631234300019";
public static final String BEER_3_UPC = "0083783375213";
Expand All @@ -44,14 +62,75 @@ public class DefaultBreweryLoader implements CommandLineRunner {
private final BeerInventoryRepository beerInventoryRepository;
private final BeerOrderRepository beerOrderRepository;
private final CustomerRepository customerRepository;
private final AuthorityRepository authorityRepository;
private final RoleRepository roleRepository;
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;

@Override
public void run(String... args) {
loadSecurityData();
loadBreweryData();
loadTastingRoomData();
loadCustomerData();
}

private void loadCustomerData() {
Role customerRole = roleRepository.findByName("CUSTOMER").orElseThrow();

//create customers
Customer stPeteCustomer = customerRepository.save(Customer.builder()
.customerName(ST_PETE_DISTRIBUTING)
.apiKey(UUID.randomUUID())
.build());

Customer dunedinCustomer = customerRepository.save(Customer.builder()
.customerName(DUNEDIN_DISTRIBUTING)
.apiKey(UUID.randomUUID())
.build());

Customer keyWestCustomer = customerRepository.save(Customer.builder()
.customerName(KEY_WEST_DISTRIBUTORS)
.apiKey(UUID.randomUUID())
.build());

//create users
User stPeteUser = userRepository.save(User.builder().username(STPETE_USER)
.password(passwordEncoder.encode("password"))
.customer(stPeteCustomer)
.role(customerRole).build());

User dunedinUser = userRepository.save(User.builder().username(DUNEDIN_USER)
.password(passwordEncoder.encode("password"))
.customer(dunedinCustomer)
.role(customerRole).build());

User keywest = userRepository.save(User.builder().username(KEYWEST_USER)
.password(passwordEncoder.encode("password"))
.customer(keyWestCustomer)
.role(customerRole).build());

//create orders
createOrder(stPeteCustomer);
createOrder(dunedinCustomer);
createOrder(keyWestCustomer);

log.debug("Orders Loaded: " + beerOrderRepository.count());
}

private BeerOrder createOrder(Customer customer) {
return beerOrderRepository.save(BeerOrder.builder()
.customer(customer)
.orderStatus(OrderStatusEnum.NEW)
.beerOrderLines(Set.of(BeerOrderLine.builder()
.beer(beerRepository.findByUpc(BEER_1_UPC))
.orderQuantity(2)
.build()))
.build());
}


private void loadTastingRoomData() {
Customer tastingRoom = Customer.builder()
.customerName(TASTING_ROOM)
.apiKey(UUID.randomUUID())
Expand Down Expand Up @@ -122,4 +201,72 @@ private void loadBreweryData() {

}
}

private void loadSecurityData() {
//beer auths
Authority createBeer = authorityRepository.save(Authority.builder().permission("beer.create").build());
Authority readBeer = authorityRepository.save(Authority.builder().permission("beer.read").build());
Authority updateBeer = authorityRepository.save(Authority.builder().permission("beer.update").build());
Authority deleteBeer = authorityRepository.save(Authority.builder().permission("beer.delete").build());

//customer auths
Authority createCustomer = authorityRepository.save(Authority.builder().permission("customer.create").build());
Authority readCustomer = authorityRepository.save(Authority.builder().permission("customer.read").build());
Authority updateCustomer = authorityRepository.save(Authority.builder().permission("customer.update").build());
Authority deleteCustomer = authorityRepository.save(Authority.builder().permission("customer.delete").build());

//customer brewery
Authority createBrewery = authorityRepository.save(Authority.builder().permission("brewery.create").build());
Authority readBrewery = authorityRepository.save(Authority.builder().permission("brewery.read").build());
Authority updateBrewery = authorityRepository.save(Authority.builder().permission("brewery.update").build());
Authority deleteBrewery = authorityRepository.save(Authority.builder().permission("brewery.delete").build());

//beer order
Authority createOrder = authorityRepository.save(Authority.builder().permission("order.create").build());
Authority readOrder = authorityRepository.save(Authority.builder().permission("order.read").build());
Authority updateOrder = authorityRepository.save(Authority.builder().permission("order.update").build());
Authority deleteOrder = authorityRepository.save(Authority.builder().permission("order.delete").build());
Authority pickupOrder = authorityRepository.save(Authority.builder().permission("order.pickup").build());
Authority createOrderCustomer = authorityRepository.save(Authority.builder().permission("customer.order.create").build());
Authority readOrderCustomer = authorityRepository.save(Authority.builder().permission("customer.order.read").build());
Authority updateOrderCustomer = authorityRepository.save(Authority.builder().permission("customer.order.update").build());
Authority deleteOrderCustomer = authorityRepository.save(Authority.builder().permission("customer.order.delete").build());
Authority pickupOrderCustomer = authorityRepository.save(Authority.builder().permission("customer.order.pickup").build());

Role adminRole = roleRepository.save(Role.builder().name("ADMIN").build());
Role customerRole = roleRepository.save(Role.builder().name("CUSTOMER").build());
Role userRole = roleRepository.save(Role.builder().name("USER").build());

adminRole.setAuthorities(new HashSet<>(Set.of(createBeer, updateBeer, readBeer, deleteBeer, createCustomer, readCustomer,
updateCustomer, deleteCustomer, createBrewery, readBrewery, updateBrewery, deleteBrewery,
createOrder, readOrder, updateOrder, deleteOrder, pickupOrder)));

customerRole.setAuthorities(new HashSet<>(Set.of(readBeer, readCustomer, readBrewery, createOrderCustomer, readOrderCustomer,
updateOrderCustomer, deleteOrderCustomer, pickupOrderCustomer)));

userRole.setAuthorities(new HashSet<>(Set.of(readBeer)));

roleRepository.saveAll(Arrays.asList(adminRole, customerRole, userRole));

userRepository.save(User.builder()
.username("spring")
.password(passwordEncoder.encode("guru"))
.role(adminRole)
.build());

userRepository.save(User.builder()
.username("user")
.password(passwordEncoder.encode("password"))
.role(userRole)
.build());

userRepository.save(User.builder()
.username("scott")
.password(passwordEncoder.encode("tiger"))
.role(customerRole)
.build());

log.debug("Users Loaded: " + userRepository.count());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package guru.sfg.brewery.config;

import guru.sfg.brewery.domain.security.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Slf4j
@Component
public class BeerOrderAuthenticationManger {

public boolean customerIdMatches(Authentication authentication, UUID customerId) {
User authenticatedUser = (User) authentication.getPrincipal();
log.debug("Auth User Customer ID" + authenticatedUser.getCustomer().getId() + " Customer Id: " + customerId);
return authenticatedUser.getCustomer().getId().equals(customerId);
}
}
120 changes: 120 additions & 0 deletions src/main/java/guru/sfg/brewery/config/RestHeaderAuthFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package guru.sfg.brewery.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* Created by jt on 6/19/20.
*/
@Slf4j
public class RestHeaderAuthFilter extends AbstractAuthenticationProcessingFilter {

public RestHeaderAuthFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
super(requiresAuthenticationRequestMatcher);
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;


if (logger.isDebugEnabled()) {
logger.debug("Request is to process authentication");
}

Authentication authResult = null;
try {
authResult = attemptAuthentication(request, response);
if (authResult != null) {
successfulAuthentication(request, response, chain, authResult);
} else {
chain.doFilter(request, response);
}
} catch (AuthenticationException exception) {
log.error("Authentication failed" + exception);
unsuccessfulAuthentication(request, response, exception);
}


}

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String userName = getUsername(request);
String password = getPassword(request);

if (userName == null) {
userName = "";
}

if (password == null) {
password = "";
}

log.debug("Authenticating User: " + userName);

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userName, password);

if (!StringUtils.isEmpty(userName)) {
return this.getAuthenticationManager().authenticate(token);
} else {
return null;
}
}

@Override
protected void unsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed)
throws IOException, ServletException {

SecurityContextHolder.clearContext();

if (log.isDebugEnabled()) {
log.debug("Authentication request failed: " + failed.toString(), failed);
log.debug("Updated SecurityContextHolder to contain null Authentication");
}

response.sendError(HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase());
}

@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {

if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
+ authResult);
}

SecurityContextHolder.getContext().setAuthentication(authResult);

}

private String getPassword(HttpServletRequest request) {
return request.getHeader("Api-Secret");
}

private String getUsername(HttpServletRequest request) {
return request.getHeader("Api-Key");
}
}
31 changes: 31 additions & 0 deletions src/main/java/guru/sfg/brewery/config/SecurityBeans.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package guru.sfg.brewery.config;

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
* Created by jt on 7/17/20.
*/
@Configuration
public class SecurityBeans {

@Bean
public PersistentTokenRepository persistentTokenRepository(DataSource dataSource) {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
return tokenRepository;
}

@Bean
public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}

}
Loading