본문 바로가기
모바일 SW 개발/REST API

Google Gmail API 사용 방법 (2) - Sample code

by 모바일 SW 개발자 Kibua20 2020. 7. 5.
반응형

앞선 게시글에서 Google API 콘솔에서 프로젝트를 생성한 후 credential.json을 얻는 방법을 설명하였고, 본 게시글은 아래 그림에서는 붉은색으로 표시한 '구글 인증 서버에 Authoized code를 요청 후 Access toekn을 받는 방법'을 설명하고자 한다.

 

[모바일/REST API] - Google Gmail API 사용 방법 (1)

[모바일/REST API] - Google gmail API 사용 방법 (3)

 

 

Google API 호출을 위한 전체 Flow (Web Server Application flow로 진행)

 

 


Step 2. 구글 인증 서버에서 Authorization code 받기

구글에 OAutho 2.0 의 Web server application에서 설명된 https request 방법을 먼저 확인해야 한다.  구글의 샘플 코드를 보면 아래와 같다.  https://accounts.google.com/o/oauth2/v2/auth로 접속하고, URL의 파라미터는 scope, access_type, includ granted scope, response_type, state, redirect_url, client_id를 전달한다. 이 중 API 별로 변경해야 하는 값은 scope, redirect_url, client_id 값이고 상세 설명은  API reference를 확인해야 한다.

<구글 Authorization code 받기 위한 샘플 코드>

https://accounts.google.com/o/oauth2/v2/auth?
    scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
    access_type=offline&
    include_granted_scopes=true&
    response_type=code&
    state=state_parameter_passthrough_value&
    redirect_uri=https%3A//oauth2.example.com/code&
    client_id=client_id

 

scope: 사용하고자 하는 API를 인증 범위를 의미하며 사용자 로그인 시 scope 에 대해서 명시적 동의를 받는다. 만일 soce에 여러개라면 각각 space로 구분해서 추가할 수 있다.   예를 들어  Gmail의 Users.message:send API는 아래와 같이 명시되어 있다.  .

Gmail send message의 scope
scope 파라미터 설명

 

  • access_type: online 과 offline으로 설정할 수 있으며 'offline'으로 설정한다. access token은 한 번 받으면 1시간 동안만 유효하고, 유효한 시간에서만 API 호출이 가능하다. access_token을 다시 받기 위해서는 refersh token을 받아야 하고  사용자 로그인 없이 refresh token을 사용해서 access token을 받을 수 있다.  사용자로 하여금 API 사용할 때마다 로그인을 할 수 없기 때문에 refersh token을 얻은 것은 서비스 개발자의 입자에서는 매우 중요하다.  (아래 설명 참고)

access_type설명

  • redirect_uri:  사용자 권한 동의를 구글 인증 서버로 요청하고 Authoization code와 access token을 받을 수 있는 URL을  설정한다. Google API Console에서 추가한 값으로 credential.json 파일에 있는 값을 사용해야 하고, 일치하지 않는 경우 에러가 발생한다. 

  • client_id:  Google API console에서 만든 OAutho client를  의미하고 crendential.json 파일의 client ID 값과 일치해야 한다.

 

2.1.Authorization code  받기 

구글의 https://accounts.google.com/o/oauth2/v2/auth 에 URL paramter를 전달하는 단계이다.  아래와 같이 URL 파라미터로 API에 맞게 변경하고 URL을 공백 없이 한 줄로 만들어서 Chrome 브라우저에 URL 값에 입력한다.  Chome 브라이저에서 URL 위에 parameter 값을 URL encoding 변환하기 때문에 별도의 URL ending은 필요 없고 공백만 없이 입력 정상 동작한다.  만일 html이나 java script에서 URL을 입력하는 경우 paramter 부분을 URL encode를 수행해야 한다.

 

Google 인증 서버에 Authorization code 요청

 

Authorization URL을 입력이 되면 아래와 같이 구글 계정 로그인 화면을 표시하고,  계정 사용자에 대한 패스워드 인증 및 API scope에 대한 명시적 동의를 얻는다.

 

1) Authorization URL을 전달하면 구글 계정 서버에서 계정을 선택 화면을 표시한다.

2) 확인되지 않은 앱: Google API console에서 권한을 신청할 때 구글의 Verification Process 리뷰를  받아야 한다. 현재는 Test 용이나 서버용 계정이기 때문에 구글 리뷰를 받을 필요는 없고, 고급 메뉴에서 App 동의 화면을 선택한다.

