OAuth란
OAuth(”Open Authorization”)은 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다. 이 매커니즘은 여러 기업들에 의해 사용되는데, 이를테면 아마존, 구글, 페이스북, 마이크로소프트, 트위터가 있으며 사용자들이 타사 애플리케이션이나 웹사이트의 계정에 관한 정보를 공유할 수 있게 허용한다. (출처 : 위키백과)
솔직히 위 설명만 보면 무슨 소린지 이해가 잘 안된다.
어떠한 사이트를 이용하다가 마음에 들어서 가입한다고 생각해보자.
가입하기를 눌렀을 때 아래와 같은 기능을 본적이 있을 것이다.
이것이 바로 OAuth를 활용한 기능이라고 볼 수 있다.
네이버 D2에서는 OAuth를 방문증, 로그인을 사원증에 빗대서 설명한다.
나방문씨(외부 손님)가 안내 데스크에서 업무적인 목적으로 김목적씨(회사 사원)를 만나러 왔다고 말한다.
안내 데스크에서는 김목적씨에게 나방문씨가 방문했다고 연락한다.
김목적씨가 안내 데스크로 찾아와 나방문씨의 신원을 확인해 준다.
김목적씨는 업무 목적과 인적 사항을 안내 데스크에서 기록한다.
안내 데스크에서 나방문 씨에게 방문증을 발급해 준다.
김목적씨와 나방문씨는 정해진 장소로 이동해 업무를 진행한다.
흥미로운점은 단순히 사용자를 인증(Authentication)을 하는 것이 아닌, 권한(Authorization)도 같이 받아올 수 있다는 것이다.
예를 들어, 구글 OAuth를 이용하면 사용자의 구글 캘린더에 대한 권한도 받아낼 수 있는 것이다.
서비스 제공자 입장에서는 정말 활용도가 무궁무진한 기술이고
사용자 입장에서는 간편하게 회원가입/로그인을 할 수 있고
플랫폼 입장에서도 고객들의 여러 데이터들을 알 수 있게 된다.
[참고] OAuth2.0의 일반적인 2가지 용도
- 연합된 신원 (federated identity) 사용자가 자신의 다른 계정으로 애플리케이션에 로그인할 수 있게 해준다. 예를 들면 Google 계정으로 Velog와 Github에 로그인하는 경우, 해당 사용자는 단지 Google 계정 하나만 관리하면 된다. 이런 의미에서, 여러 사이트들이 연합해 하나의 신원ㅇ르 사용한다고 말할 수 있다.
- 권한 위임(delegated authority) 어떤 서비스가 사용자를 대신해서 다른 서비스의 리소스에 접근할 수 있게 해준다. 예를 들면 LinkedIn에서 구글 사용자의 연락처 리스트를 보고 그 연락처에 있는 사람들을 링크드인 친구로 등록할 것을 추천하는 경우이다. 즉, 사용자의 구글 연락처 리스트에 접근할 수 있는 권한이 링크드인에 위임된 것이다.
용어 정리
OAuth에 소개하기에 앞서 용어를 먼저 정리하고자 한다.
리소스 서버(resource server) , 서비스 제공자(service provider)
- Open API를 제공하는 서비스.
- ex) 구글, 애플, 페이스북, 카카오, 네이버
클라이언트(client) 혹은 소비자(Consumer)
- Open API를 사용해 서비스 제공자의 기능을 사용하면서, 사용자에게 서비스를 제공.
- 서비스를 운영하는 웹이나 어플리케이션이다.
리소스 오너(resource owner), 사용자(user)
- 실제 서비스를 사용하는 사용자이다.
- 서비스 제공자 계정을 가지고 있는 사용자.
OAuth 프로토콜에서 소개하는 명칭은 각각 Resource server, Client, Resource owner이다. 다른 기술 블로그들을 찾아보면 OAuth를 소개하는 글에 모두 제 각각 이름을 짓는다. (ex 소비자, 서버, 클라이언트 등등) 명칭만 다르지 수행하는 일은 동일하니 오해없기를 바란다.
Authorization Code
클라이언트가 서비스 제공자에게 접근 권한을 인증받기 위해 사용하는 값.
인증이 완료된 이후에는 Access Token으로 교환한다.
Access Token
인증 후 클라이언트가 서비스 제공자의 자원에 접근하기 위한 키를 포함하는 값
Refresh Token
한번 발급받은 Access Token은 사용할 수 있는 시간이 제한되어 있으며, 만료된 Token으로 API를 요청하면 401에러가 발생한다.
Access Token이 유효기간 종료 등으로 만료되면, 새로운 토큰을 얻어야 하는데 그때 Refresh Token을 사용한다.
보통 Resource Server는 Access Token을 발급할 때 Refresh Token을 함께 발급한다.
Access Token이 만료되어 401에러가 발생하면, Client는 보관 중이던 Refresh Token을 보내 새로운 Access Toekn을 발급받게 된다.
OAuth 개요
OAuth를 사용하기에 상황을 세팅해보자.
우리는 Github로부터 사용자의 Gist의 목록을 가져와 볼 것이다.
즉 우리는 Client에 속하는 웹 개발자이다.
명심해야할 것은 앞으로 나올 몇번의 GET, POST 요청은 결국 Access Token을 얻기 위함인 것이다.
- 어플리케이션이 OAuth 서버에 요청해 브라우저를 열어 사용자가 인증을 진행하게 한다.
- 사용자는 브라우저에서 나오는 인증 프롬프트로 인증 후 어플리케이션의 요청을 승인한다.
- 사용자는 OAuth 서버에서 인증코드를 받아 어플리케이션으로 돌아온다.
- 어플리케이션은 인증 코드를 access token으로 교환해준다.
시작하기에 앞서
Client(웹 어플리케이션)가 플랫폼을 이용하기 위해서는 자신의 서비스를 등록하여 사전 승인을 받아야 한다. Github Developer Settings에서 Github에 웹 어플리케이션을 등록한다.
위와 같은 순서로 Github OAuth Apps에 접근하여, 아래 정보를 입력하여 발행한다.
등록 절차를 마치면 세 가지 정보를 부여받는다.
- Client ID : 클라이언트 웹 어플리케이션을 구별할 수 있는 식별자이며, 노출이 무방하다.
- Client Secret : ClientID에 대한 비밀키로서, 절대 노출해서는 안된다.
- Authorized redirect URL : Authorization Code를 전달받을 리다이렉트 주소이다.
Client Secret은 발급 당시에만 확인할 수 있기 때문에, 발급 후에 꼭 다른곳에 기록해두자.
Client Secret은 절대 유출되어서는 안되는 중요한 정보이다.
해당 게시글에 사용된 Client Secret은 삭제된거니 시도해보지 마세요 ㅎㅎ..
A. Client가 User에게 Github ID, 권한 받기
기본 요청 형식
GET <https://github.com/login/oauth/authorize>
매개변수
이름 | 유형 | 설명 |
client_id | string | 필수. 위에서 Github에서 등록하고 받은 클라이언트 ID |
redirect_uri | string | 사용자가 권한을 승인 후 전송당할 URL |
login | string | 특정 계정을 제안할 때 사용 |
scope | string | 어떠한 권한을 제공받을 것인지 |
state | string | 추측할 수 없는 임의의 문자열. 요청 위조 공격으로부터 보호하는데 사용 |
allow_signup | string | 인증되지 않은 사용자에게 GIthub에 등록할 수 있는 옵션이 제공되는지 여부. 기본값은 true이다. |
더욱 자세한 매개변수는 GIthub 문서를 살펴보면 된다.
위의 내용을 바탕으로 사용자의 Gist 권한을 받아와보자.
GET <https://github.com/login/oauth/authorize?client_id={cliend_id}&scope=gist>
우선 브라우저의 주소창에 위와 같은 형식의 주소를 요청한다.
사용자가 Github에 로그인하고, 권한을 허용한다는 버튼을 누르면,
localhost:3000/afterlogin?code=89abcd3fb2567bf2492c 이런 GET 응답이 들어오게 된다.
이는 callbackURL에 query String으로 code라는 값을 전달해준 것이다.
전달받은 code가 앞서 설명한 Authorization 코드이다.
callback URL으로 전달받은 query string을 파싱하는 코드를 Express로 작성해보았다.
router.get('/afterlogin', function(req, res, next) {
console.log(req.query.code);
res.render('index', { title: 'afterlogin' });
});
Authorization Code를 줄테니 Access Token 주세요!
아까 Query String으로 전달받은 Authorization Code 는 일시적인 값이다. Github에서는 해당 코드가 10분 동안만 유효한다. 즉, 10분이 지나면 만료가 되니까 그 전에 Access Token으로 바꿔야 한다.
기본 요청 형식
POST <https://github.com/login/oauth/access_token>
매개변수
이름 | 유형 | 설명 |
client_id | string | 필수. 위에서 Github에서 등록하고 받은 클라이언트 ID |
client_secret | string | 필수. 위에서 Github에서 등록하고 받은 클라이언트 Secret |
code | string | 필수. Get 요청의 query string으로 받은 Authorization code의 값 |
redirect_uri | string | 사용자가 권한을 승인 후 전송당할 URL |
POSTMAN을 통해 Access token을 발급 받아보자.
Client는 ID와 비밀키 및 code를 Resource Owner를 거치지 않고 Resource Server에 직접 전달한다.
Resource Server는 정보를 검사한 다음, 유효한 요청이라면 Access Token을 발급하게 된다.
Client는 해당 토큰을 서버에 저장해두었다가 API 호출 시 해당 토큰을 헤더에 담아 보낸다.
Access Token을 사용하여 API 호출
이제 얻은 Token로 API를 호출하여 사용자의 정보를 얻어올 일만 남았다.
어떤 기능, 정보가 있는지는 Github의 Rest API Document를 참조하자.
기본 요청 형식
Authorization: Bearer OAUTH-TOKEN
GET <https://api.github.com/user>
위 사진은 Users에 관련된 정보를 요청한 결과이다. (참조)
Access token이 있어야 응답이 가능한 정보이고, 이와 같이 해당 계정과 연동된 풍부한 자원 및 기능들을 내가 만든 웹 어플리케이션에서 사용할 수 있다.
이때 주의하여야할 점은, Access Token 뒤에 &token_type=bearer 라고 붙은걸 없애주고, 앞에 Bearer 을 붙혀주어야한다.
Bearer은 OAuth를 위해 고안된 Token type이다.
이제 마지막으로 Gist 정보를 얻어와 보자!
Github의 Rest API 문서를 뒤적이다보면, Gists라는 탭이 있다.
조금 뒤적이다 보면, 이런 문서를 찾을 수 있을 것이다.
이대로 POSTMAN에 요청을 해보면, 사진과 같이 내 GIST 목록이 잘 나오는것을 확인할 수 있다.
이걸 JS로 조금 가공을 하면 원했던 값만을 얻을 수 있게 된다!!!!
참조
- https://oauth.net/2/
- https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps#web-application-flow
- https://docs.github.com/en/rest
- https://tecoble.techcourse.co.kr/post/2021-07-10-understanding-oauth/
- https://d2.naver.com/helloworld/24942
- https://showerbugs.github.io/2017-11-16/OAuth-란-무엇일까
- https://yonghyunlee.gitlab.io/temp_post/oauth-authorization-code/
'프로그래밍 > 개발 이야기' 카테고리의 다른 글
[온라인 인프콘] 지금 당장 DevOps를 해야하는 이유 - 김충섭 (0) | 2022.09.12 |
---|---|
[온라인 인프콘] 어느 날 고민 많은 주니어 개발자가 찾아왔다 - 김영한 (0) | 2022.09.10 |
네이버 부스트캠프 7기 챌린지 후기 + 멤버십 합격 (2) | 2022.08.24 |
구름의 3번째 컨퍼런스에 다녀오다 (2) | 2022.08.24 |
네이버 부스트캠프 7기 1차, 2차 코딩테스트 후기 및 결과 (1) | 2022.07.05 |
댓글