Instantly share code, notes, and snippets.
Created
September 4, 2024 09:50
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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