セルフサービスマシンツーマシン

ビジネスケースがAPIやバックエンドサーバーなどの非インタラクティブなオーディエンスにサービスを提供する場合は、マシンツーマシン(M2M)構成でオンボードします。

ユースケース

次の場合は、M2Mオンボーディングパスを使用します。

  • サービスツーサービス通信をサポートする

  • 保護されたリソースまたはAPIにアクセスする必要があるサーバー上でスケジュールされたジョブまたはcronタスクが実行されている

  • IoTデバイスがバックエンドサービスまたはAPIと通信できるようにする

  • ユーザーの関与なし、またはユーザートークンの有効期限が切れた後に他のAPIレイヤーと通信する必要があるAPIレイヤーがある

  • ユーザーが認証される前に呼び出す必要がある特権APIがある(つまり、Auth0テナントのアクションまたはカスタムデータベーススクリプトから)

  • APIゲートウェイを使用してバックエンドサービスを管理する

  • 非対話型アプリケーションや、daemonやバックエンドサービスなど人間との対話を含まないその他のツールを使用またはサポートする

このガイドの使用方法

このガイドは、Auth0でM2M実装を作成するための経路です。検討すべき考慮事項、ベストプラクティス、概念を提供します。

  • 「アーキテクチャ」では、ソフトウェア開発ライフサイクルと既存のインフラストラクチャをサポートするようにAuth0を構成することをお勧めします。

  • 「アカウントの作成」では、Auth0でAPIインスタンスを作成する手順と、マシンツーマシン認証に必要な認証フロー(または権限許可)をサポートするアプリケーションを作成する手順を示します。

  • 「認証」では、認証に使用する必要がある権限許可と、設定できるアクセストークンおよびアクセス許可(またはスコープ)について説明します。

  • 「ブランディング」では、証明書の管理方法に応じて、カスタムドメインの構成方法に関する情報をどこで入手できるかをアドバイスします。

  • 「デプロイメントの自動化」では、デプロイメントを支援するツールについて読むことができます。

  • 「品質保証」では、ユニットテストと、Auth0 Dashboardで提供される準備チェックについて詳しく説明します。

アーキテクチャ

Auth0アカウントとテナント、またはAuth0サービスのグループと構造を構成する前に、既存のエコシステムでAuth0の機能を最大限に活用できるように既存のインフラストラクチャのマップを作成します。

一般的なシナリオで説明したように、Auth0を構成する前に、アプリケーションドメイン、ネットワークドメイン、またはM2Mデバイスドメインに他の非対話型テクノロジーを考慮する必要があるかもしれません。M2Mシナリオの例を確認するには、「サーバー + API」を参照してください。Nodeを使ったハンズオン・ラボやAPIのデプロイをテストするには、GitHubリポジトリにアクセスしてください。

現在の技術スタックを視覚化したり、Auth0が現在のソフトウェア開発ライフサイクル(SDLC)にどのように適合するかを計画したりできます。これは、必要なテナントの数を判断するのに役立ちます。

考慮事項

新しいアカウントを作成したり、最初のテナントを構成したりする前に、次の点を考慮する必要があります。

  • 特定のエンドポイントを呼び出すためにAPIを分割またはグループ化する方法。

    • これにより、アクセストークンのオーディエンスやその他のクレームが決定されます。

  • リソースのサードパーティコンシューマーは、呼び出しごとにアクセストークンを要求する場合があります。呼び出しが多すぎると、レート制限に影響する可能性があります。

アカウントの作成

アーキテクチャの計画ができたので、Auth0アカウントとテナントを構成します。Auth0サービスにサインアップすると、最初のテナントが作成されます。ここで、Auth0アセット、サービス、およびリソースを構成します。サインアップして開始します。

開始する前に

Auth0 Dashboard内またはAuth0 Management APIを使用して、以下を作成します。

  • APIを表すAPI

  • クライアントの資格情報フローを使用するM2Mアプリケーション

アカウントを作成する前に、構成情報を計画することをお勧めします。

  • テナント名には、Auth0ドメインにおけるロールが含まれます。名前を決める前に、「テナントの特性」をお読みください。

  • ユースケースに必要となるAuth0機能を検討します。機能によっては、プロフェッショナルおよびエンタープライズプラン以外では、ご利用いただけません。

  • 開発、ステージング、本番など、複数の環境に対応する必要があるか決定します。詳細については、「複数の環境をセットアップする」をお読みください。

  • テナント内に登録するサードパーティアプリケーションが関連するユースケースがある場合、OIDCクライアント登録の仕様に基づいて、動的アプリケーション登録を使用することができます。

  • バックエンドサービスおよびAPIライブラリー」をお読みのうえ、クイックスタートをお試しください。

