• 사용자가 아닌 응용프로그램 (client) 이 인증을 요청할때 사용 ( Resource Owner = Client )

  • 접근 권한이 한정되어있는 프로그램 사용시 활용

  • 신뢰성이 높은 관리자용 Desktop App 이나 Mobile App 에서 사용

5. Device Code Grant

  • 장치 코드 부여 유형은 브라우저가 없거나 입력이 제한된 장치에서 사용.

6. Refresh Token Grant

  • 기존에 저장해둔 리프러시 토큰이 존재할 때 엑세스토큰을 재발급 받을 필요가 있을 때 사용합니다. 그리고 기존 액세스는 토큰이 만료됩니다.

마이크로 서비스 보안을 쇼핑몰에 적용 예제

이번 장은 Oauth2.0 과 JWT 토큰을 사용하여 쇼핑몰에 적용한 예제를 살펴본다.

  • 우선 Client 는 사용하고자 하는 서비스 이기 때문에 쇼핑몰 ui 가 될 수 있습니다.
  • 쇼핑몰에 접속시 사용자는 자기자신을 확인 하는 로그인을 하게 되는데, 로그인 정보를 확인 하는 Grant 는 1. Authorization Code Grant, 2. Implicit Grant, 3. Password Credentials Grant 방식을 사용 할 수 있습니다. Authorization Server 를 구축하지 않고 타사 인증 서비스를 사용한다면, 1번 방법밖에 사용 할 수 없지만, Authorization Server 를 구축 하였기에 모든 Grant 를 사용 할 수있습니다. 그중 ui 에서 권한을 요청하는 방식은 3. Password Credentials Grant 방식 으로 예제는 구축되어 있습니다.
  • Resource Owner는 사용자 정보이고, Authorization Server 에 사용자 정보를 같이 가지고 있는 방식으로 예제를 구축하였습니다. 이렇게 인증서버가 사용자 정보를 같이 포함하고 있는 서버를 IAM(Identity and Access Management) 서버라고 부른다.
  • Authorization Server 는 Spring security 를 사용하여 구축 하였고, 토큰 요청시 JWT 로 변환하는 작업을 포함 하였습니다.
  • Resource Server 는 토큰이 유효한지 체크를 하고, 유효하면 api 를 허용하는 역할을 하기에, Gateway 서비스에 구현을 하였습니다.

참고 소스 코드 :
Authorization Server, Resource Owner - Oauth
Resource Server - Gateway
Client - UI

Authorization Server 사용

  1. git clone 합니다.

  2. cd oauth 접속 후 mvn spring-boot:run 으로 서버를 실행합니다.

  3. 로컬에서 실행시 localhost:8090 으로 서버가 실행 됩니다.

  • 서비스(ui)에서 Password Credentials Grant 방식으로 권한증서를 요청하기 위해서는 인증서버에서 발행하여 주는 Client_id, Client_Secret 정보를 모두 알고 있어야 합니다.

  • 서버가 실행시 유저 정보를 임의 값으로 생성 메모리 db 에 넣어주었습니다. AuthorizationServerApplication.java

  • 서버가 실행시 Client 정보를 임의 값으로 생성 메모리 db 에 넣어주었습니다. OAuth2AuthorizationServerConfig.java

  1. 토큰을 요청하는 api 는 /oauth/token 입니다. 요청시 grant_type=password username, password 를 같이 입력 하고, header 에 Client_id, Client_Secret 정보를 base64 로 인코딩 하여 요청합니다.
  • http --form POST localhost:8090/oauth/token 'Authorization: Basic dWVuZ2luZS1jbGllbnQ6dWVuZ2luZS1zZWNyZXQ=' grant_type=password username=1@uengine.org password=1

  • Basic 인증은 가장 일반적인 인증 스키마 입니다. base64를 이용하여 인코딩된 사용자 ID/비밀번호 쌍의 인증 정보를 전달합니다. base64는 복호화가 가능한 인코딩이기에 안전하지 않고 HTTPS / TLS 와 같이 사용을 하여야 보안상 안전해 진다. (예제에서는 https 를 사용하지는 않았다.)

  • 토큰 요청시 JWT 토큰과 추가로 서버에서 설정한 additionalInfo 값이 return 됩니다. 해당 토큰을 사용하여 자원요청을 하면 됩니다.

