アカウントリンクに向けてアクセストークンに移行する
以前は、一部のケースで、IDトークンを使ってユーザーアカウントのリンクやリンク解除ができました。この機能は、廃止されます。今後は、すべてのケースでアクセストークンを使う必要があります。
影響のある機能
アカウントリンクにおける変更点は以下のとおりです:
Authorization
ヘッダーでIDトークンを使用できなくなりました。代わりにアクセストークンを使用する必要があります。Authorization
ヘッダーでアクセストークンを使用し、付与されたアクセス許可がupdate:users
の場合、要求のボディにはセカンダリアカウントのuser_id
またはIDトークンのいずれかを送信できます。Authorization
ヘッダーでアクセストークンを使用し、付与されたアクセス許可がupdate:current_user_metadata
の場合、要求のボディにはセカンダリアカウントのIDトークンのみ送信できます。要求の本文でセカンダリアカウントのIDトークンを送信する場合(上記2つのポイントで紹介したユースケース)、以下のような条件があります。
IDトークンは
RS256
を使用して署名される必要があります(この値は、[Dashboard]>[Clients(クライアント)]>[Client Settings(クライアントの設定)]>[Advanced Settings(高度な設定)]>[OAuth]から設定できます。IDトークンの
aud
クレームは、クライアントを特定し、アクセストークンのazp
クレームと同じ値でなければいけません。
Authorization
ヘッダーでアカウントのリンクを解除する目的です。代わりにアクセストークンを使用しなければなりません。
アカウントをリンクする方法、リンクを解除する方法はいくつかあります。次のリストで、ユースケースと変更が及ぼす影響を確認してください。
ユースケース | ステータス |
---|---|
Management APIのPOST /api/v2/users/{id}/identities エンドポイントを使用し、プライマリアカウントのIDトークンをAuthorization ヘッダーで送信する。 |
影響あり |
Management APIのPOST /api/v2/users/{id}/identities エンドポイントを使用し、(update:users スコープ付きの)アクセストークンをauthorization ヘッダーで、セカンダリアカウントのuser_id をペイロードとして送信する。 |
影響なし |
Management APIのPOST /api/v2/users/{id}/identities エンドポイントを使用し、(update:current_user_identities スコープ付きの)アクセストークンをAuthorization ヘッダーで、セカンダリアカウントのuser_id をペイロードとして送信する。 |
影響あり |
Management APIのPOST /api/v2/users/{id}/identities エンドポイントを使用し、アクセストークンをAuthorization ヘッダーで、セカンダリアカウントのIDトークンをペイロードとして送信する。 |
新しいユースケース |
auth0.Management のインスタンスを作成するために、auth0.jsライブラリーとプライマリアカウントのIDトークンを使用する。 |
影響あり |
auth0.Management のインスタンスを作成するために、auth0.jsライブラリーと(update:users スコープ付きの)アクセストークンを使用する。 |
影響なし |
auth0.Management のインスタンスを作成するために、auth0.jsライブラリーと(update:current_user_identities スコープ付きの)アクセストークンを使用する。 |
影響あり |
Management APIのDELETE /api/v2/users/{id}/identities/{provider}/{user_id} エンドポイントを使用し、プライマリアカウントのIDトークンをAuthorization ヘッダーで送信する。 |
影響あり |
Management APIのDELETE /api/v2/users/{id}/identities/{provider}/{user_id} エンドポイントを使用し、アクセストークンをAuthorization ヘッダーで送信する。 |
影響なし |
アクション
IDエンドポイントにリンクするアカウントへのすべての呼び出しを確認し、上記の脆弱なフローを利用する呼び出しを更新します。呼び出しを更新する方法には、次のようなものがあります。
クライアント側/ユーザー開始のリンクシナリオ: クライアント側のリンク シナリオの場合、
update:current_user_identities
スコープのアクセス トークンを使用してIdentitiesエンドポイントへの呼び出しを行い、ペイロード(link_with
)でセカンダリ アカウントの ID トークンを提供します。IDトークンは、OAuth/OIDC準拠のフローを通じて取得しなければなりません。サーバー側リンクシナリオ: サーバー側リンクシナリオの場合は、
update:users
スコープのアクセス トークンを使用してIdentitiesエンドポイントへの呼び出しを行い、ペイロードでセカンダリ アカウントのuser_id
を指定します。
詳細については、ユーザーアカウントのリンクを参照してください。
ユーザーアカウントをリンクする
ユーザーアカウントをリンクするには、Management APIのユーザーアカウントのリンクエンドポイントを呼び出すか、Auth0.jsライブラリを使用します。
Management APIで現在のユーザーアカウントをリンクする
一般的なユースケースは、ログインしたユーザーに、アプリを使ってのアカウントのリンクを許可する、というものです。
非推奨になる前は、プライマリユーザーのIDトークンまたはアクセストークン(update:current_user_identities
スコープを含む) を使用してManagement APIで認証し、ユーザーアカウントのリンクエンドポイントを使用できました。
次に、アクセストークン(update:current_user_identities
スコープを含む)を取得し、それを使用してAPIで認証し、ユーザーアカウントのリンクエンドポイントを使用する必要があります。ペイロードは、セカンダリユーザーのIDトークンでなければなりません。
次の例に示すように、
update:current_user_identities
スコープでアクセストークンを取得します。この例では暗黙的フローを使用していますが、任意の種類のアプリケーションのアクセストークンを取得できます。以前の、IDトークンを使う方法では、コードは次のようになります:
アクセストークンを使う新しい方法だと、コードは次のようになります:codeblockOld.header.login.configureSnippethttps://{yourDomain}/authorize? scope=openid &response_type=id_token &client_id={yourClientId} &redirect_uri=https://{yourApp}/callback &nonce=NONCE &state=OPAQUE_VALUE
Was this helpful?
/codeblockOld.header.login.configureSnippethttps://{yourDomain}/authorize? audience=https://{yourDomain}/api/v2/ &scope=update:current_user_identities &response_type=token%20id_token &client_id={yourClientId} &redirect_uri=https://{yourApp}/callback &nonce={nonce} &state={opaqueValue}
Was this helpful?
/Management APIにアクセスできるアクセストークンを取得するには以下を行います。
audience
をhttps://{yourDomain}/api/v2/
に設定するスコープ
${scope}
を要求するresponse_type
をid_token token
に設定し、Auth0がIDトークンとアクセストークンの両方を送るようにするアクセストークンをデコードすると、次のような内容になります:{ "iss": "https://{yourDomain}/", "sub": "auth0|5a620d29a840170a9ef43672", "aud": "https://{yourDomain}/api/v2/", "iat": 1521031317, "exp": 1521038517, "azp": "{yourClientId}", "scope": "${scope}" }
Was this helpful?
/aud
はテナントのAPI URI、スコープ
は${scope}
、sub
はログインユーザーのユーザーIDに設定されています。
次のような条件があります。
セカンダリアカウントのIDトークンは
RS256
で署名されている必要があります。セカンダリアカウントのIDトークンの
aud
クレームはクライアントを識別し、要求の作成に使用されたアクセス トークンのazp
クレームと同じ値を保持する必要があります。
アクセストークンを取得したら、それを使ってユーザーアカウントをリンクします。この部分は同じで、要求のうち、
Bearer
トークンとして使用する値を除き変更はありません。応答も同じです。{ "method": "POST", "url": "https://{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities", "httpVersion": "HTTP/1.1", "headers": [{ "name": "Authorization", "value": "Bearer ACCESS_TOKEN" }, { "name": "content-type", "value": "application/json" }], "postData" : { "mimeType": "application/json", "text": "{\"link_with\":\"SECONDARY_ACCOUNT_ID_TOKEN\"}" } }
Was this helpful?
/
auth0.jsを使って現在のユーザーアカウントをリンクする
auth0.jsライブラリを使用してManagement APIにアクセスし、アカウントをリンクする場合は、おそらくユーザーのプライマリ ID の ID トークンを使用してauth0.Management
をインスタンス化し、それを使用してアカウントをリンクします。
update:current_user_identities
スコープのアクセス トークンを取得し、このトークンを使用してauth0.Management
をインスタンス化します。linkUser
への最後の呼び出しは変わりません。以前の、IDトークンを使う方法では、コードは次のようになります:
アクセストークンを使う新しい方法だと、コードは次のようになります:codeblockOld.header.login.configureSnippet// get an ID Token var webAuth = new auth0.WebAuth({ clientID: '{yourClientId}', domain: '{yourDomain}', redirectUri: 'https://{yourApp}/callback', scope: 'openid', responseType: 'id_token' }); // create a new instance var auth0Manage = new auth0.Management({ domain: '{yourDomain}', token: '{yourIdToken}' });
Was this helpful?
/codeblockOld.header.login.configureSnippet// get an Access Token var webAuth = new auth0.WebAuth({ clientID: '{yourClientId}', domain: '{yourDomain}', redirectUri: 'https://{yourApp}/callback', audience: 'https://{yourDomain}/api/v2/', scope: 'update:current_user_identities', responseType: 'token id_token' }); // create a new instance var auth0Manage = new auth0.Management({ domain: '{yourDomain}', token: '{yourMgmtApiAccessToken}' });
Was this helpful?
/応答でIDトークンとアクセストークンの両方を求めます(
responseType: `token id_token`
)。Management APIを意図したトークンのオーディエンスとして設定します(
audience: `https://{yourDomain}/api/v2/`
)。必要な許可を要求します(
scope: `update:current_user_identities`
)。アクセストークンを使ってManagement APIで認証します。
Management APIで任意のユーザーアカウントをリンクする
update:users
スコープを含むアカウント リンク用のアクセス トークンを取得し、要求でセカンダリーアカウントの user_id
とプロバイダー
を送信する場合は、何も変更する必要はありません。
ただ、ここで紹介している新しいメソッドはその代わりになります。APIでの認証には引き続きupdate:users
スコープを含むアクセストークンを使用しますが、要求のペイロードでセカンダリのアカウントIDトークンを(user_id
およびプロバイダー
の代わりに)送信できます。
curl --request POST \
--url 'https://{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities' \
--header 'authorization: Bearer ACCESS_TOKEN' \
--header 'content-type: application/json' \
--data '{"link_with":"SECONDARY_ACCOUNT_ID_TOKEN"}'
Was this helpful?
var client = new RestClient("https://{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities");
var request = new RestRequest(Method.POST);
request.AddHeader("authorization", "Bearer ACCESS_TOKEN");
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"link_with\":\"SECONDARY_ACCOUNT_ID_TOKEN\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Was this helpful?
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities"
payload := strings.NewReader("{\"link_with\":\"SECONDARY_ACCOUNT_ID_TOKEN\"}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("authorization", "Bearer ACCESS_TOKEN")
req.Header.Add("content-type", "application/json")
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}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities")
.header("authorization", "Bearer ACCESS_TOKEN")
.header("content-type", "application/json")
.body("{\"link_with\":\"SECONDARY_ACCOUNT_ID_TOKEN\"}")
.asString();
Was this helpful?
var axios = require("axios").default;
var options = {
method: 'POST',
url: 'https://{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities',
headers: {authorization: 'Bearer ACCESS_TOKEN', 'content-type': 'application/json'},
data: {link_with: 'SECONDARY_ACCOUNT_ID_TOKEN'}
};
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 ACCESS_TOKEN",
@"content-type": @"application/json" };
NSDictionary *parameters = @{ @"link_with": @"SECONDARY_ACCOUNT_ID_TOKEN" };
NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities"]
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}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"link_with\":\"SECONDARY_ACCOUNT_ID_TOKEN\"}",
CURLOPT_HTTPHEADER => [
"authorization: Bearer ACCESS_TOKEN",
"content-type: application/json"
],
]);
$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 = "{\"link_with\":\"SECONDARY_ACCOUNT_ID_TOKEN\"}"
headers = {
'authorization': "Bearer ACCESS_TOKEN",
'content-type': "application/json"
}
conn.request("POST", "/{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities", 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}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities")
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["authorization"] = 'Bearer ACCESS_TOKEN'
request["content-type"] = 'application/json'
request.body = "{\"link_with\":\"SECONDARY_ACCOUNT_ID_TOKEN\"}"
response = http.request(request)
puts response.read_body
Was this helpful?
import Foundation
let headers = [
"authorization": "Bearer ACCESS_TOKEN",
"content-type": "application/json"
]
let parameters = ["link_with": "SECONDARY_ACCOUNT_ID_TOKEN"] as [String : Any]
let postData = JSONSerialization.data(withJSONObject: parameters, options: [])
let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/api/v2/users/PRIMARY_ACCOUNT_USER_ID/identities")! 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?
次のような条件があります。
セカンダリアカウントのIDトークンは
RS256
で署名されている必要があります。セカンダリアカウントのIDトークンの
aud
クレームはクライアントを識別し、要求の作成に使用されたアクセス トークンのazp
クレームと同じ値を保持する必要があります。
ユーザーアカウントのリンクを解除する
IDトークンを使ってアカウントのリンクを解除するには、アクセストークンを使うようコードを更新しなければなりません。
まず、
update:current_user_identities
スコープのアクセストークンを取得する必要があります。以前の、IDトークンを使う方法では、コードは次のようになります:
アクセストークンを使う新しい方法だと、コードは次のようになります:codeblockOld.header.login.configureSnippethttps://{yourDomain}/authorize? scope=openid &response_type=id_token &client_id={yourClientId} &redirect_uri=https://{yourApp}/callback &nonce={nonce} &state={opaqueValue}
Was this helpful?
/codeblockOld.header.login.configureSnippethttps://{yourDomain}/authorize? audience=https://{yourDomain}/api/v2/ &scope=update:current_user_identities &response_type=token%20id_token &client_id={yourClientId} &redirect_uri=https://{yourApp}/callback &nonce={nonce} &state={opaqueValue}
Was this helpful?
/Management APIにアクセスできるアクセストークンを取得するには以下を行います。
audience
をhttps://{yourDomain}/api/v2/
に設定するスコープ
${scope}
を要求するresponse_type
をid_token token
に設定し、Auth0がIDトークンとアクセストークンの両方を送るようにするアクセストークンをデコードすると、次のような内容になります:codeblockOld.header.login.configureSnippet{ "iss": "https://{yourDomain}/", "sub": "auth0|5a620d29a840170a9ef43672", "aud": "https://{yourDomain}/api/v2/", "iat": 1521031317, "exp": 1521038517, "azp": "{yourClientId}", "scope": "update:current_user_identities" }
Was this helpful?
/aud
はテナントのAPI URI、スコープ
はupdate:current_user_identities
、sub
はログインユーザーのユーザーIDに設定されています。
アクセストークンを取得したら、
Authorization
ヘッダーでそれを使用して、Management API のユーザーIDエンドポイントのリンク解除を呼び出すことができます。以前の方法では、呼び出しは次のようになります:
新しい方法では、呼び出しは次のようになります:DELETE https://YOUR_DOMAIN/api/v2/users/{primaryAccountUserId}/identities/{secondaryAccountProvider}/{secondaryAccountUserId} Authorization: 'Bearer {yourIdTokenOrMgmtApiAccessToken}'
Was this helpful?
/DELETE https://{yourDomain}/api/v2/users/{primaryAccountUserId}/identities/{secondaryAccountProvider}/{secondaryAccountUserId} Authorization: 'Bearer {yourMgmtApiAccessToken}'
Was this helpful?
/
セキュリティに関する考慮事項
ある特定のアカウントリンクフローに、特殊な状況において悪用される可能性のある弱点が見つかりました。実際に悪用された証拠はありませんが、予防策としてこのフローを廃止することが決まりましたので、
当該のアカウントリンクフローを使用している方は、2018年10月19日までに安全な実装へと移行するようお願いしています。このガイドでご紹介している移行パスをご利用いただけば、どの機能も失われません。
2018年10月19日以降、当該のアカウントリンクフローは無効になり、ランタイムエラーが生じます。
Authorizationヘッダーにスコープupdate:current_user_identities
を含むトークン(IDまたはアクセストークン)を使用してPost Identitiesエンドポイントを呼び出し、ペイロードにセカンダリアカウントのuser_id
を含めると、影響を受けます。その他のユースケースは影響を受けません。