I have been asking to create a simple implementation using Okta Authentication to indentify the user and Spring Security Roles to implement method control authorization.
The okta part is pretty straight forward, I have a simple GET request which gets the users email address after they have logged in via Okta. From here, I need to use this to identify their role in the application .yml file to see what they are authorized to do.
Below is the code I have written, is it possible to return the User object to the front end and then using this when calling the rest of the controllers which would have @preAuthorize(hasRole(ADMIN))?
I know using groups within Okta would be the easiest approach, but this is not possible for my scenario.
@RestController
public class OktaRestController {
private final UserRoleService userRoleService;
public OktaRestController(UserRoleService userRoleService) {
this.userRoleService = userRoleService;
}
@GetMapping("/verifyUser")
public User helloUser(@AuthenticationPrincipal OidcUser user) {
String userEmail = (String) user.getAttributes().get("email");
LOGGER.info("Email address for user is: " + userEmail);
return userRoleService.createUser(userEmail);
}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/home")
public String home() {
return "You can edit";
}
Security Configuration:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
Find the role based on the email address gotten from Okta and create a spring security UserDetails user:
@Service
public class UserRoleService {
private final Map<String, String[]> rolesMap = new ConcurrentHashMap<>();
@Autowired
private UserRoleService(Roles roles) {
if (roles.areRolesPresent()) {
for (Roles.Role userRole : roles.getRoles()) {
rolesMap.put(userRole.getName(), userRole.getUsers());
}
}
}
public User createUser(String email){
String role = findUserRoleByEmail(email);
return new User(email, "", setUserRole(role));
}
private String findUserRoleByEmail(String email){
for (Map.Entry<String, String[]> entry : rolesMap.entrySet()) {
if(Arrays.asList(entry.getValue()).contains(email)){
return entry.getKey();
}
}
return null;
}
private static Collection<? extends GrantedAuthority> setUserRole(String userRole) {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_" + userRole.toUpperCase()));
return authorities;
}
}
Application.yml where roles and users emails will be stored:
authorisation:
roles:
- name: admin
users:
- [email protected]
- name: member
users:
- [email protected]
question from:
https://stackoverflow.com/questions/65904172/using-okta-authentication-and-spring-preauthorizehasrole-for-method-level-c 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…