회원가입이나 로그인이 필요한곳 어디든 Google, Naver, Kakao, twiter등 외부 계정을 기반으로 간편히 회원가입 및 로그인 할 수 있는 웹,앱 어플리케이션을 쉽게 찾아볼 수 있다. 이때 사용 되는 프로토콜을 OAuth라한다, 단순히 로그인뿐만이 아니라 예를 들어 Google로 로그인하면 API를 통해 연동된 Calendar 정보를 가져와 사용자에게 보여줄수 있다.
[OAuth란?]
OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다. (위키백과)
[OAuth 참여자]
OAuth 동작에 관여하는 참여자는 크게 세 가지로 구분할 수 있다.
1. Resource Server : Client가 제어하고자 하는 자원을 보유하고 있는 서버입니다.
Facebook, Google, Twitter, Kakao가 이에 속한다.
2. Resource Owner : 자원의 소유자입니다.
Client가 제공하는 서비스를 통해 로그인하는 실제 유저가 이에 속합니다.
3. Client
Resoure Server에 접속해서 정보를 가져오고자 하는 클라이언트(웹 어플리케이션)입니다.
[Resource Server 요구정보 및 부여받는 권한]
Resource Server는 기본적으로 2가지 사항을 요구한다.(웹)
- Homepage URL (페이지의 url주소)
- CallBack(redirect) URL : Authorization Code를 전달받을 주소
- scope : Client가 Resource Server로부터 인가받을 권한의 범위이다.
해당 요구사항들이 유효하면 클라이언트는 서버에게 크게 세 가지 정보를 부여받는다.
- Client ID : 클라이언트 웹 어플리케이션을 구별할 수 있는 식별자이며, 노출되도 무방하다.
- Client Secret : Client ID에 대한 비밀키로서, 절대 노출되서는 안된다.
- Authorization Code : 위 2가지 정보와 함깨, Access Token, Refresh Token을 받는데 사용된다.
[Resource Owner의 승인]
네이버에서는 네이버로그인을 하기 위해 다음과 같은 주소로 GET 요청과 필요한 파라매터들을 보내도록 명시한다. (state = 사이트 간 요청 위조(cross-site request forgery) 공격을 방지하기 위해 애플리케이션에서 생성한 상태 토큰값으로 URL 인코딩을 적용한 값을 사용)
GET <https://nid.naver.com/oauth2.0/authorize?client_id={client_id}&redirect_uri={redirect_uri}?state={state}>
String clientId = "nMUNpsgNjmad0FDEnocF";//애플리케이션 클라이언트 아이디값";
String redirectURI = URLEncoder.encode("", "UTF-8");
SecureRandom random = new SecureRandom();
String state = new BigInteger(130, random).toString();
String apiURL = "<https://nid.naver.com/oauth2.0/authorize?response_type=code>";
apiURL += "&client_id=" + clientId;
apiURL += "&redirect_uri=" + redirectURI;
apiURL += "&state=" + state;
model.addAttribute("state", state);
model.addAttribute("APIURL",apiURL);
return new ModelAndView("loginpage");
- Resource Owner는 Resource Server에 접속하여 로그인을 수행한다.. 로그인이 완료되면 Resource Server는 Query String으로 넘어온 파라미터들을 통해 Client를 검사한다.
[Resource Server의 승인]
Resource Owner의 승인이 마무리 되면 명시된 Redirect(Callback) URL로 클라이언트를 리다이렉트 시킨다. 이 때 Resource Server는 Client가 자신의 자원을 사용할 수 있는 Access Token을 발급하기 전에, 임시 암호인 Authorization Code를 함께 발급합니다.
해당 정보들을 이용해서 Resource Server에게 엑세스토큰을 발급받습니다.
// ex) Java
RestTemplate restTemplate = new RestTemplate();
NaverDTO naverDTO = new NaverDTO();
naverDTO.setURL("<https://nid.naver.com/oauth2.0/token?grant_type=authorization_code&>");
naverDTO.setClient_id(clientId);
naverDTO.setClient_secret(clientSecret);
naverDTO.setCode(code);
naverDTO.setState(state);
naverDTO.setRedirect_uri(URLEncoder.encode("", "UTF-8"));
String Token = restTemplate.getForObject(naverDTO.toString(),String.class);
JSONObject jsonObject = new JSONObject(Token);
이제 Client는 해당 토큰을 서버에 저장해두고, Resource Server의 자원을 사용하기 위한 API 호출시 해당 토큰을 헤더에 담아 보냅니다.
[API 호출]
Access Token을 헤더에 담아 Github API를 호출하면, 해당 계정과 연동된 Resource Server의 풍부한 자원 및 기능들을 내가 만든 웹 어플리케이션에서 사용할 수 있다.
[Refresh Token?]
Access Token은 만료 기간이 있으며, 만료된 Access Token으로 API를 요청하면 401 에러가 발생합니다. Access Token이 만료되어 재발급받을 때마다 서비스 이용자가 재 로그인하는 것은 다소 번거롭다.
보통 Resource Server는 Access Token을 발급할 때 Refresh Token을 함께 발급한다. Client는 두 Token을 모두 저장해두고, Resource Server의 API를 호출할 때는 Access Token을 사용한다. Access Token이 만료되어 401 에러가 발생하면, Client는 보관 중이던 Refresh Token을 보내 새로운 Access Token을 발급받게 된다.
'개발 > WEB' 카테고리의 다른 글
디바운싱과 쓰로틀링 (0) | 2024.06.20 |
---|---|
12가지 API 보안 강화 전략 (0) | 2024.05.07 |
SSE(Server-Sent-Events) (0) | 2024.04.15 |
세션, 쿠키 그리고 토큰의 차이점 (0) | 2024.04.11 |
SSL/TLS 인증 (0) | 2024.04.11 |