본문 바로가기
Back-end

Github Oauth App의 Authorization 처리

by 노아론 2019. 10. 31.

Authorizing OAuth Apps 를 통해 문서확인이 가능하며 이 문서를 토대로 인증구현 방법을 작성하였다.
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/

Github의 OAuth Application 인증을 통해 로그인을 하고,

유저 정보와 repository를 가져오는 과정에 기술한다.

Github에서 추가가능한 App은 OAuth App과 Github App 이 있다

이 두가지의 차이점은 다음과 같다

  • OAuth App : 사용자가 접근가능한 것에 요청 가능

  • Github App : 필요한 것만 액세스 요청 가능, 코드에 대한 읽기/쓰기 권한이 없음. issues, labels, milestones 관리 가능

보다 더 자세한 차이는 https://developer.github.com/apps/differences-between-apps/

이 글에서는 OAuth App 에 대해 다룹니다.

웹 어플리케이션 플로우

  1. 사용자가 Github 정보를 입력하도록 리다이렉트됨

  2. Github에서 로그인을 거쳐 Authorize 후 서버(서비스되는 서버의 callback url)로 돌아옴

  3. 유저의 Access token을 통해 API에 접근 가능

유저에게 Github 정보 요청하기

먼저 Github의 setting/developers 에 들어가서 새 Oauth application을 등록한다.

image

과정을 처음부터 보이기위해, 위와 같이 임의로 등록하였다.

Authorization callback URL은 웹 어플리케이션 플로우의 2번에서

서비스되는 서버의 어느 경로로 redirect 되는지 설정하면 된다.

Register application 을 하면 다음과 확인할 수 있다.

Client secret은 독자분들을 위해 블라인드 처리하지 않음. 작성 후 Reset 처리완료함.

image

 

그럼 이제 유저에게 Github 정보를 입력하도록 요청해보자

GET https://github.com/login/oauth/authorize

# Parameters
client_id : string # 필수
redirect_uri : string # authorization을 거치고 어디로 이동하는지
scope : string # 접근 범위. 기본값 : 빈칸
login : string # placeholder와 비슷한 역할을 한다
state : string # csrf공격 방지를 위해 게싱 불가능한 랜덤 스트링 (직접 설정필요)
allow_signup : string # 미인증 사용자에게 가입가능하게 할 것인지. 기본값 true

scope 설정에 관한 문서

scope 설정을 하지않으면?

Read org and team membership, read org projects

Read repository hooks

Read all user profile data

Access commit status

Access user email addresses (read-only)

에 대한 권한만 가진다

나는 repository의 status, repository에 대해 hook으로 읽기권한, user의 이메일주소 읽기권한을 scope로 두었다.

repo:status
Grants read/write access to public and private repository commit statuses. This scope is only necessary to grant other users or services access to private repository commit statuses without granting access to the code.
read:repo_hook
Grants read and ping access to hooks in public or private repositories.
user:email
Grants read access to a user's email addresses.

완성된 URI로 나타내면 아래와 같다

https://github.com/login/oauth/authorize?scope=repo:status read:repo_hook user:email&client_id=6cff16f825bbdac48d5b

redirect_uri를 설정하지 않았는데, 처음 OAuth App을 등록할때 callback url에 넣은 url로 이동된다.

나의 경우, https://example.com/callback/로 이동될 것이다.

그럼 다음과 같이 확인할 수 있다.

scope 설정대로 권한 access 가 표시된다.

 

image

 

이제 callback_url로 설정해둔 곳으로 redirect 됨을 볼 수 있을 것이다.

URI는 다음과 같이 구성됨을 확인할 수 있다.

https://example.com/callback/?code=a5e58d098317a84df83a

Callback_url과 함께 code 파라미터가 붙는다

만일, CSRF 공격 방지를 위해 state를 추가하였다면 state 파라미터도 함께 붙게 된다.

유저가 깃헙 Authorization을 통해 리다이렉트된 이후의 과정

이제 우리는 code라는 파라미터를 가지고 Authorize한 사용자의 Access Token을 구할 것이다.

Q. code 파라미터가 Access Token 아닌가?

A. 아니다. client_idclient_secret와 함께 code를 파라미터로 하여금 요청을 해야 우리가 원하는 Access Token을 구할 수 있다.

https://github.com/login/oauth/access_token 에 POST 요청을 보내어 Access Token을 받아보자

아래와 같이 POST요청으로 client_id, client_secret, code 데이터를 담는다.

만일 CSRF 공격방지를 위해 state파라미터가 있다면 state 를 추가해 동일한 값을 넣어준다.

POST https://github.com/login/oauth/access_token

# 전달 데이터
client_id : 6cff16f825bbdac48d5b
client_secret : 434e4cf8ed7cef95a48d3f79e2fabcfa09fb7bb4
code : a5e58d098317a84df83a

요청을 하면 아래 응답과 같은 형식으로 나오는 것을 볼 수 있다.

{
    "access_token":"940cda2f68dd9a05ccdd71e60025b878e024e1ce",
    "scope":"read%3Arepo_hook%2Crepo%3Astatus%2Cuser%3Aemail",
    "token_type":"bearer"
}

드디어 Access Token을 구했다!

이제 간단한 동작 여부 확인을 위해 유저에 대한 정보를 요청 해보자

Access Token은 body가 아닌, Header 에 넣어서 GET으로 요청한다.

API종류마다 요청방식과 파라미터는 다를 수 있다

GET https://api.github.com/user

# Header
Authorization: Token 940cda2f68dd9a05ccdd71e60025b878e024e1ce

Response 데이터는 아래와 같다.

{
    "login": "roharon",
    "id": 4939738,
    "node_id": "MDQ6VXNlcjQ5Mzk3Mzg=",
    "avatar_url": "https://avatars0.githubusercontent.com/u/4939738?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/roharon",
    "html_url": "https://github.com/roharon",
    "followers_url": "https://api.github.com/users/roharon/followers",
    "following_url": "https://api.github.com/users/roharon/following{/other_user}",
    "gists_url": "https://api.github.com/users/roharon/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/roharon/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/roharon/subscriptions",
    "organizations_url": "https://api.github.com/users/roharon/orgs",
    "repos_url": "https://api.github.com/users/roharon/repos",
    "events_url": "https://api.github.com/users/roharon/events{/privacy}",
    "received_events_url": "https://api.github.com/users/roharon/received_events",
    "type": "User",
    "site_admin": false,
    "name": "Aaron Roh",
    "company": null,
    "blog": "https://info.aaronroh.org",
    "location": "SOUTH KOREA",
    "email": "roharon@studentpartner.com",
    "hireable": true,
    "bio": "Microsoft Student Partner |\r\nGithub Campus Expert trainee |\r\nKITRI-BOB 8th mentee |\r\nHUFS CES undergrad.\r\n",
    "public_repos": 58,
    "public_gists": 9,
    "followers": 23,
    "following": 14,
    "created_at": "2013-07-04T11:53:02Z",
    "updated_at": "2019-10-30T12:19:28Z"
}

여기까지 Github OAuth App의 Authorization 처리와 실제 작동까지 보았다.
앞으로 네이버 아이디로 로그인(네아로), 카카오 로그인과 같은 OAuth2 인증 로그인구현에 대해 간간히 포스팅해보고자 한다.

댓글