전제 조건
- 권한 부여 서버와 리소스 서버로 깃허브를 사용한다
- 클라이언트는 내가 작성한 스프링 백엔드 코드다
- 사용자는 깃허브를 사용하면서 내가 작성한 스프링 백엔드 코드에 접근한 사람이다
1. 권한 부여 서버에게 클라이언트를 알리기
- 깃허브에서 클라이언트의 이름, 홈페이지, 깃허브가 클라이언트를 다시 호출할 링크를 지정하기
- 양식 입력 후 클라이언트 ID와 클라이언트 비밀을 얻을 수 있다
2. 클라이언트에 인증 방식으로 OAuth2를 사용할 것이라고 선언하기
- build.gradle 혹은 pom.xml에 OAuth2 의존성을 주입해야 한다
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
}
- config 파일에 OAuth2를 사용할 것이라고 선언한다
@Override
protected void configure(HttpSecurity http) throws Exception{
http.oauth2Login(); // OAuth2LoginAuthenticationFilter를 필터 체인에 추가한다. 이 필터는 요청을 가로채고 OAuth2 인증 논리를 적용한다
http.authorizeRequests()
.anyRequest()
.authenticated();
}
3. 클라이언트와 관련된 세부 사항을 등록하기
ClientRegistration
- 클라이언트가 사용할 권한 부여 서버를 등록하기 위해 사용하는 인터페이스
- 스프링 시큐리티가 제공
- 권한 부여 서버를 등록한다는 말이 있어서 권한 부여 서버를 나타내는 것인가? 착각할 수 있지만 이름에도 나와있듯이 클라이언트를 나타내는 것이다. 즉, 클라이언트를 등록할 수 있게 해 주는 인터페이스인데 그 등록 내용에 클라이언트가 사용할 권한 부여 서버를 등록하는 내용도 있으니 권한 부여 서버를 등록하기 위해 사용할 수 있는 것이다.
- 클라이언트의 다양한 세부 정보를 포함하고 있다
방법 1 ClientRegistration 생성 후 내용 등록
- 권한 부여 서버의 설명서를 찾아서 필요한 내용들을 등록해야 한다
private ClientRegistration clientRegistration() {
ClientRegistration cr = ClientRegistration.withRegistrationId("github")
.clientId("a7553955a0c534ec5e6b")
.clientSecret("1795b30b425ebb79e424afa51913f1c724da0dbb")
.scope(new String[]{"read:user"})
.authorizationUri("https://github.com/login/oauth/authorize")
.tokenUri("https://github.com/login/oauth/access_token")
.userInfoUri("https://api.github.com/user")
.userNameAttributeName("id")
.clientName("GitHub")
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}")
.build();
return cr;
}
방법 2 CommonOAuth2Provider 사용
- 구글, 깃허브, 페이스북, 옥타 등의 사이트를 권한 부여 서버로 사용할 때 사용 가능
- 방법1보다 간단하게 등록 가능
private ClientRegistration clientRegistration() {
return CommonOAuth2Provider.GITHUB.getBuilder("github")
.clientId("")
.clientSecret("")
.build();
}
4. 3에서 등록한 클라이언트를 사용하는 방법 설정
ClientRegistrationRepository
- ClientRegistration을 인증에 이용하도록 설정하기 위해 사용
- OAuth2LoginAuthenticationFilter는 ClientRegistrationRepository에서 ClientRegistration 세부 정보를 얻을 수 있다.
- ClientRegistration 의 등록 ID로 ClientRegistration을 찾는다
방법 1 InMemoryClientRegistrationRepository 사용
- ClientRegistration의 인스턴스를 메모리에 저장
@Bean
public ClientRegistrationRepository clientRepository() {
var c = clientRegistration();
return new InMemoryClientRegistrationRepository(c);
}
방법 2 HttpSecurity 객체의 oauth2Login()의 매개 변수로 Customizer 객체 이용
@Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2Login(c -> {
c.clientRegistrationRepository(clientRepository());
});
http.authorizeRequests()
.anyRequest().authenticated();
}
5. 인증된 사용자의 세부 정보 얻기
- 스프링 시큐리티에서 인증된 사용자의 세부 정보는 Authentication 객체 형태로 SecurityContext에 저장된다.
- Authentication 객체의 구현은 OAuth2AuthenticationToken이기 때문에 컨트롤러 메서드 매개변수로 이를 넣어주면 여기서 인증된 사용자의 세부 정보를 얻을 수 있다.
@GetMapping("/")
public String main(OAuth2AuthenticationToken token){
logger.info(String.valueOf(token.getPrincipal()));
return "main.html";
}
6. 결과
- 사용자가 클라이언트의 http://localhost:8080으로 접속하면 깃허브 인증 페이지로 리디렉션 된다.
- 사용자가 깃허브에서 올바르게 로그인을 하면 클라이언트는 깃허브로부터 액세스 토큰을 얻을 수 있는 코드를 얻게 되고, 이 코드를 이용해 깃허브로부터 액세스 토큰을 얻는다.
- 클라이언트는 로그인 된 사용자의 세부 정보를 얻을 수 있다.
+ ClientRegistration과 ClientRegistrationRepository를 작성하지 않는 방법
1) 일반적인 공급자일 경우(구글, 깃허브 등)
application.properties 파일에 client-id와 client-secret를 등록하면 스프링 부트가 속성 파일을 바탕으로 자동으로 ClientRegistration과 ClientRegistrationRepository를 생성해주기 때문에 따로 코드를 작성하지 않아도 된다.
spring.security.oauth2.client.registration.github.client-id=a7553955a0c534ec5e6b
spring.security.oauth2.client.registration.github.client-secret=1795b30b425ebb79e424afa51913f1c724da0dbb
2) 일반적인 공급자가 아닐 경우
spring.security.oauth2.client.provider로 시작하는 속성 그룹으로 권한 부여 서버에 관한 세부 정보를 application.properties파일에 적어야 한다.
spring.security.oauth2.client.provider.myprovider.authorization-uri=
GitHub - wikibook/spring-security: 《스프링 시큐리티 인 액션》 예제 코드
《스프링 시큐리티 인 액션》 예제 코드. Contribute to wikibook/spring-security development by creating an account on GitHub.
github.com
'Spring > security' 카테고리의 다른 글
[시큐리티] OAuth 2 (0) | 2023.03.30 |
---|---|
[시큐리티] 토큰 (0) | 2023.03.29 |
[시큐리티] CORS (0) | 2023.03.28 |
[시큐리티] CSRF (0) | 2023.03.27 |
[시큐리티] 필터 (0) | 2023.03.23 |