1. OAuth2 인증 서버 설정 (SecurityConfig)
SecurityConfig
클래스는 OAuth2 인증 서버와 클라이언트를 설정하는 코드입니다.
코드 설명
@Configuration
public class SecurityConfig {
// 1. 인증 서버 필터 체인 설정
@Bean
@Order(1)
public SecurityFilterChain asFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults());
http.exceptionHandling((e) ->
e.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")));
return http.build();
}
// 2. 기본 시큐리티 필터 체인 설정
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.formLogin(Customizer.withDefaults());
http.authorizeHttpRequests(c -> c.anyRequest().authenticated());
return http.build();
}
// 3. 사용자 정보 설정 (InMemoryUserDetailsManager)
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails = User.withUsername("bill")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails);
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
// 4. OAuth2 클라이언트 설정
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("client")
.clientSecret("secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("https://www.manning.com/authorized")
.scope(OidcScopes.OPENID)
.build();
return new InMemoryRegisteredClientRepository(registeredClient);
}
// 5. JWT 키 설정
@Bean
public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAKey rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
return new ImmutableJWKSet<>(new JWKSet(rsaKey));
}
// 6. 인증 서버 세팅
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().build();
}
// 7. JWT 토큰 커스터마이징
@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
return context -> {
JwtClaimsSet.Builder claims = context.getClaims();
claims.claim("priority", "HIGH");
};
}
}
2. Code Verifier 생성 (PKCE)
SecureRandom을 사용하여 Code Verifier를 생성합니다.
코드
package main;
import java.security.SecureRandom;
import java.util.Base64;
public class GenerateVerifier {
public static void main(String[] args) {
System.out.println(generateVerifier());
}
public static String generateVerifier() {
SecureRandom secureRandom = new SecureRandom();
byte[] code = new byte[32];
secureRandom.nextBytes(code);
return Base64.getUrlEncoder().withoutPadding().encodeToString(code);
}
}
결과 예시:
3. Code Challenge 생성
SHA-256을 사용하여 Code Verifier를 기반으로 Code Challenge를 생성합니다.
코드
package main;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class GenerateChallenge {
public static void main(String[] args) {
String verifier = "Oz85Ph-hZO88HAfqoSm0mix0on7pjQGMLoDVmqMBVhE";
System.out.println(generateChallenge(verifier));
}
public static String generateChallenge(String verifier) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
byte[] digested = messageDigest.digest(verifier.getBytes());
return Base64.getUrlEncoder().withoutPadding().encodeToString(digested);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
결과 예시:
4. 인증 요청
브라우저에서 다음 URL에 접속하여 로그인 페이지를 띄웁니다.
- ID : bill
- Password : password
http://localhost:8080/oauth2/authorize?response_type=code&client_id=client&scope=openid&redirect_uri=https://www.manning.com/authorized&code_challenge=위에서 생성한 Challenge Code&code_challenge_method=S256
결과 예시:
결과 예시:
5. POST 요청으로 토큰 발급
Postman에서 다음과 같이 설정합니다.
- URL:
http://localhost:8080/oauth2/token
- Method: POST
- Authorization:
- Auth Type: Basic Auth
- Username: client
- Password: secret
- Headers:
- Authorization:
Basic Y2xpZW50OnNlY3JldA==
(Base64로 인코딩된client:secret
) - Content-Type:
application/x-www-form-urlencoded
- Authorization:
- Body:
- grant_type:
authorization_code
- code:
URL에서 발급받은 인증 코드
- redirect_uri:
https://www.manning.com/authorized
- client_id:
client
- code_verifier:
위에서 생성한 Code Verifier
- grant_type:
6. 응답 예시
요약
- Code Verifier 생성
- Code Challenge 생성
- 브라우저 URL로 로그인
- Postman에서 토큰 요청 및 응답 확인
'OAuth' 카테고리의 다른 글
인가 코드 그랜트 타입과 클라이언트 크레덴셜 그랜트 타입 (0) | 2024.12.18 |
---|---|
Client Credentials Grant Type (0) | 2024.12.18 |
Spring Authorization Server 구성 (0) | 2024.12.17 |
Authorization Code (0) | 2024.12.17 |
Proof Key(PKCE) (0) | 2024.12.17 |