client 에서 Authorization Server 호출과 토큰 저장

  1. client (ui) 에서 인증서버로 http 요청을 하는 코드는 다음과 같다. 클라이언트는 알고있는 Client_id, Client_Secret 정보를 javascript 에서 base64 로 변환하는 방법인 btoa() 를 사용하여 인코딩 후 basic 스키마로 토큰 요청을 합니다. store.js

  2. 정상적으로 토큰 발행시 토큰 정보는 브라우저의 storage 인 localstorage 에 저장을 합니다. localStorage.setItem('accessToken', accessToken)

  • 브라우저에서는 토큰을 api 요청시마다 사용을 하기 때문에 저장을 해야 합니다. 브라우저에서 토큰을 저장하는 방식은 크게 웹 스토리지에 저장을 하거나, cookie 에 저장을 하는 방식이 있습니다.

  • 브라우저 웹 스토리지는 로컬스토리지와 세션스토리지 두가지 방식이 있습니다. 로컬스토리지는 삭제를 하지 않는 이상 브라우저를 종료하여도 정보가 남아있고, 세션스토리지는 브라우저를 종료하면 정보가 사라지는 방식입니다. 토큰은 자체 유효시간이 존재하기에 로컬스토리지에 저장을 하는것이 조금더 나은 방식입니다.

  • 쿠키는 자체적으로 이름, 값, 만료시간등을 가지고 자바스크립트나 서버에서도 사용할수 있는 값이지만, 4KB 만 저장을 할수 있는 용량문제로 토큰을 저장하는 방식에는 맞지 않다.

  1. client (ui) 에서 각종 api 를 요청시 header 값에 토큰을 실어서 같이 보냅니다.
  • http localhost:8088 'Authorization: Bearer $TOKEN'

  • curl localhost:8088/orders --header 'Authorization: Bearer $TOKEN'

  • Bearer 스키마는 Oauth 2.0 의 보안 리소스를 요청하는 방식입니다. RFC 6750

Resource Server 에서 토큰 유효성 확인

  1. Gateway 는 spring-cloud-gateway 를 사용하였습니다. spring-cloud-gateway 는 web reactive 방식을 사용하기 위하여 spring5 의 webflux 방식으로 구현이 되어있습니다. 그러기에 security 적용을 위하여 spring-security-webflux webflux-oauth2 방식을 사용하여 리소스 서버를 구축해야 합니다.
  • webflux 방식에서 jwt 토큰을 인증 하는 방식은 jwk-Set-Uri 를 구성하여 jwt 토큰 생성시 사용한 Key 값을 체크합니다.
@GetMapping('/.well-known/jwks.json')
@ResponseBody
public Map<String, Object> getKey(Principal principal) {
    RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic();
    RSAKey key = new RSAKey.Builder(publicKey).build();
    return new JWKSet(key).toJSONObject();
}
  • @EnableWebFluxSecurity 를 선언하여 들어오는 모든 요청을 검사 하고, 그중에서 ServerHttpSecurity http.oauth2ResourceServer().jwt() 역할을 선언하여 토큰 검증을 실시 합니다.
    ResourceServerConfiguration.java
*MSA School의 모든 콘텐츠에 대한 권리는 MSA School에 있으며, 무단 복제 및 배포를 금합니다. 영리 목적의 사용은 허용되지 않으며, 개인적 용도로 복제할 경우 반드시 출처를 표기해야 합니다.
© uEngine. All Rights Reserved. | 주소 : 서울특별시 서초구 신반포로45길 18 502호(잠원동, 주일빌딩)
사업자등록번호 : 211-87-95355 | 전화번호 : 02-567-8301 | 대표이사 : 장진영
*MSA School의 모든 콘텐츠에 대한 권리는 MSA School에 있으며, 무단 복제 및 배포를 금합니다.
영리 목적의 사용은 허용되지 않으며, 개인적 용도로 복제할 경우 반드시 출처를 표기해야 합니다.
© uEngine. All Rights Reserved.
주소 : 서울특별시 서초구 신반포로45길 18 502호(잠원동, 주일빌딩)
사업자등록번호 : 211-87-95355
전화번호 : 02-567-8301
대표이사 : 장진영