Oauth認証してGmailフィードを使う方法

2011年12月23日


マッシュアップサイトなど作る時に使うかも。
Oauth認証のプロセスを踏むことによって、認証したユーザーのGmail新着情報を得ることができます。日本語でも英語でもなかなか情報が出てこなくて苦戦したので、メモしておきます。言語はPHPです。

Gmailフィードとは

Gmailの新着情報をrssで取得することができるサービスです。Gmailにログインした状態でGmailフィードにアクセスすると、未読メールだけが表示されます。
 
これをマッシュアップサイトに組み込むと、閲覧者に閲覧者自身の未読メールを通知するサービスなどが作れますが、そのためには閲覧者が自分のアカウントで認証・承認する仕組みを作り、それを使ってgoogleに「この閲覧者のデータ下さい」って処理する必要があります(Oauth認証)

googleに登録する

Oauth認証を行うためには、googleのアカウント情報にアクセスして登録を行う必要があります。

ドメイン所有の確認がありますが、htmlファイルをサーバにアップロードする方法が一番手軽だと思います。尚、このファイルを消してしまうとドメイン所有がキャンセルされてしまうらしいので、消さないようにして下さい。
ドメイン所有が確認されると、ページが遷移してOauth認証に必要な情報が出てきます。

Target URL path prefix コールバック先のURL
OAuth Consumer Key カスタマーキー
OAuth Consumer Secret シークレットキー

コールバック先のURLは、アクセストークンを取得するファイル名を絶対パスで指定して下さい。以下では、login.phpがそれに当たります。

ログイン処理(login.php)

まずはログイン処理です。1つのページでリクエストトークンとアクセストークンの両方を取得するようにしています。なお、カスタマーキーとシークレットキー、コールバック先のURL(********で表示している場所)は自分の環境に置き換えて下さい。
 
login.php

<?php
session_start();
$time = time();
$oauth_consumer_key = '********'; //カスタマーキー
$consumersecret = '********'; //シークレットキー

// 最初の認証作業(リクエストトークンの要求)
if(!isset($_SESSION['gmailToken']) && !isset($_GET['oauth_token'])){
	$querystring =
		//コールバック先のURL
		'oauth_callback=' . urlencode('http://************/login.php') .
		'&oauth_consumer_key=' . $oauth_consumer_key.
		'&oauth_nonce=' . urlencode(uniqid() . uniqid()) .
		'&oauth_signature_method=HMAC-SHA1' .
		'&oauth_timestamp=' . $time .
		'&scope=' . urlencode('https://mail.google.com/mail/feed/atom/');

	$url = 'https://www.google.com/accounts/OAuthGetRequestToken';//request tokenを処理するurl

	//リクエストデータのセット
	$basestring = 'GET&' . urlencode($url) . '&' . urlencode($querystring);
	$token = '';
	$key = $consumersecret . '&' . $token;
	$signature = base64_encode(hash_hmac('SHA1', $basestring, $key, true));
	$url = 'https://www.google.com/accounts/OAuthGetRequestToken?' . $querystring . '&oauth_signature=' . urlencode($signature);

	//リクエストを変数に放りこみ、解析
	$response = file_get_contents($url);
	$ltrimarray = explode("oauth_token=", $response);
	$rtrimarray = explode("&", $ltrimarray[1]);
	$oauth_token = $rtrimarray[0];
	$ltrimarray = explode("oauth_token_secret=", $response);
	$rtrimarray = explode("&", $ltrimarray[1]);
	$oauth_token_secret = $rtrimarray[0];

	setcookie("token_secret", $oauth_token_secret, time() + 3600);//googleから遷移後に値を保持するためにcookeに保存

	header('Location:https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=' . $oauth_token);//リダイレクト
}

// googleから返ってきた後の処理(アクセストークンの処理)

if (!isset($_SESSION['gmailToken']) && isset($_GET['oauth_token']) && isset($_COOKIE["token_secret"])) {

	//リクエストデータのセット
	$querystring =
		'oauth_consumer_key=' . $oauth_consumer_key .
		'&oauth_nonce=' . urlencode('4e18ada0d45784e18ada0d495c') .
		'&oauth_signature_method=HMAC-SHA1' .
		'&oauth_timestamp=' . $time .
		'&oauth_token=' . urlencode($_GET["oauth_token"]) .
		'&oauth_verifier=' . urlencode($_GET["oauth_verifier"]) .
		'&oauth_version=' . urlencode('1.0');
	$url = 'https://www.google.com/accounts/OAuthGetAccessToken';
	$basestring = 'GET&' . urlencode($url) . '&' . urlencode($querystring);
	$token = $_COOKIE["token_secret"];
	$key = $consumersecret . '&' . $token;
	$signature = base64_encode(hash_hmac('SHA1', $basestring, $key, true));
	$url = 'https://www.google.com/accounts/OAuthGetAccessToken?' . $querystring . '&oauth_signature=' . urlencode($signature);

	//googleから返ってきたデータの取得・解析
	$response = file_get_contents($url);
	$ltrimarray = explode("oauth_token=", $response);
	$rtrimarray = explode("&", $ltrimarray[1]);
	$oauth_token = $rtrimarray[0];
	$ltrimarray = explode("oauth_token_secret=", $response);
	$rtrimarray = explode("&", $ltrimarray[1]);
	$oauth_token_secret = $rtrimarray[0];

	//そのデータをセッションに保持
	$_SESSION['gmailToken'] = array('token'=>$oauth_token,'secret'=>$oauth_token_secret);
}


