リフレッシュトークンの取り消し
リフレッシュトークンが侵害された場合に備えて、リフレッシュトークンを取り消すことができます。Auth0は、トークンが悪意のある攻撃者にさらされている可能性があるかのように、トークンの失効を処理します。
また、クライアントが新しいアクセス トークンを取得するためにリフレッシュトークンを交換するたびに、新しいリフレッシュトークンも返されるように、リフレッシュトークンのローテーションを使用することもできます。このため、侵入を受けると永久にリソースへのアクセスを許してしまうような、寿命の長いリフレッシュトークンはなくなりました。リフレッシュトークンは交換され続け、失効し続けるため、脅威の軽減に繋がっています。
次の方法でリフレッシュトークンを無効化することができます。
ダッシュボード内
認証
/oauth/revoke
エンドポイントにPOST要求を行うManagement API
/api/v2/device-credentials
エンドポイントにPOST要求を行う
トークンと付与を更新する
付与により、アプリケーションはユーザー資格情報を公開することなく、別のエンティティ上のリソースにアクセスできるようになります。トークンは付与の文脈で発行され、付与が無効化されると、その付与の文脈で発行されたすべてのトークンも無効化されます。一方、トークンが無効化された場合、必ずしも付与が無効化されるわけではありません。
DashboardまたはManagement APIを使用して、デバイスがAuth0のユーザーからリンク解除されたときに、Dashboardのテナント設定で取り消し動作を選択できます。
Go to [Dashboard] > [Tenant Settings(テナント設定)] > [Advanced(詳細)]に移動し、[Settings(設定)]セクションにスクロールします。
失効をどのように動作させたいかに応じて、リフレッシュトークン失効削除許可トグルを有効または無効にします。
リフレッシュトークンを無効化する際に基礎となる許可を削除するには、トグルを有効にします。取り消し要求ごとに、特定のトークンだけでなく、同じ認可付与に基づくその他すべてのトークンを無効にします。つまり、同じユーザー、アプリケーション、オーディエンスに発行されたリフレッシュトークンがすべて取り消されます。
リフレッシュトークンを無効化する際に基礎となる許可を保持するには、トグルを無効にします。デバイスのリンクが解除されると、関連付けられたリフレッシュトークンのみが取り消され、許可はそのまま残ります。
Dashboardの使用
Dashboardを使用して、トークンを発行したアプリケーションへのユーザーの承認済みアクセスを取り消すことができます。これにより、リフレッシュトークンが無効になります。これは、トークン自体を取り消すのと機能的に同じです。
[Dashboard]>[User Management(ユーザー管理)]>[Users(ユーザー)]に移動し、ユーザー名をクリックして表示します。
[Authorized Application(認可アプリケーション)]タブを選択します。このページには、ユーザーがアクセスを許可したすべてのアプリケーションが一覧表示されます。
承認済みアプリケーションへのユーザーのアクセスを取り消して、リフレッシュトークンを無効にするには、[Revoke(取り消し)]をクリックします。
Authentication APIを使用する
リフレッシュトークンを取り消すには、https://{yourDomain}/oauth/revoke
にPOST
要求を送信します。
/oauth/revoke
エンドポイントは、特定のトークンだけでなく、許可全体を取り消します。リフレッシュトークンを取り消すには、/api/v2/device-credentials
エンドポイントを使用します。APIは最初にアプリケーションの資格情報を検証し、次にトークンが取り消し要求を行ったアプリケーションに発行されたかどうかを確認します。この検証が失敗すると、要求は拒否され、アプリケーションにエラーが通知されます。次に、APIはトークンを無効にします。無効化は直ちに行われ、取り消し後はトークンを再び使用することはできません。取り消し要求ごとに、同じ承認許可に対して発行されたすべてのトークンが無効になります。
curl --request POST \
--url 'https://{yourDomain}/oauth/revoke' \
--header 'content-type: application/json' \
--data '{ "client_id": "{yourClientId}", "client_secret": "{yourClientSecret}", "token": "{yourRefreshToken}" }'
Was this helpful?
var client = new RestClient("https://{yourDomain}/oauth/revoke");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{ \"client_id\": \"{yourClientId}\", \"client_secret\": \"{yourClientSecret}\", \"token\": \"{yourRefreshToken}\" }", 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/revoke"
payload := strings.NewReader("{ \"client_id\": \"{yourClientId}\", \"client_secret\": \"{yourClientSecret}\", \"token\": \"{yourRefreshToken}\" }")
req, _ := http.NewRequest("POST", url, payload)
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}/oauth/revoke")
.header("content-type", "application/json")
.body("{ \"client_id\": \"{yourClientId}\", \"client_secret\": \"{yourClientSecret}\", \"token\": \"{yourRefreshToken}\" }")
.asString();
Was this helpful?
var axios = require("axios").default;
var options = {
method: 'POST',
url: 'https://{yourDomain}/oauth/revoke',
headers: {'content-type': 'application/json'},
data: {
client_id: '{yourClientId}',
client_secret: '{yourClientSecret}',
token: '{yourRefreshToken}'
}
};
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/json" };
NSDictionary *parameters = @{ @"client_id": @"{yourClientId}",
@"client_secret": @"{yourClientSecret}",
@"token": @"{yourRefreshToken}" };
NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://{yourDomain}/oauth/revoke"]
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/revoke",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{ \"client_id\": \"{yourClientId}\", \"client_secret\": \"{yourClientSecret}\", \"token\": \"{yourRefreshToken}\" }",
CURLOPT_HTTPHEADER => [
"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 = "{ \"client_id\": \"{yourClientId}\", \"client_secret\": \"{yourClientSecret}\", \"token\": \"{yourRefreshToken}\" }"
headers = { 'content-type': "application/json" }
conn.request("POST", "/{yourDomain}/oauth/revoke", 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/revoke")
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/json'
request.body = "{ \"client_id\": \"{yourClientId}\", \"client_secret\": \"{yourClientSecret}\", \"token\": \"{yourRefreshToken}\" }"
response = http.request(request)
puts response.read_body
Was this helpful?
import Foundation
let headers = ["content-type": "application/json"]
let parameters = [
"client_id": "{yourClientId}",
"client_secret": "{yourClientSecret}",
"token": "{yourRefreshToken}"
] as [String : Any]
let postData = JSONSerialization.data(withJSONObject: parameters, options: [])
let request = NSMutableURLRequest(url: NSURL(string: "https://{yourDomain}/oauth/revoke")! 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?
ここでは、
属性 | 説明 |
---|---|
client_id 必須 |
アプリケーションのクライアントID。アプリケーションは、リフレッシュトークンが発行されたものと一致する必要があります。 |
client_secret |
アプリケーションのクライアントシークレット。機密アプリケーションに必要です。 |
token 必須 |
取り消したいリフレッシュトークン。 |
アプリケーションは、リフレッシュトークンが発行されたものと一致する必要があります。
クライアントシークレットなしでトークンを取り消す
クライアントシークレットを安全に保管できないアプリケーション(ネイティブアプリなど)の場合、/oauth/revoke
エンドポイントはクライアントシークレットなしでのアクセスをサポートします。ただし、アプリケーション自体のtokenEndpointAuthMethod
プロパティがnone
に設定されている必要があります。tokenEndpointAuthMethod
値は、[Dashboard] > [Applications(アプリケーション)] > [Applications(アプリケーション)]から、またはManagement APIを使用して変更できます。
要求が有効な場合、リフレッシュトークンは取り消され、応答はHTTP 200
で、応答本文は空です。それ以外の場合、応答本文にはエラーコードと説明が含まれます。
{
"error": "invalid_request|invalid_client",
"error_description": "Description of the error"
}
Was this helpful?
考えられる応答は次のとおりです。
HTTPステータス | 説明 |
---|---|
200 | リフレッシュトークンが取り消された、存在しない、または取り消し要求を行うアプリケーションに対して発行されていません。応答本文は空欄のままです。 |
400 | 必要なパラメーターが要求で送信されませんでした("error":"invalid_request" )。 |
401 | 要求は承認されていません("error": "invalid_client" )。アプリケーションの資格情報(client_id とclient_secret )が要求に存在し、有効な値が指定されていることを確認します。 |
Management APIの使用
Auth0 Management APIを使用してリフレッシュトークンを取り消すには、取り消すリフレッシュトークンのid
が必要です。既存のリフレッシュトークンのリストを取得するには、/api/v2/device-credentials
エンドポイントを呼び出し、type=refresh_token
とuser_id
を指定して、read:device_credentials
スコープを含むアクセス トークンを使用します。結果を絞り込むには、トークンに関連付けられたclient_id
(わかっている場合)を指定することもできます。
GET https://{yourDomain}/api/v2/device-credentials?
type=refresh_token
&client_id=
&user_id=
{
"Authorization": "Bearer {your_access_token}"
}
Was this helpful?
応答本文:
[
{
"id": "dcr_dFJiaAxbEroQ5xxx",
"device_name": "my-device" // the value of 'device' provided in the /authorize call when creating the token
}
]
Was this helpful?
リフレッシュトークンを取り消すには、delete:device_credentials
スコープを含むアクセス トークンと上記で取得した ID の値を使用して、/api/v2/device-credentials
エンドポイントを呼び出します。
DELETE https://{yourDomain}/api/v2/device-credentials/{id}
{
"Authorization": "Bearer {your_access_token}"
}
Was this helpful?
応答はHTTP 204: The credential no longer exists
(認証情報はもう存在しません)になります。
考慮事項と制限
デバイス認可フローでは、デバイスに再認証を強制する唯一の方法は、デバイスに割り当てられたリフレッシュトークンを取り消すことです。詳細については、ユーザーからデバイスのリンクを解除するを参照してください。デバイスは、現在有効なアクセストークンの期限が切れて、アプリケーションが失効したリフレッシュトークンを使おうとするまでは、再認証が強制されないことに注意してください。
リフレッシュトークンのローテーション使用中に以前無効になったトークンが使用されている場合は、その無効になったトークンが発行された以降に発行されたリフレッシュトークンの全セットが付与と同様に直ちに失効され、ユーザーの再認証が必要になります。
リフレッシュトークンを取り消すには、Authentication APIの
/oauth/revoke
エンドポイントを使用します。このエンドポイントは、基礎となる許可を削除しません。この動作を変更して、Dashboardで基礎となる許可も削除できます。[Dashboard] > [Tenant Settings(テナント設定)] > [Advanced(詳細)]。Settings(設定)までスクロールし、リフレッシュトークンの取り消しによる許可の削除のトグルを有効にします。ローテーション用に構成されたリフレッシュトークンを取り消すには、Management API
/api/v2/device-credentials
エンドポイントを使用します。