GoogleAPIのアクセストークンとリフレッシュトークン

#はじめに
先日GoogleのAPIを使う際に見落としでNot FoundエラーとBad　Requestのエラーがありましたので、メモとしてまとめます。

#Googleのコンソールからプロジェクト作成
https://console.developers.google.com/apis/dashboard

#API認証情報の作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/a63b21a3-ef46-6765-409a-598d4f3a9e89.png)

##1. OAuthクライアントID
利用者は画面から認可同意を行う場合はこちらを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/e3e7b39e-725e-4c3e-c2c3-1a7ed3fde601.png)

アプリケーション種類、名前、承認済みのリダイレクトURIは３つは入力すると、クライアント ID、クライアント シークレットを生成されました。

##2. サービスアカウントキー
画面操作不要で裏でJSON形式でアクセストークンを取得。バッチなどの処理の場合はこちらを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/a00b0bbc-3ecb-2a24-5b0a-5477f8618264.png)

JSON形式でファイルをダウンロードする

※APIのClientのライブラリを利用して通信
https://developers.google.com/api-client-library/java/google-api-java-client/oauth2

#認可コードの取得
クライアント、スコップを設定してURLからアクセス

```html
https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 redirect_uri=http%3A%2F%2localhost:8080&
 response_type=code&
 client_id=上記で取得したクライアントID
```

Google側に同意すると、URLから認可コードを取得できます。
`http://localhost:8080/?code=xxxxxxxxxxxx&scope=yyyyyyyyyyy`

※１　scopeは下記のURLに確認できます。
https://developers.google.com/identity/protocols/googlescopes
※２　redirect_uriは設定した承認済みのリダイレクトURI
※３　access_typeはonline、offlineを設定可能。offline　＋　初回目の場合のみToken APIをアクセスするとrefresh_tokenをもらえる。

#アクセストークンの取得
##仕様
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/a5fb3521-c11d-8e6c-2c48-2c27eb323a1c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/f3d69282-e8c2-e8e9-2b3a-9c2618ae835b.png)

ポイント１：POSTメソッド。GETメソッドだとNG
ポイント２：ヘッダーに「Content-Type: application/x-www-form-urlencoded」を設定。設定しないまたはJSONを設定するとNG。

##サンプルコード
```Test.java
        String url = "https://oauth2.googleapis.com/token";

		CloseableHttpClient httpclient = HttpClients.createDefault();

		HttpPost request = new HttpPost(url);
		List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
		parameters.add(new BasicNameValuePair("code", authorizationCode)); //上記取得した認可コード
		parameters.add(new BasicNameValuePair("client_id", oAuthClientId)); //コンソールにAPI認証情報のクライアントID
		parameters.add(new BasicNameValuePair("client_secret", oAuthClientSecret)); //コンソールにAPI認証情報のクライアントシークレット
		parameters.add(new BasicNameValuePair("redirect_uri", "http://localhost:8080")); //設定した承認済みのリダイレクトURI
		parameters.add(new BasicNameValuePair("grant_type", "authorization_code")); //固定

		HttpEntity entity = new UrlEncodedFormEntity(parameters);
		request.setEntity(entity);
		
		request.setHeader("Content-Type", "application/x-www-form-urlencoded");

		CloseableHttpResponse response = httpclient.execute(request);
		if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
		    String result = EntityUtils.toString(response.getEntity(), "UTF-8");
		    System.out.println(result);
		}
		response.close();
```

レスポンスのフィールド：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/0745af22-8a00-3431-9556-b02417697253.png)

ここまでアクセストークンが取得できましたので、Googleからデータ取得はできます。
ヘッダーにアクセストークンを設定する例です。
`curl -H "Authorization: Bearer <access_token>" https://www.googleapis.com/drive/v2/files`

#リフレッシュトークンを使ってアクセストークン更新
アクセストークンが期限あります。一定期間（60分）を経過すると、無効になります。このとき、再度認可コードを取得してもよいのですが、
利用者に面倒なので、リフレッシュトークンを使ってアクセストークン再発行するのは一般的です。

##仕様
アクセストークンと同じ感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/833e8dc5-888f-fbc4-3fc1-c721cacb3593.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/f962e1a2-1870-4204-b5b4-909e55804a9b.png)

##サンプルコード
```Test.java
        String url = "https://oauth2.googleapis.com/token";

		HttpPost request = new HttpPost(url);
		List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
		parameters.add(new BasicNameValuePair("refresh_token", "xxxxxxx")); //もっているリフレッシュトークン
		parameters.add(new BasicNameValuePair("client_id", oAuthClientId)); //コンソールにAPI認証情報のクライアントID
		parameters.add(new BasicNameValuePair("client_secret", oAuthClientSecret)); //コンソールにAPI認証情報のクライアントシークレット
		parameters.add(new BasicNameValuePair("redirect_uri", "http://localhost:8080")); //設定した承認済みのリダイレクトURI
		parameters.add(new BasicNameValuePair("grant_type", "refresh_token")); //固定

		HttpEntity entity = new UrlEncodedFormEntity(parameters);
		request.setEntity(entity);
		
		request.setHeader("Content-Type", "application/x-www-form-urlencoded");

		CloseableHttpClient httpclient = HttpClients.createDefault();
		CloseableHttpResponse response = httpclient.execute(request);
		if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
		    String result = EntityUtils.toString(response.getEntity(), "UTF-8");
		    System.out.println(result);
		}
		response.close();
```

レスポンス例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/d7070d9b-917d-d250-0c8e-40a34b20923f.png)

サンプルの通り、リフレッシュトークンがないので、リフレッシュトークンも無効になったら、認可コード取得からやり直すとなります。

参考URL：https://developers.google.com/identity/protocols/OAuth2WebServer

以上