IDプロバイダーAPIを呼び出す

FacebookやGitHubなどの外部IDプロバイダー(IdP)でユーザーを正常に認証すると、多くの場合、IdPはAuth0に返すユーザープロファイルにアクセストークンを含めます。

このトークンを取得して使用し、IdPのAPIを呼び出すことができます。

これから説明する手順は、コードがバックエンドまたはフロントエンドのどちらで実行されるかによって異なります。

  • コードがバックエンドで実行される場合、サーバーがシークレットを安全に保存できると想定できます(後でわかるように、バックエンドシナリオではシークレットを使用します)。その場合は、この記事の[backend section(バックエンドのセクション)]に進んでください。

  • コードがフロントエンドで実行される場合(たとえば、SPA、ネイティブデスクトップ、モバイルアプリなど)、アプリは資格情報を安全に保持できないため、別のアプローチに従う必要があります。その場合は、この記事の[frontend section(フロントエンド)]に進んでください。

バックエンドから

ユーザーを認証すると、IdPは通常、Auth0に返すユーザープロファイルにアクセストークンを含めます。

セキュリティとコンプライアンス上の理由から、Auth0はこのトークンをユーザープロファイルの一部としてアプリに送信しません。これを取得するには、Auth0 Management APIにアクセスして、ユーザーの完全なプロファイルを取得する必要があります。

  1. [Auth0 Management API]を呼び出すためのアクセストークンを取得します。

  2. ステップ1で取得したアクセストークンを使用して、Auth0 Management APIの[Get Users by ID endpoint(IDエンドポイントによるユーザー取得)]を呼び出します。このエンドポイントは、IdPアクセストークンを含む完全なユーザープロファイルを返します。

  3. 応答からIdPアクセストークンを抽出し、それを使用してIdPのAPIを呼び出します。

ステップ1:トークンを取得

Management APIを呼び出すには、アクセストークンが必要です。

Management APIのテストアプリケーションを作成

Management APIv2 Token(Management APIv2トークン)を初めて要求する場合は、Management APIを呼び出すために使用できるアプリケーションを作成して構成する必要があります。

  1. [Auth0 Dashboard]>[Applications(アプリケーション)]>[API]に移動して、[Auth0 Management API]を選択します。

  2. [API Explorer(API エクスプローラー)]ビューを選択し、[Create & Authorize a Test Application(テストアプリケーションの作成と承認)]をクリックします。

これにより、新しいアプリケーションが作成され、Management APIのすべてのスコープが付与されます。つまり、このアプリケーション用に生成されたトークンは、すべてのManagement APIエンドポイントにアクセスできるようになります。

ボタンが表示されない場合

このボタンが表示されない場合は、Management APIに少なくとも1つの認可済みアプリケーションがすでに存在しています。既存のアプリケーションのスコープを更新して使用するか、以下の手順で新しいものを作成してください。

  1. [Auth0 Dashboard]>[Applications(アプリケーション)]>[Applications(アプリケーション)]に移動して、[Create Application(アプリケーションの作成)]を選択します。

  2. [Machine to Machine Applications(マシンツーマシンアプリケーション)]を選択して[Create(作成)]をクリックします。

  3. [Select an API(APIの選択)]ドロップダウンから [Auth0 Management API]を選択します。

  4. 必要なスコープを有効にして、[Authorize(認可)]を選択します。

  5. APIビューを選択して、Auth0 Management APIを有効に設定します。

登録済みのAuth0 Management APIからスコープを付与または削除するには、[Machine to Machine Applications(マシンツーマシンアプリケーション)]ビューを選択します。

アプリケーションに付与されたスコープを編集

Management APIトークンの取得

これで構成が完了し、Management APIトークンを取得する準備が整いました。

  1. 登録済みのAuth0 Management APIから、[Test(テスト)]ビューを選択します。

  2. ドロップダウンから[Application(アプリケーション)]を選択し、カスタマイズされた変数を使用してすぐに使用できるスニペットを事前に設定します。

  3. スニペットの優先言語を選択し、コピーして実行します。

  4. 応答からaccess_tokenプロパティを抽出します。これは、Management APIにアクセスするために使用します。

スニペットの役目

スニペットは、POST操作をAuth0の認証APIの/oauth/tokenエンドポイントOAuth 2.0クライアント資格情報付与を使って実行します。これはマシンツーマシンプロセスがAPIへのアクセス時に使用する付与です。フローの詳細については、「Client Credentials Flow(クライアントの資格情報フロー)」を参照してください。

トークンの有効期限

デフォルトでは、受け取ったトークンの有効期限は24時間(86,400秒)です。これを変更するには、

  1. [Auth0 Dashboard]>[Applications(アプリケーション)]>[API]に移動して、[Auth0 Management API]を選択します。

  2. [Settings(設定)]ビューを選択し、[Token Expiration (Seconds)(トークンの有効期限(秒))]フィールドを見つけて新しい値を入力し、[Save(保存)]をクリックします。設定できる最大値は2,592,000秒(30日)ですが、デフォルト値のままにしておくことをお勧めします。

次に生成するトークンでは、更新された有効期限が使用されます。

ステップ2:完全なユーザープロファイルの取得

ユーザーのプロファイルを取得するには、前のセクションで抽出したアクセストークンを使用して、Management APIの[Get a User endpoint(ユーザーエンドポイントの取得)]を呼び出します。


curl --request GET \
  --url 'https://{yourDomain}/api/v2/users/%7BuserId%7D' \
  --header 'authorization: Bearer {yourAccessToken}'

Was this helpful?

/
var client = new RestClient("https://{yourDomain}/api/v2/users/%7BuserId%7D");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer {yourAccessToken}");
IRestResponse response = client.Execute(request);