3) 고급> App 화면으로 이동 선택

4) 사용자에게 API의 scope에 대한 명시적 동의를 받는다. 설정된 scope에 대한 확인 과정을 진행한다.

5) API에 개인정보 접근에 대한  최종 확인 

 

Google 인증 서버에 Authorization code 요청: 사용자의 명시적인  동의를 받는다 

 

Google 인증 서버에 Authorization code 요청: 사용자의 명시적인  동의를 받는다 

 

 

Step 3. Authoization code값을 활용해서  Access token을 받기

 

사용자가 API의 scope을 명시적으로 동의하고 구글 서버에 제출하면 redirect URL로 인증 결과(authorization code)를 전달한다.  아래 그림에서는 Chrome 브라우저에서 URL의 위치가 구글 서버에서 localhost를 변경됨을 확인할 수 있다. 그 세부 내용을 보면 Redirect URL에 state, code, scope이 전달되어 있음을 알 수 있다. 

 

6) 구글 인증 서버에서 Redirect URL로 authorization code를 전달 받음

7) 구글 서버에서 code 값, client ID, client_secret, redirect URL, grant type을 설정하여 구글 서버에 https 의 request 전송

8) 구글 서버에서는 reponse에 refresh token과 access token을 reponse 한다. 

 

Repsonse 를 보면 access_token, expires_in, scope이 명시되어 있다. 이 중에 expireds_in 값는 access token의 유효한 시간 값으로 3600초(= 1시간)의 유효 시간을 가지고 있다.

 

Authoization code를 활용해서 access token 받기

7) 번 과정은  http의 post와 동일한 값을 가진다.  Html의 java script을 구성이 가능하면, curl이나 python으로도 request를 호출해도 access token을 얻을 수 있다.  

Access token을 획득하기 위해서 http request

 

 

 

참고) Redirect URL을 위한 receivecode.html  (출처: 생활 코딩)

receivecode.html 은 구글 인증 서버에서 내려주는 URL 중 code 값을 찾아서 다시 post 하는 코드이다.

<!DOCTYPE html>
<html>
<body>
<style>
  input{  width:300px; }
</style>
        
<form action="https://www.googleapis.com/oauth2/v4/token" method="post" enctype="application/x-www-form-urlencoded">
code : 
<input type="text" id="codebox" name="code"><br>
client_id : <input type="text" name="client_id" value="178730211101-6f69st2m3ajb3je2clsdm15e3cv7170e.apps.googleusercontent.com"><br>
client_secret : <input type="text" name="client_secret" value="RIQqjr77Nfrt9gSGnihfQRPe"><br>
redirect_uri : <input type="text" name="redirect_uri" value="http://localhost:8080/receivecode.html"><br>
grant_type : <input type="text" name="grant_type" value="authorization_code"><br>
<input type="submit">
</form>

<script>
        function getHttpParam(name) {
            var regexS = "[\\?&]" + name + "=([^&#]*)";
            var regex = new RegExp(regexS);
            var results = regex.exec(window.location.href);
            if (results == null) {
                return 2;
            } else {
                return results[1];
            }
        }
        var ret = getHttpParam("code");
        document.getElementById("codebox").value = ret;
</script>

</body>
</html>

 

Check Point #1.

Web server의 정상 동작 여부를 확인해야 합니다.  http://localhost:8080 or http://localhost 가 정상적으로 표시되어야 한다. 만일 정상적으로 표시되지 않는다면 apache2와 tomcat9 버전으로 설치해야 한다. (설치 방법)

 

Check point #2. 

Web server가 정상 동작하는 상태에서 Google 계정이 표시 안되고, URL에러가 발생하는 경우는 URL 에 붙는 paramter를 URL 인코딩을 해야 한다.  즉 URL parameter는 space 나 '/' 를 사용할 수 없기 때문에 URL encoder으로 변환해야 한다.

 

 

관련 글:

[모바일/REST API] - Google Gmail API 사용 방법 (1)

[모바일/REST API] - Google gmail API 사용 방법 (3)

 

[모바일/Python] - Python 표준 입출력(stdin/stdout) 활용 - 리눅스 프로그램과 연동

[모바일/Python] - Python JSON 사용 시 TypeError: Object of type bytes is not JSON serializable

[모바일/Python] - Python smtplib 사용한 email 발송 예제 (gmail)

[개발환경] - [Memo] 우분투에서 gmail 활용하여 command line으로 email 전송