テナントのプロビジョニング

アーキテクチャの計画ができたので、Auth0アカウントとテナントを構成します。

APIの登録

このセクションでは、Auth0でAPIを作成します。

まず、Auth0 DashboardでAPI用のインスタンスを作成します。

  1. 指示に従ってAPIを登録します。

[Authentication(認証)]セクションで、M2M認証用のAPI設定を構成します。

アプリケーションの関連付け

アプリケーションとAPIの間に関連付けを作成して、アプリケーションがAPIからアクセストークンを要求できるようにする必要があります。クライアント権限許可について詳細は、認証のセクションで説明します。

DashboardでAPIを作成する場合、Auth0は自動的にテストアプリケーションを生成し、APIに関連付けます。

  1. [Auth0 Dashboard] > [Applications(アプリケーション)]に移動します。

  2. API作成時に作成したテストM2Mテストアプリケーションを選択します。

  3. [API]ビューに切り替え、このアプリケーションに対して有効にしたいAPIを見つけます。

  4. [Authorize(認可)]トグルを有効にし、右側にある矢印ボタンを選択してカードを展開します。

  5. [Update(更新)]を選択します。

    [Dashboard] > [Applications(アプリケーション)] > [APIs]

認証

あるAPIを別のAPIから呼び出す場合、または認証されたユーザーコンテキストがない状況から呼び出す場合は、ユーザーではなくアプリケーションを認可する方法が必要です。これは、アプリケーションが認証され(client_idclient_secretを使用)、1回の呼び出しで認可される1ステッププロセスです。

非対話型アプリケーションまたはサービスの認証では、クライアント権限許可または認証フローを選択する必要があります。Auth 2.0クライアントの資格情報フローは、人間の介入を必要とせず、M2Mアプリケーションに最適です。

開始する前に

Auth0 DashboardやManagement APIで、以下のことを行います。

  • クライアントの資格情報フローを使用するようにアプリケーションを設定します。

  • M2Mアクセストークンのスコープを更新します。

認証方式を構成する前に以下のことを行います。

  • マシンツーマシン認証については、「クライアントの資格情報フロー」を参照してください。これは非対話型の認証と認可のワークフローです。

  • APIのアクセスレベルを決定します。これは、APIを作成する際に構成するスコープや権限を決めるのに役立ちます。

クライアントの資格情報フローを構成する

Auth0 DashboardまたはManagement APIを使用して、アクセストークンと引き換えにクライアント資格情報を提供する認証フローを設定できます。

Auth0 DashboardまたはManagement APIを使用するには、「付与タイプを更新する」の手順に従ってください。

M2Mアクセストークン

トークンベースの認証では、非対話型クライアントは、Authentication APIトークンエンドポイントへの呼び出しでclient_idclient_secretを提供し、アクセストークンを取得します。このアクセストークンにより、保護されたAPIへのアクセスが許可されます。

デフォルトのプロファイルまたは形式は、2つのトークンプロファイルに関連付けられたAuth0トークンプロファイルです。トークンプロファイルをRFC 9068に変更することもできます。詳細については、「アクセストークンのプロファイル」をお読みください。トークンが有効であることを確認するために、APIは署名アルゴリズムをチェックします。デフォルトの署名アルゴリズムは、キーベースのアルゴリズムであるRSA256です。

/oauth/tokenエンドポイントへの要求は、次のサンプルのようになります。


curl --request POST \
  --url 'https://{yourDomain}/oauth/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data client_id=YOUR_CLIENT_ID \
  --data client_secret=YOUR_CLIENT_SECRET \
  --data audience=YOUR_API_IDENTIFIER

Was this helpful?