Was this helpful?

/
package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "https://{yourDomain}/api/v2/users/%7BuserId%7D"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("authorization", "Bearer {yourAccessToken}")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}

Was this helpful?

/
HttpResponse<String> response = Unirest.get("https://{yourDomain}/api/v2/users/%7BuserId%7D")
  .header("authorization", "Bearer {yourAccessToken}")
  .asString();

Was this helpful?

/
var axios = require("axios").default;

var options = {
  method: 'GET',
  url: 'https://{yourDomain}/api/v2/users/%7BuserId%7D',
  headers: {authorization: 'Bearer {yourAccessToken}'}
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});

Was this helpful?

/
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer {yourAccessToken}" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/api/v2/users/%7BuserId%7D"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];
[request setAllHTTPHeaderFields:headers];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];

Was this helpful?

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://{yourDomain}/api/v2/users/%7BuserId%7D",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer {yourAccessToken}"
  ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

Was this helpful?

/
import http.client

conn = http.client.HTTPSConnection("")

headers = { 'authorization': "Bearer {yourAccessToken}" }

conn.request("GET", "/{yourDomain}/api/v2/users/%7BuserId%7D", headers=headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))

Was this helpful?

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://{yourDomain}/api/v2/users/%7BuserId%7D")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Get.new(url)
request["authorization"] = 'Bearer {yourAccessToken}'

response = http.request(request)
puts response.read_body

Was this helpful?

/
import Foundation

let headers = ["authorization": "Bearer {yourAccessToken}"]

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/api/v2/users/%7BuserId%7D")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()

Was this helpful?

/

次の値を置き換えます:

  • {userId}:IdPのAPIを呼び出すユーザーのID。

  • {yourAccessToken}:前のセクションで抽出したアクセストークン。

ユーザーIDを見つけるには

  • 実装の場合には、IDトークンsubクレームからユーザーIDを抽出するか、認証APIの/userinfoエンドポイントを呼び出して、user_id応答プロパティからユーザーIDを抽出します。

ステップ3:IdPアクセストークンの抽出

IdPのAPIを呼び出すために使用されるアクセストークンは、ユーザーのID配列内にあります。user.identities[0].access_token.

ほとんどの場合、ユーザーのIDは1つだけですが、ユーザーが異なる接続を使用して複数回サインインしていて、[account linking(アカウントのリンク)]を使用している場合は、複数のIDが存在する可能性があります。

このサンプル応答では、ユーザーのIDが1つだけであることがわかります。google-oauth2

{
  "email": "john.doe@test.com",
  "email_verified": true,
  "name": "John Doe",
  "given_name": "John",
  "family_name": "Doe",
  "picture": "https://myavatar/photo.jpg",
  "gender": "male",
  "locale": "en",
  "updated_at": "2017-03-15T07:14:32.451Z",
  "user_id": "google-oauth2|111199914890750704174",
  "nickname": "john.doe",
  "identities": [
    {
      "provider": "google-oauth2",
      "access_token": "ya29.GlsPBCS6ahokDlgCYnVLnDKNE71HBXPEzNhAPoKJLAGKDSe1De3_xclahNcdZXoU-26hCpa8h6240TV86dtaEQ4ZWoeeZduHDq_yeu9QyQqUr--S9B2CR9YJrLTD",
      "expires_in": 3599,
      "user_id": "111199914890750704174",
      "connection": "google-oauth2",
      "isSocial": true
    }
  ],
  "created_at": "2017-03-15T07:13:41.134Z",
  "last_ip": "127.0.0.1",
  "last_login": "2017-03-15T07:14:32.451Z",
  "logins_count": 99
}

Was this helpful?

/

これで、IdPのAPIを呼び出す準備ができました。その方法の詳細については、IdPのドキュメントを参照してください。

フロントエンドから

パブリックアプリケーション(SPA、ネイティブデスクトップ、またはモバイルアプリケーション)を使用している場合は、ここを参照してください。

フロントエンドアプリを使用する場合、フロントエンドアプリは資格情報を安全に保持できないパブリックアプリケーションであるため、IdP APIを呼び出すプロセスはバックエンドプロセスとは異なります。SPAコードは表示および変更でき、ネイティブ/モバイルアプリは逆コンパイルおよび検査できるため、秘密鍵やパスワードなどの機密情報を保持することはできません。

具体的には、バックエンドプロセスの最初のステップで/oauth/tokenを呼び出すために使用するマシンツーマシンアプリケーションのClient Secret(クライアントシークレット)]を安全に保持できません。

代わりに、バックエンドのプロキシを構築し、それをAPIとしてアプリケーションに公開する必要があります。

プロキシの構築

まず、この記事のbackend section(バックエンド)セクションに記載されている手順を実装するプロセスをバックエンドに構築し、それをAPIとしてアプリケーションに公開します。

IdPのAPIは同じバックエンドプロセスから呼び出すため、アクセストークンはパブリックアプリケーションに公開されません。

次に、Authorization Code Flow with Proof Key for Code Exchange (PKCE)(コード交換用の証明キー(PKCE)を使用した認可コードフロー)を使用して、パブリックアプリケーションからプロキシAPIを呼び出します。

方法の説明

以前にこれを実装したことがないのであれば、APIを使ったシングルページアプリケーション(SPA)アーキテクチャ のシナリオが役に立つかもしれません。さまざまなシナリオを取り上げて、Auth0を構成する方法、SPAからAPIを呼び出す方法、API検証の実装方法を説明しています。Angular 2Node.jsを使ったサンプルもあります。

また、APIを使ったモバイルアプリケーションのバリエーション(サンプルではAndroidNode.jsを使用)もあります。