ユーザープロファイル情報を取得する
Amazonユーザープロファイルへのアクセスをユーザーがウェブサイトに許可すると、アクセストークンが返されます。サーバー側のスクリプトで認可コードグラントを使用してアクセストークンをリクエストしている場合、アクセストークンはアクセストークンレスポンスで返されます。
ブラウザベースのアプリで、クライアント側でアクセストークンが必要な場合は、options.pkce=true
を設定し、認可コードを指定してretrieveToken
APIを呼び出すことによってアクセストークンを取得できます。このAPIが機能するには、クライアントでCookieを有効にするとともに、authorize
の呼び出しをretrieveToken
の呼び出しと同じドメインで行う必要があります。許可されたユーザーデータにアクセスするには、HTTPSを使用して、受け取ったアクセストークンをLogin with Amazonに送信します。
そのレスポンスとして、Login with Amazonは該当するユーザープロファイルデータを返します。ここで返されるプロファイルデータは、アクセスをリクエストする際にscope
で指定したスコープによって決まります。アクセストークンに従って、そのスコープにアクセスできるようになります。
JavaScript用のLogin with Amazon SDKを使用する
JavaScript用のLogin with Amazon SDKでは、amazon.Login.retrieveProfile
を使用してアクセストークンをプロファイルと交換します。次に例を示します。
<script type="text/javascript">
document.getElementById('LoginWithAmazon').onclick = function() {
setTimeout(window.doLogin, l);
return false;
};
window.doLogin = function() {
options = {};
options.scope = 'profile';
options.pkce = true;
amazon.Login.authorize(options, function(response) {
if ( response.error ) {
alert('oauthエラー' + response.error);
return;
}
amazon.Login.retrieveToken(response.code, function(response) {
if ( response.error ) {
alert('oauthエラー' + response.error);
return;
}
amazon.Login.retrieveProfile(response.access_token, function(response) {
alert('こんにちは。' + response.profile.Name);
alert('あなたのEメールアドレス:' + response.profile.PrimaryEmail);
alert('あなたの一意のID:' + response.profile.CustomerId);
if ( window.console && window.console.log )
window.console.log(response);
});
});
});
};
</script>
amazon.Login.retrieveProfile
関数は、success
、error
、profile
の3つのパラメーターを返します。success
は、呼び出しが成功したかどうかを表します。error
は、エラーが発生した場合にエラーメッセージを返します。エラーが発生しなければ、profile
にユーザーのプロファイルが返されます。このメソッドとパラメーターの詳細については、JavaScript用のLogin with Amazon SDKリファレンスを参照してください。
サーバー側でprofileエンドポイントを呼び出す
profile
エンドポイントを直接呼び出す場合、アクセストークンを指定するには3とおりの方法(クエリパラメーターとして指定する、Bearerトークンとして指定する、HTTPヘッダーでx-amz-access-token
を使用する)があります。次に例を示します。
https://api.amazon.com/user/profile?access_token=AtzaIIQEBLjAsAhRmHjNgHpi0UDme37rR6CuUpSR...
GET /user/profile HTTP/1.1
Host: api.amazon.com
Date: Wed, 0l Jun 20ll l2:00:00 GMT
Authorization: Bearer Atza|IQEBLjAsAhRmHjNgHpi0U-Dme37rR6CuUpSR...
GET /user/profile HTTP/1.1
Host: api.amazon.com
Date: Wed, 0l Jun 20ll l2:00:00 GMT
x-amz-access-token: Atza|IQEBLjAsAhRmHjNgHpi0U-Dme37rR6CuUpSR...
Login with Amazonは、コンテンツタイプとしてapplication/json
のみを、コンテンツ言語としてen-us
のみをサポートします。明記されていない場合でも、Login with Amazonではこのコンテンツタイプと言語をデフォルトで使用します。
GET /user/profile HTTP/1.1
Host: api.amazon.com
Date: Wed, 0l Jun 20ll l2:00:00 GMT
x-amz-access-token: Atza|IQEBLjAsAhRmHjNgHpi0U-Dme37rR6CuUpSR...
Accept: application/json
Accept-Language: en-US
以下の各言語の詳細なコードサンプルは次のようになります。
サーバー側のアプリで、/handle_login.php
に対するリクエストを処理し、アクセストークンとプロファイルREST APIを使用してプロファイル情報を取得します。次のコードサンプルを使用する場合は、YOUR-CLIENT-ID
をアプリの登録時に取得したクライアントIDに置き換えます。
// アクセストークンがこちらに属していることを検証する
$c = curl_init('https://api.amazon.com/auth/o2/tokeninfo?access_token=' . urlencode($_REQUEST['access_token']));
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
$r = curl_exec($c);
curl_close($c);
$d = json_decode($r);
if ($d->aud != 'YOUR-CLIENT-ID') {
// アクセストークンがこちらに属していない
header('HTTP/1.1 404 Not Found');
echo 'ページが見つかりません';
exit;
}
// アクセストークンをユーザープロファイルと交換する
$c = curl_init('https://api.amazon.com/user/profile');
curl_setopt($c, CURLOPT_HTTPHEADER, array('Authorization: bearer ' . $_REQUEST['access_token']));
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
$r = curl_exec($c);
curl_close($c);
$d = json_decode($r);
echo sprintf('%s %s %s', $d->name, $d->email, $d->user_id);
サーバー側のアプリで、/handle_login.php
に対するリクエストを処理し、アクセストークンとプロファイルREST APIを使用してプロファイル情報を取得します。次のコードサンプルを使用する場合は、YOUR-CLIENT-ID
をアプリの登録時に取得したクライアントIDに置き換えます。
require "rubygems"
require "net/https"
require "json"
require "uri"
...
# アクセストークンがこちらに属していることを検証する
uri = URI.parse("https://api.amazon.com/auth/o2/tokeninfo?access_token=" + URI.encode(access_token))
req = Net::HTTP::Get.new(uri.request_uri)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = http.request(req)
decode = JSON.parse(response.body)
if decode['aud'] != 'YOUR-CLIENT-ID'
# アクセストークンがこちらに属していない
raise "無効なトークン"
end
# アクセストークンをユーザープロファイルと交換する
uri = URI.parse("https://api.amazon.com/user/profile")
req = Net::HTTP::Get.new(uri.request_uri)
req['Authorization'] = "bearer " + access_token
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = http.request(req)
decode = JSON.parse(response.body)
puts sprintf "%s %s %s", decode['name'], decode['email'], decode['user_id']
サーバー側のアプリで、/handle_login.php
に対するリクエストを処理し、アクセストークンとプロファイルREST APIを使用してプロファイル情報を取得します。次のコードサンプルを使用する場合は、YOUR-CLIENT-ID
をアプリの登録時に取得したクライアントIDに置き換えます。
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.fluent.Content;
import org.apache.http.client.fluent.Request;
import java.net.URLEncoder;
import java.util.Map;
...
// アクセストークンがこちらに属していることを検証する
Content c = Request.Get("https://api.amazon.com/auth/o2/tokeninfo?access_token=" + URLEncoder.encode(access_token, "UTF-8"))
.execute()
.returnContent();
Map m = new ObjectMapper().readValue(c.toString(), new TypeReference>(){});
if (!"YOUR-CLIENT-ID".equals(m.get("aud"))) {
// アクセストークンがこちらに属していない
throw new RuntimeException("無効なトークン");
}
// アクセストークンをユーザープロファイルと交換する
c = Request.Get("https://api.amazon.com/user/profile")
.addHeader("Authorization", "bearer " + access_token)
.execute()
.returnContent();
m = new ObjectMapper().readValue(c.toString(), new TypeReference>(){});
System.out.println(String.format("%s %s %s", m.get("name"), m.get("email"), m.get("user_id")));
サーバー側のアプリで、/handle_login.php
に対するリクエストを処理し、アクセストークンとプロファイルREST APIを使用してプロファイル情報を取得します。次のコードサンプルを使用する場合は、YOUR-CLIENT-ID
をアプリの登録時に取得したクライアントIDに置き換えます。
import pycurl
import urllib
import json
import StringIO
...
b = StringIO.StringIO()
# アクセストークンがこちらに属していることを検証する
c = pycurl.Curl()
c.setopt(pycurl.URL, "https://api.amazon.com/auth/o2/tokeninfo?access_token=" + urllib.quote_plus(access_token))
c.setopt(pycurl.SSL_VERIFYPEER, 1)
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.perform()
d = json.loads(b.getvalue())
if d['aud'] != 'YOUR-CLIENT-ID' :
# アクセストークンがこちらに属していない
raise BaseException("無効なトークン")
# アクセストークンをユーザープロファイルと交換する
b = StringIO.StringIO()
c = pycurl.Curl()
c.setopt(pycurl.URL, "https://api.amazon.com/user/profile")
c.setopt(pycurl.HTTPHEADER, ["Authorization: bearer " + access_token])
c.setopt(pycurl.SSL_VERIFYPEER, 1)
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.perform()
d = json.loads(b.getvalue())
print "%s %s %s"%(d['name'], d['email'], d['user_id'])
ユーザープロファイルのレスポンス
アクセストークンが有効な場合、ユーザーのプロファイルデータはJSON形式のHTTPレスポンスとして返されます。次に例を示します。
HTTP/1.1 200 OK
x-amzn-RequestId: 0f6bef6d-705c-lle2-aacb-93e6bf26930l
Content-Type: application/json
Content-Language: en-US
Content-Length: 85
{
"user_id": "amznl.account.K2LI23KL2LK2",
"email":"mhashimoto-04@plaxo.com",
"name" :"Mork Hashimoto",
"postal_code": "98052"
}
Request-Id
はログ用であり、無視して構いません。Login with Amazonチームと問題のトラブルシューティングを行う場合、Request-Id
の提供をAmazonチームに求められることがあります。
プロファイルリクエストの処理中に問題が発生すると、HTTPエラーが返されます。アクセスリクエストのエラーコードには、次のものがあります。
ステータス | エラーコード | 説明 |
---|---|---|
200 | 成功 |
リクエストに成功しました。 |
400 | invalid_request |
リクエストに必須パラメーターが含まれていないか、形式に誤りがあります。 |
400 | invalid_token |
提供されたアクセストークンは、期限切れ、取り消し済み、形式の誤り、またはそのほかの理由により無効です。 |
401 | insufficient_scope |
提供されたアクセストークンでは、必要なスコープにアクセスできません。 |
500 | ServerError |
サーバーでランタイムエラーが発生しました。 |
エラーコードに加えて、詳しい情報を含むJSONペイロードが返されることもあります。次に例を示します。
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Content-Length: 74
{
"error": "機械可読なエラーコード",
"error_description": "人が読み取れる形式のエラーの説明",
"request_id": "bef0c2f8-e292-4l96-8c95-8833fbd559df"
}
サーバーにユーザー情報を取り込む
Amazonから取得したユーザープロファイル情報をバックエンドサーバーに取り込むことで、サインインしたユーザーを特定したり、ユーザーのアカウントをさらにカスタマイズしたりできます。これを安全に行うため、HTTPSを使用してクライアントからサーバーにアクセストークンを送信します。次にサーバー側からそのアクセストークンを使用して、profile
エンドポイントを呼び出します。詳細と各種言語のコードサンプルについては、サーバー側でprofileエンドポイントを呼び出すを参照してください。Login with Amazonからは、user_id
、email
、name
、postal_code
などの値を含むユーザープロファイルレスポンスが返されるので、それをサーバーに保存できます。
この手順を踏むことで、サーバーに保存したプロファイルデータを、クライアントにサインインしているユーザーに確実に対応付けることができます。バックエンドにおけるユーザーアカウントの結合と管理の詳細については、既存のアカウントシステムと統合するを参照してください。