/
var client = new RestClient("https://{yourDomain}/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Was this helpful?

/
package main

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

func main() {

	url := "https://{yourDomain}/oauth/token"

	payload := strings.NewReader("grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("content-type", "application/x-www-form-urlencoded")

	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.post("https://{yourDomain}/oauth/token")
  .header("content-type", "application/x-www-form-urlencoded")
  .body("grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER")
  .asString();

Was this helpful?

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

var options = {
  method: 'POST',
  url: 'https://{yourDomain}/oauth/token',
  headers: {'content-type': 'application/x-www-form-urlencoded'},
  data: new URLSearchParams({
    grant_type: 'client_credentials',
    client_id: 'YOUR_CLIENT_ID',
    client_secret: 'YOUR_CLIENT_SECRET',
    audience: 'YOUR_API_IDENTIFIER'
  })
};

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 = @{ @"content-type": @"application/x-www-form-urlencoded" };

NSMutableData *postData = [[NSMutableData alloc] initWithData:[@"grant_type=client_credentials" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&client_id=YOUR_CLIENT_ID" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&client_secret=YOUR_CLIENT_SECRET" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"&audience=YOUR_API_IDENTIFIER" dataUsingEncoding:NSUTF8StringEncoding]];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/oauth/token"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[request setAllHTTPHeaderFields:headers];
[request setHTTPBody:postData];

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}/oauth/token",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER",
  CURLOPT_HTTPHEADER => [
    "content-type: application/x-www-form-urlencoded"
  ],
]);

$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("")

payload = "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER"

headers = { 'content-type': "application/x-www-form-urlencoded" }

conn.request("POST", "/{yourDomain}/oauth/token", payload, 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}/oauth/token")

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

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/x-www-form-urlencoded'
request.body = "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&audience=YOUR_API_IDENTIFIER"

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

Was this helpful?

/
import Foundation

let headers = ["content-type": "application/x-www-form-urlencoded"]

let postData = NSMutableData(data: "grant_type=client_credentials".data(using: String.Encoding.utf8)!)
postData.append("&client_id=YOUR_CLIENT_ID".data(using: String.Encoding.utf8)!)
postData.append("&client_secret=YOUR_CLIENT_SECRET".data(using: String.Encoding.utf8)!)
postData.append("&audience=YOUR_API_IDENTIFIER".data(using: String.Encoding.utf8)!)

let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/oauth/token")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

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?

/

応答は、次のサンプルのようになります。

HTTP/1.1 200 OK
Content-Type: application/json
{
  "access_token":"eyJz93a...k4laUWw",
  "token_type":"Bearer",
  "expires_in":86400
}

Was this helpful?

/

トークンの有効期限

アクセストークンには、トークンの有効期間の制限があります。通信はバックチャネルで行われるため、リフレッシュトークンを使用してセッションを延長することはできません。アクセストークンの有効期限を1時間に設定することを検討してください。特定の環境に合わせて、セキュリティとパフォーマンスのバランスを取る必要がある場合があります。詳細については、「アクセストークンのライフタイムを更新する」を参照してください。

Scopes(スコープ)

非対話型クライアントまたはサービスがAPIを呼び出す前に、APIが許可する権限またはスコープを定義する必要があります。Auth0 Dashboardでスコープを設定して、Authentication APIへの認証要求に含めることができます。APIスコープの使用方法についてその他の例は、「APIスコープ」を参照してください。

スコープを構成するには、Auth0 DashboardのAPIの権限を追加の手順に従うか、Management APIに提供されているサンプルを使用します。

ブランディング

非対話型クライアントやバックチャネルで動作するサービスを提供する場合でも、既存のブランドの外観と雰囲気に合わせてエクスペリエンスをカスタマイズできます。

カスタムドメイン

Auth0は、/authorizeエンドポイントを呼び出してアクセストークンを要求するときに、カスタムドメインの使用をサポートします。

M2Mオンボーディング - カスタムドメイン

Auth0ダッシュボードでは、次の操作を行う必要があります。

  • Auth0サービスで使用する前に、ドメインを登録して検証します。

  • 独自の証明書を管理するか、Auth0管理の証明書を使用するかを決定します。証明書の詳細については、「証明書管理のオプション」をお読みください。

  • 自己管理証明書に使用するTLS(SSL)のバージョンと暗号がAuth0でサポートされていることを確認します。詳細ついては、「TLS(SSL)のバージョンと暗号」をお読みください。

  1. Auth0管理の証明書を使用してカスタムドメインを構成するには、「Auth0管理証明書を使ってカスタムドメインを構成する」の手順に従ってください。

    1. 独自の証明書を管理する場合は、「自己管理証明書を使ってカスタムドメインを構成する」の手順に従ってください。

  2. カスタムドメインを使用したAPI構成」を確認してください。カスタムドメインを組み込むには、API設定を調整する必要がある場合があります。