[모바일/REST API] - 우분투 20.04에서 Web 서버 설치 방법 (apache2, tomcat9)

 

반응형



댓글12

  • 로그인시렁.. 2020.08.27 11:05

    명시적 동의 받은거 확인하려는지 매번 다시 접속할때마다 로그인 하라고 하는데, 혹시 로그인 안하고 인증 방법은 없나요? api key나 client.json 정보로..
    답글

    • refresh 토근을 받으셨나요? acess 토근은 유효 기간이 1시간이고 refresh 토근은 유효 시간이 상대적으로 깁니다.

    • BlogIcon 구구구글 2020.08.27 15:09

      답변 감사합니다 :)
      java sample 보면서 코딩하고 있는데, url에 클라이언트 아이디 스코프 등등 날리기만하네요.. 인증은 되는데 매번 로그인을 요구해서...
      반환 받은 Credential에 AccessToken이 들어있습니다.
      https://developers.google.com/youtube/v3/docs 참조하고 있어요

    • access 토근 요청할 때 offline 으로 설정해야 refresh 토큰이 내려옵니다.

    • BlogIcon 구구구글 2020.08.27 15:59

      넹. flow 빌드할 때 셋팅 해줬어요. refresh 토큰도 잘 내려와요.
      처음에 접속 할때는 항상 로그인 해줘야하나요~?
      client_secrets나 api key를 저장해놓고 로그인 안하고 바로 인증 하는 방법은 없을까요~?

    • 우아~ 금방 수정하시네요. 저는 refresh token 받은데 거의 일주일 이상 삽질(?)을 했던 기억이...

      Google API 인증 방식 중에서 Web Application 을 사용자 인증을 *최소 한번*은 명시적으로해야 합니다. refresh token은 받은 다음부터는 구글 로그인 없이 access token을 받을 수 있습니다.

      Server application 으로 JWT 방식으로 인증하면 사용자 로그인은 필요 없지만 서비스 계정과 사용자 계정가 차이가 있습니다.
      아래 링크 확인해보세요.

      https://kibua20.tistory.com/87

    • BlogIcon 구구구글 2020.08.27 16:28

      감사합니다 :)
      Web Application 에서는 *최소 한 번* 로그인을 해줘야 하는군요...ㅠ
      Server application 이쪽도 아까부터 테스트 중이었는데 제가 구버전 maven을 가져왔는지 계속 메소드 충돌 나더라구요..
      deprecated가 너무 많아요..
      서비스 계정 만들고 인증테스트 하고 있는데 OAuth랑 차이나서 헷갈리고 있습니다..
      이쪽 장점이 로그인 없이 토큰을 받을 수 있으니 이쪽을 파보겠습니다.
      도움이 많이 되었어요 감사합니다 :)

    • 서비스 계정은 제 블로그 링크에서 아래 사항을 주의하시면 됩니다. JWT 생성은 그리 어렵지는 않습니다.

      --------------------------------------------
      Service account는 end-user를 대신해 Google 서버에서 인증을 받고 API를 호출할 수 있다. Sevice Account의 가장 큰 장점은 사용자 로그인이 없이 Access token을 발급 가능하다. 사용자가 명시적인 로그인이 없이도 Json Web Token을 기반으로 API scope에 대한 사용 권한을 받을 수 있고, Access 토근을 통해서 Google API를 사용할 수 있다.

      한 가지 주의할 점은 사용자의 계정과 서비스의 계정은 별도의 계정이며, 사용자 데이터를 접근하기 위해서는 서비스 계정에 공유 권한을 부여해야 한다. 예를 들어, kibua20@gmail.com 의 사용자 계정에 kibua20-services@serverapi.iam.gservices.com 의 서비스 계정을 만들었다면 이 둘은 다른 계정으로 취급되고, kibua20 계정의 캘린더 데이터를 접근하기 위해서는 kibua20-services 계정에 캘린더 접근 권한은 사전에 허용해야 서비스 계정에서 사용자 계정의 캘린더 사용이 가능하다.

  • 도와주세요 2020.11.24 13:46

    "2.1.Authorization code 받기"를 따라 하고 있는데 URL 요청해서 로그인 하니까 아래와 같은 메시지가 뜹니다. 이걸 어떻게 액세스 권한을 부여할 수 있을까요? 구글링해도 답이 안 보입니다 ㅠㅠ
    403 오류: access_denied
    The developer hasn’t given you access to this app. It’s currently being tested and it hasn’t been verified by Google. If you think you should have access, contact the developer
    답글