Skip to content

Instantly share code, notes, and snippets.

@joshlong
Created September 4, 2024 09:50
Show Gist options
  • Save joshlong/46b7bac5edebe0adf6fac109140781d0 to your computer and use it in GitHub Desktop.
Save joshlong/46b7bac5edebe0adf6fac109140781d0 to your computer and use it in GitHub Desktop.
demonstrates how to change the authorities of the incoming token to reflect reconciled user state
package com.example.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.sql.DataSource;
import java.security.Principal;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@SpringBootApplication
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
// private static class MyGrantedAuthoritiesMapper implements GrantedAuthoritiesMapper {
//
// private final JdbcUserDetailsManager userDetailsManager;
//
// MyGrantedAuthoritiesMapper(JdbcUserDetailsManager userDetailsManager) {
// this.userDetailsManager = userDetailsManager;
// }
//
// @Override
// public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
// var username = SecurityContextHolder.getContext().getAuthentication().getName();
// var userDetails = this.userDetailsManager.loadUserByUsername(username);
// return userDetails.getAuthorities();
// }
// }
@Bean
JdbcUserDetailsManager jdbcUserDetailsManager(DataSource dataSource) {
return new JdbcUserDetailsManager(dataSource);
}
@Bean
GrantedAuthoritiesMapper userAuthoritiesMapper(JdbcUserDetailsManager userDetailsManager) {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(authority -> {
if (authority instanceof OidcUserAuthority oidcUserAuthority) {
var idToken = oidcUserAuthority.getIdToken();
var userInfo = oidcUserAuthority.getUserInfo();
System.out.println(idToken);
System.out.println(userInfo);
// make sure u change this for google
var username = userInfo.getSubject();
var userDetails = userDetailsManager.loadUserByUsername(username);
mappedAuthorities.addAll(userDetails.getAuthorities());
// Map the claims found in idToken and/or userInfo
// to one or more GrantedAuthority's and add it to mappedAuthorities
} else if (authority instanceof OAuth2UserAuthority oauth2UserAuthority) {
var userAttributes = oauth2UserAuthority.getAttributes();
userAttributes.forEach((k, v) -> System.out.println(k + ":" + v));
// Map the attributes found in userAttributes
// to one or more GrantedAuthority's and add it to mappedAuthorities
}
});
return mappedAuthorities;
};
}
}
@Component
class AuthenticationListener implements ApplicationListener<AuthenticationSuccessEvent> {
private final JdbcClient jdbcClient;
AuthenticationListener(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent event) {
System.out.println("somebody logged in to ur system with the following authentication [" +
event.getAuthentication().getName() + ":" + event
.getAuthentication()
.getAuthorities() + "]");
var username = event.getAuthentication().getName();
var password = UUID.randomUUID().toString();
var enabled = true;
this.jdbcClient.sql("""
insert into users (username, password, enabled) values (?,?,?)
on conflict do nothing ;
""")
.params(username, password, enabled)
.update();
this.jdbcClient.sql("""
insert into authorities (username, authority) values (?,?)
on conflict do nothing ;
""")
.params(username, "USER")
.update();
}
}
@Controller
@ResponseBody
class SecuredController {
@GetMapping("/admin")
Map<String, String> admin(Principal principal) {
return Map.of("message", "hello, admin " + principal.getName());
}
@GetMapping("/")
Map<String, String> hello(Principal principal) {
var user = SecurityContextHolder
.getContextHolderStrategy()
.getContext()
.getAuthentication();
System.out.println("authentication [" + user.getName() + ":" + user.getAuthorities() + "]");
return Map.of("message", "hello, " + principal.getName());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment