Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- @Profile
- application.properties
- Spring Security
- 다익스트라
- webjar
- JPA
- 스프링 부트
- cors
- HATEOAS
- Application Argument
- WebApplication Type
- rest api
- 브루트포스
- @ConfigurationProperties
- 백트래킹
- 리소스핸들러
- AuthenticationPrincipal
- 백준
- 외부설정
- 리소스 서버
- 백기선
- 정적 리소스
- Application Event
- OAuth2
- EnableAutoConfiguration
- 알고리즘
- Application Runner
- HttpMessageConverters
- 스프링부트
- JsonSerializer
Archives
- Today
- Total
아카이브
[스프링 기반 REST API 개발] 시큐리티 OAuth2 인증 서버 설정하기 본문
OAuth2(Open Authorization, Open Authentication 2) : 인증을 위한 표준 프로토콜
- 1~5 단계는 Authorization Code 발급 요청 URL을 통해 진행할 수 있습니다.
- 7~8 단계는 서비스에서 callback URL을 통해 전달받은 Authorization Code를 사용하여 Access Token 요청 API를 통해 진행할 수 있습니다.
- 8 단계에서 발급받은 Access Token은 서비스에서 자체적으로 저장, 관리해야 합니다.
- 10~11 사용자의 서비스 요청 시 회원정보가 필요하다면 Access Token을 사용해 API를 호출할 수 있습니다.
OAuth2 서버를 통해 인증 토큰을 받는다.
토큰 발행 테스트
- User
- Client
- POST /oauth/token
- HTTP Basic 인증 헤더 (클라이언트 아이디 + 클라이언트 시크릿)
- 요청 매개변수 (MultiValueMap<String, String>)
- grant_type: password
- username
- password
- 응답에 access_token 나오는지 확인
Grant Type: Password
- (A) 사용자가 클라이언트에 username과 password를 전달한다.
- (B) 사용자의 username과 password를 OAuth 서버에 제공한다.
- (C) OAuth 서버에서 확인해 유효하면 access token을 발급해준다.(선택적으로 refresh token)
- Granty Type: 토큰 받아오는 방법
- 서비스 오너가 만든 클라이언트에서 사용하는 Grant Type
- 요청과 응답이 한쌍으로 토큰을 바로 발급받을 수 있다.(장점)
- username과 password를 직접 요구하므로 third-party에게 허용해서는 안되고, 본인 서비스에서만 허용해야 한다.
요청
POST /oauth/token HTTP/1.1
Host: authorization-server.com
Content-type: application/x-www-form-urlencoded
grant_type=password
&username=exampleuser
&password=1234luggage
&client_id=xxxxxxxxxx
- grant_type=password : password 유형을 사용하는 서버에 알려줍니다.
- username : 응용 프로그램에 입력 한 사용자 이름
- password : 응용 프로그램에 입력 한 사용자의 암호
- client_id : 개발자가 등록 과정에서 얻은 응용 프로그램의 공용 식별자
- client_secret : client_id와 연결된 secret(비밀번호)
client_id와 client_secret은 HTTP Basic Authentication 인증 헤더로 넣는다.
응답
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create delete"
}
AuthorizationServer 설정
- @EnableAuthorizationServer
- extends AuthorizationServerConfigurerAdapter
- configure(AuthorizationServerSecurityConfigurer security)
- PassswordEncoder 설정
- configure(ClientDetailsServiceConfigurer clients)
- 클라이언트 설정
- grantTypes
- password
- refresh_token: OAuth Token을 발급받을 때 refresh_token도 같이 발급해주는데 이 토큰으로 새로운 액세스 토큰을 발급받음
- scopes
- secret / name
- accessTokenValiditySeconds
- refreshTokenValiditySeconds
- AuthorizationServerEndpointsConfigurer
- tokenStore
- authenticationManager
- userDetailsService
HTTP Basic을 사용하기 위해 의존성 추가
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-test -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
HTTP Basic이란? HTTP 표준에 정의된 가장 단순한 인증 기법이다.
Client는 ID:PASSWOD 문자열을 Base64 Encoding 한 문자열을 Authentication Header에 추가한 뒤 요청하고 200 OK 응답을 받는다.
파라미터가 쉽게 노출될 수 있지만, SSL이나 TLS로 노출을 막을 수 있다.
AuthServerConfig @Configuration class 작성하기
@Configuration
@EnableAuthorizationServer /* OAuth2 인증 서버 */
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
AuthenticationManager authenticationManager;
@Autowired
AccountService accountService;
@Autowired
TokenStore tokenStore;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.passwordEncoder(passwordEncoder);
// client secret도 password encode 관리
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory() // 원래는 jdbc db로 생성해야 한다
.withClient("myApp") // client_id 생성
.authorizedGrantTypes("password", "refresh_token") // 지원하는 type
.scopes("read", "write") // scope 설정
.secret(this.passwordEncoder.encode("pass")) // client_secret encoding
.accessTokenValiditySeconds(10 * 60) // 유효시간
.refreshTokenValiditySeconds(6 * 10 * 60) // 유효시간
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager) // 우리의 auth_manager로 설정하고
.userDetailsService(accountService) // 우리의 userDetailService인 accountService를 설정하고
.tokenStore(tokenStore) // 우리의 tokenStore를 설정
;
}
}
getToken() Test 코드 작성하기
@Test
@TestDescription("인증 토큰을 발급 받는 테스트")
void getAuthToken() throws Exception {
// Given
String username = "jumen@naver.com";
String password = "5215";
Account build = Account.builder()
.email(username)
.password(password)
.roles(Set.of(AccountRole.ADMIN, AccountRole.USER))
.build();
this.accountService.saveAccount(build);
String clientId = "myApp";
String clientSecret = "pass";
this.mockMvc.perform(post("/oauth/token")
.with(httpBasic(clientId, clientSecret)) // BasicAuth 방식으로 auth_header에 넣어준다
.param("username", username)
.param("password", password)
.param("grant_type", "password")
)
.andExpect(status().isOk())
.andDo(print())
.andExpect(jsonPath("access_token").exists())
;
}
'Spring > 스프링 기반 REST API 개발' 카테고리의 다른 글
[스프링 기반 REST API 개발] 시큐리티 현재 사용자 조회하기 (0) | 2021.01.09 |
---|---|
[스프링 기반 REST API 개발] 시큐리티 OAuth2 리소스 서버 설정하기 (0) | 2021.01.09 |
[스프링 기반 REST API 개발] 시큐리티 폼 인증 설정하기 (0) | 2021.01.09 |
[스프링 기반 REST API 개발] 시큐리티 기본 설정하기 (0) | 2021.01.09 |
[스프링 기반 REST API 개발] Account에 스프링 시큐리티 적용하기 (0) | 2021.01.09 |