カスタムドメインで問題が発生した場合は、「カスタムドメインのトラブルシューティング」を確認してください。

デプロイメント自動化

Auth0は、使用可能なデプロイメント自動化アプローチに関していくつかの異なるオプションをサポートしており、それぞれを組み合わせて使用することができます。

ベストプラクティス

デプロイメントの自動化をどのように構成する場合でも、デプロイメント前にカスタムコードとアクションの単体テストを実行し、デプロイメント後にテナントに対して統合テストを実行することをお勧めします。

CLIツールのデプロイ

アーキテクチャセクションで推奨されているように、開発、テスト、および本番用のAuth0テナントを用意する必要があります。これらのテナントは、品質チェックとテストのために同一の構成を共有する必要がありますが、環境間で構成が一致しないためにエラーが発生する可能性があります。たとえば、各環境には異なるクライアントIDとクライアントシークレットがあります。

これらの不一致エラーを軽減するには、Deploy CLIツールを使用して、Auth0インスタンスを既存のCI/CDパイプラインと統合できます。動的なキーワード置換を使用すると、同様の構成を共有するテナントの環境変数を置き換えることができます。詳細については、「Deploy CLIツール」と「キーワードの置換」をご覧ください。

Real-time Webtask Logs拡張機能

Real-time Webtask Logs拡張機能は、console.log出力やその他の例外など、カスタムコードのすべてのログをリアルタイムで表示します。Auth0 Actionsまたはその他のカスタムロジックを使用している場合は、この拡張機能を使用してデバッグとトラブルシューティングを行うことができます。インストールと構成の詳細については、「Real-time Webtask Logs拡張機能」をご覧ください。

品質保証

品質保証は、本番稼働前に問題を特定する上で重要です。プロジェクトの性質に応じて、Auth0との統合の一環として検討する必要があるさまざまな種類の品質保証テストがあります。

  • 予期しない本番負荷にさらされた場合、APIはどのように機能しますか?

  • サードパーティアプリケーションによってレート制限はどのように影響を受けますか?

Auth0のウィジェットやユニバーサルログインのような機能を使用していない場合、多くのブラウザーやデバイスで、ユーザビリティやアクセシビリティのベストプラクティスをすぐに利用することはできません。機能要件が満たされ、予期しないイベントが正しく処理されるように、アプリケーションとAuth0の統合をテストするためのガイダンスと、Auth0 Actionsなどの個々の拡張モジュールのユニットテストが提供されています。また、Auth0の「ペネトレーションテストポリシー」を確認し、「負荷テストポリシー」と組み合わせて活用できるモックテストを完了して、予期しない負荷の下でもアプリケーションを確実に動作させることをお勧めします。

ユニットテスト

ユニットテストは、Auth0 Actionsなどの拡張性のユニットを検証します。カスタムコードを使用している場合は、デプロイメント前にテストフレームワーク(Mochaなど)を使用して追加コードをテストすることをお勧めします。

モックテスト

Auth0の負荷テストポリシーと負荷テストの必要性のバランスを取るために、Auth0のエンドポイントのモックテストを作成するのが一般的です。これは、テストを制約することなく、構成が想定されたインターフェイスでの動作を確認するための有効な方法です。MockServerJSON Server、さらにPostmanなどのツールも使用できます。

Deployment(デプロイ)

デプロイメントとモニタリング」のセクションでは、デプロイメントのベストプラクティスに関するガイダンスを提供しています。「導入前の確認事項」、特に組み込みの「Auth0 Dashboard準備状況チェック」を確認することをお勧めします。

準備チェックを確認するには、[Auth0 Dashboard]>[Run Readiness Checks(準備状況チェックの実行)]を選択し、テナント名と環境タグの下のドロップダウンメニューを選択します。

Auth0 Dashboard > Readiness Checklist

フィルターを使用して、選択したアプリケーションに準備状況チェックを適用できます。これらのチェックは、構成済みのAPIには適用されません

特定の構成に適用されないチェックについては、[Dismiss(閉じる)]を選択して最終結果から削除できます。

本番稼働前に最終チェックの「デプロイメントのベストプラクティス」を確認し、ログを利用してサービスを監視することをお勧めします。

もっと詳しく