//承認済みだったら画面遷移
if (isset($_SESSION['gmailToken'])) {
	header('Location:index.php');
}

アクセストークンを取得して、セッションにそのデータを保持したらheaderでindex.phpに遷移するようにしています。
 

これで、ユーザーをgoogleの認証ページに飛ばして認証手続きを行うことが出来ます。

表示処理(index.php)

ここでは、取得したアクセストークンをパラメータに放りこんでデータを要求します。なお、ログインできていなかったら(セッションに必要なデータがなかったら)戻ってログイン処理をやり直すようにしています。

index.php

<?php
// *********************************************************
// gmailへログインできてるか確認
// *********************************************************
if (!isset($_SESSION['gmailToken'])) {
	header('Location:login.php');
	exit();
} 

// *********************************************************
// gmail atomの受信部分
// *********************************************************

$oauth_consumer_key = '********'; //カスタマーキー
$consumersecret = '********'; //シークレットキー

if (isset($_SESSION['gmailToken'])) {
		$gmailToken = $_SESSION['gmailToken']; //セッションの読み込み
		//リクエストデータの準備
		$querystring =
			'oauth_consumer_key=' . $oauth_consumer_key .
			'&oauth_nonce=' . urlencode('4e18ada0d45784e18ada0d495d') .
			'&oauth_signature_method=HMAC-SHA1' .
			'&oauth_timestamp=' . $time .
			'&oauth_token=' . $gmailToken[token] .
			'&oauth_version=' . urlencode('1.0');
		$url = 'https://mail.google.com/mail/feed/atom/';
		$basestring = 'GET&' . urlencode($url) . '&' . urlencode($querystring);
		$token = $gmailToken[secret];
		$key = $consumersecret . '&' . $token;
		$signature = base64_encode(hash_hmac('SHA1', $basestring, $key, true));
		$querystring = str_replace("=", "="", $querystring);
		$querystring = str_replace("&", "", ", $querystring);
		$querystring = $querystring . "", oauth_signature="" . urlencode($signature) . """;
		$r = 'Authorization: OAuth ' . $querystring;
		//リクエストデータのセット
		$header = array($r);
		$options = array(CURLOPT_HTTPHEADER => $header, 
			CURLOPT_HEADER => false, 
			CURLOPT_URL => $url,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_SSL_VERIFYPEER => false); //SSL通信を行う時はtrue...?
		//通信開始
		$ch = curl_init();
		curl_setopt_array($ch, $options);
		$response = curl_exec($ch);
		curl_close($ch);
		
		//xmlファイルの解析
		$gmail = simplexml_load_string($response);
}

//xmlファイルの表示
	echo '<h2>'.$gmail->title . '</h2>';
	echo $gmail->fullcount . "通の新着メールがあります<br>";
	foreach ($gmail->entry as $child) {
		echo "<table class="mail">";
		echo '<tr><td width="100px">件 名</td><td><a href="'. $child->link[href] . '">' . $child->title . '</a></td></tr>';
		echo '<tr><td>受信日</td><td>' . $child->modified . '</td></tr>';
		echo '<tr><td>送信者</td><td>' . $child->author->name . '&lt;' . $child->author->email . '&gt;</td></tr>';
		echo '<tr><td>内 容</td><td>' . $child->summary . '<br /><br /></td><tr>';
		echo "</table>";
	}
?>

本番環境では、セッションの代わりにクッキーを使うのが現実的だと思います。
それでは、楽しいGmailフィードライフを!

slackチームに参加下さい

ng-onsenui2.slack.com

OnsenUI2(Angular2)について知見を共有する場です。Angular2に限ってOnsenUI2を議論できる場がなかったのでつくりました。これから使い始めるという方はぜひご参加ください。
https://ng-onsenui2.herokuapp.com/

Ionic2.slack.com

日本語情報が少ないのでこちらで知見を共有できればと思います。お陰様で参加者100名を超えました。ありがとうございます。
https://ionic2-ja.herokuapp.com