> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> GDPRの「同意の条件」要件への準拠に役立つAuth0の機能について説明します。

# GDPR: 同意の条件

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

GDPR第7条に基づき、個人データの処理について、明確で容易にアクセスできる形でユーザーの同意を得る必要があります。また、ユーザーが同意したことを示せるようにし、いつでも簡単に同意を撤回できる手段を提供しなければなりません。

この記事では、これらの要件を満たすためにAuth0の機能をどのように活用できるかを説明します。

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  これらの文書の内容は法的助言を目的としたものではなく、法的支援に代わるものでもありません。GDPRを理解し、これを遵守する最終的な責任はお客様にありますが、Auth0は可能な限りGDPR要件への対応を支援します。
</Callout>

<div id="ask-for-consent">
  ## 同意を求める
</div>

サインアップ時には、ユーザーに同意を求める必要があります。Auth0 では、この情報をユーザーのメタデータに保存できます。利用できる方法はいくつかあり、Auth0 を使ってユーザーをどのように認証するかによって異なります。メタデータを使ったソリューションを設計する前に、制限事項を把握しておいてください。Auth0 では、`user_metadata` の合計サイズは **16 MB** に制限されています。詳しくは、[Metadata Field Names and Data Types](/docs/ja-jp/manage-users/user-accounts/metadata/metadata-fields-data) を参照してください。

<Warning>
  Auth0 のメタデータは安全なデータ保存場所ではないため、高リスクのシークレットや、社会保障番号やクレジットカード番号のような個人を特定できる情報 (PII) などの機微な情報の保存には使用しないでください。Auth0 をご利用のお客様には、メタデータに保存するデータを十分に見直し、アイデンティティ/アクセス管理の目的で必要なものだけを保存することを強くお勧めします。
</Warning>

<div id="use-lock">
  ### Lock を使用する
</div>

Lock UI は、利用規約やプライバシーに関する声明ページへのリンクと、ユーザーがサインアップする際にチェックする必要がある同意チェックボックスを表示するようにカスタマイズできます。これは `mustAcceptTerm`s Lock オプションで実現できます。このプロパティを `true` に設定すると、サインアップ前にチェック必須のチェックボックスが利用規約とあわせて表示されます。利用規約は `languageDictionary` オプションを使って指定できます。詳しくは、[Lock Configuration Options](/docs/ja-jp/libraries/lock/lock-configuration) をお読みください。

ユーザーが同意してサインアップしたら、初回ログイン時に実行される `ルール` を使って、`user_metadata` に同意情報を保存します。ルールの詳細については、[Auth0 Rules](/docs/ja-jp/customize/rules) をお読みください。

サインアップ時にユーザーからさらに多くの情報を取得したい場合で、データベース接続を使用してユーザーを認証しているなら、Lock UI にカスタムフィールドを追加できます。これは `additionalSignUpFields` Lock オプションで実現できます。カスタムフィールドはすべて自動的に `user_metadata` に追加されます。

ソーシャルログインを使用している場合、カスタムフィールドを追加することはできませんが、ユーザーを別のページにリダイレクトして、そこで同意や追加情報を求めたあと、認証トランザクションを完了するために再度リダイレクトして戻すことができます。これはリダイレクト ルールで実現できます。詳しくは、[Redirect Users from Within Rules](/docs/ja-jp/customize/rules/redirect-users) をお読みください。サインアップ処理が完了したら、<Tooltip tip="Management API: お客様が管理タスクを実行できるようにする製品です。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Management+API">Management API</Tooltip> の [**Update User** エンドポイント](https://auth0.com/docs/api/management/v2#!/Users/patch_users_by_id) を呼び出して、`user_metadata` に同意情報を保存します。

これらのシナリオの実装方法については、[GDPR: Track Consent with Lock](/docs/ja-jp/secure/data-privacy-and-compliance/gdpr/gdpr-track-consent-with-lock) をお読みください。

<div id="use-custom-ui">
  ### カスタムUIを使用する
</div>

データベース接続を使用するカスタムのサインアップフォームでは、ユーザーの同意を取得するために、サインアップ画面に追加のフィールドを設ける必要があります。その後、Auth0 にユーザーを作成するために、Authentication API の [**Signup** エンドポイント](https://auth0.com/docs/api/authentication#signup) を呼び出します。この時点で、同意情報を `user_metadata` の一部として設定できます。

または、SPA から auth0.js を使用している場合は、[`signup` メソッドを使用して](/docs/ja-jp/libraries/auth0js)、Auth0 にユーザーを作成し、同意情報を `user_metadata` の一部として設定できます。

ソーシャルプロバイダーを使用するカスタムのサインアップフォームでは、サインアップ時にユーザーの同意情報を設定することはできませんが、ユーザーが作成されしだい更新できます。Management API の [**Update User** エンドポイント](https://auth0.com/docs/api/management/v2#!/Users/patch_users_by_id) を呼び出して、同意情報を `user_metadata` に保存してください。

これらのシナリオの実装方法については、[GDPR: カスタムUIで同意を追跡する](/docs/ja-jp/secure/data-privacy-and-compliance/gdpr/gdpr-track-consent-with-custom-ui) を参照してください。

<div id="re-consent-and-user-migration">
  ### 再同意とユーザー移行
</div>

既存のユーザーに同意を求める必要があり、既存のデータベースから Auth0 へユーザーを移行することにした場合は、[Automatic User Migration](/docs/ja-jp/manage-users/user-migration/configure-automatic-migration-from-your-database) 機能を利用できます。これを有効化すると、有効化後に各ユーザーが初めてログインした際、パスワードをリセットしなくても Auth0 にユーザーが作成されます。これを行うには、次の対応が必要です。

* ユーザーデータの利用方法、利用期間、ユーザーの権利などについて、ユーザーに表示する通知を作成するとともに、UI のサインアップボックスをカスタマイズします。
* 以前の利用規約やこれまでのプライバシー認証を踏まえて、ユーザーに再同意が必要かどうかを判断します。

利用規約が変更されるたびに、ユーザーには**必ず**再度同意を求める必要がある点に注意してください。

<div id="track-consent">
  ## 同意を追跡する
</div>

GDPR によれば、ユーザーが自身の個人データの処理に同意したことを示せる必要があります。

Auth0 では、ユーザーの同意情報を `user_metadata` の一部として保存できます。同意したかどうかを示す flag のみを保存することも、同意情報と設定一式 (たとえば、ユーザーが同意した日付や同意した条件などを含む) を保存することもできます。その後、この情報には Management API を使用してアクセスし、操作できます。

Management API には、ユーザー検索、ユーザーのメタデータを更新するためのエンドポイント、ユーザーを一括エクスポートするための機能に関しても、いくつかの選択肢があります。

Management API にアクセスするには、<Tooltip tip="アクセストークン: API にアクセスするために使用される認可資格情報で、不透明な文字列または JWT の形式を取ります。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=access+token">アクセストークン</Tooltip>が必要です。Management API 用のアクセストークンを取得する方法については、[Management API Access Tokens](/docs/ja-jp/secure/tokens/access-tokens/management-api-access-tokens) を参照してください。

<div id="search-for-users-by-email-address">
  ### メールアドレスでユーザーを検索する
</div>

メールアドレスでユーザーを検索するには、[**Search User by Email** エンドポイント](/docs/ja-jp/manage-users/user-search/user-search-best-practices)を使用します。

返されるフィールドを制限するには、**fields** リクエストパラメータを `user_metadata` に設定します。これにより、完全なユーザープロファイルではなく、user\_metadata のみが返されます。

リクエストの例:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://{yourDomain}/api/v2/users-by-email?email=USER_EMAIL_ADDRESS&fields=user_metadata' \
    --header 'authorization: Bearer YOUR_MGMT_API_ACCESS_TOKEN'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/users-by-email?email=USER_EMAIL_ADDRESS&fields=user_metadata");
  var request = new RestRequest(Method.GET);
  request.AddHeader("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN");
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

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

  func main() {

  	url := "https://{yourDomain}/api/v2/users-by-email?email=USER_EMAIL_ADDRESS&fields=user_metadata"

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

  	req.Header.Add("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN")

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

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

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

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.get("https://{yourDomain}/api/v2/users-by-email?email=USER_EMAIL_ADDRESS&fields=user_metadata")
    .header("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'GET',
    url: 'https://{yourDomain}/api/v2/users-by-email',
    params: {email: 'USER_EMAIL_ADDRESS', fields: 'user_metadata'},
    headers: {authorization: 'Bearer YOUR_MGMT_API_ACCESS_TOKEN'}
  };

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

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/users-by-email?email=USER_EMAIL_ADDRESS&fields=user_metadata",
    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 YOUR_MGMT_API_ACCESS_TOKEN"
    ],
  ]);

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

  curl_close($curl);

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

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

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

  conn.request("GET", "/{yourDomain}/api/v2/users-by-email?email=USER_EMAIL_ADDRESS&fields=user_metadata", headers=headers)

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

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

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/users-by-email?email=USER_EMAIL_ADDRESS&fields=user_metadata")

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

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

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

レスポンスの例:

```json lines theme={null}
[
  {},
  {
    "user_metadata": {
      "consent": {
	    "given": true,
	    "date": "01/23/2018",
	    "text_details": "some-url"
	  }
    }
  }
]
```

<div id="search-for-users-by-id">
  ### IDでユーザーを検索する
</div>

ユーザーIDで検索するには、[**Get a User** エンドポイント](/docs/ja-jp/manage-users/user-search/user-search-best-practices)を使用します。

返されるフィールドを制限するには、**fields** リクエストパラメータを `user_metadata` に設定します。これにより、完全なユーザープロファイルではなく、`user_metadata` のみが返されます。

リクエストの例:

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://{yourDomain}/api/v2/users/%7ByourUserID%7D?fields=user_metadata' \
    --header 'authorization: Bearer {yourMgmtApiAccessToken}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/users/%7ByourUserID%7D?fields=user_metadata");
  var request = new RestRequest(Method.GET);
  request.AddHeader("authorization", "Bearer {yourMgmtApiAccessToken}");
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

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

  func main() {

  	url := "https://{yourDomain}/api/v2/users/%7ByourUserID%7D?fields=user_metadata"

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

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

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

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

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

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.get("https://{yourDomain}/api/v2/users/%7ByourUserID%7D?fields=user_metadata")
    .header("authorization", "Bearer {yourMgmtApiAccessToken}")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'GET',
    url: 'https://{yourDomain}/api/v2/users/%7ByourUserID%7D',
    params: {fields: 'user_metadata'},
    headers: {authorization: 'Bearer {yourMgmtApiAccessToken}'}
  };

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

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/users/%7ByourUserID%7D?fields=user_metadata",
    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 {yourMgmtApiAccessToken}"
    ],
  ]);

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

  curl_close($curl);

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

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

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

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

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

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

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/users/%7ByourUserID%7D?fields=user_metadata")

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

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

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

レスポンスの例:

```json lines theme={null}
{
  "user_metadata": {
    "consent": {
	    "given": true,
	    "date": "01/23/2018",
	    "text_details": "some-url"
  	}
  }
}
```

<div id="update-consent-information">
  ### 同意情報を更新する
</div>

ユーザーの`user_metadata`を更新するには、[**ユーザーを更新** エンドポイント](https://auth0.com/docs/api/management/v2#!/Users/patch_users_by_id)を使用します。

リクエストの構成方法は、メタデータをルートプロパティとして持たせているか、内部プロパティとして持たせているかによって異なります。

メタデータがルートプロパティとして保存されている場合:

```json lines theme={null}
{
  "consentGiven": true,
  "consentDetails": "some-url"
}
```

メタデータがネストされたプロパティとして保存されている場合:

```json lines theme={null}
{
  "consent": {
    "given": true,
    "text_details": "some-url"
  }
}
```

<div id="update-root-property">
  #### ルートプロパティの更新
</div>

ルートレベルのプロパティへの更新はマージされるため、更新したいフィールドの値だけを送信すれば十分です。たとえば、同意日を追加し、その値を `01/23/2018` に設定するとします。

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url 'https://{yourDomain}/api/v2/users/USER_ID' \
    --header 'authorization: Bearer YOUR_MGMT_API_ACCESS_TOKEN' \
    --header 'content-type: application/json' \
    --data '{"user_metadata":{"consentDate":"01/24/2018"}}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/users/USER_ID");
  var request = new RestRequest(Method.PATCH);
  request.AddHeader("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN");
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{"user_metadata":{"consentDate":"01/24/2018"}}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

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

  func main() {

  	url := "https://{yourDomain}/api/v2/users/USER_ID"

  	payload := strings.NewReader("{"user_metadata":{"consentDate":"01/24/2018"}}")

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

  	req.Header.Add("authorization", "Bearer YOUR_MGMT_API_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))

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.patch("https://{yourDomain}/api/v2/users/USER_ID")
    .header("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN")
    .header("content-type", "application/json")
    .body("{"user_metadata":{"consentDate":"01/24/2018"}}")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'PATCH',
    url: 'https://{yourDomain}/api/v2/users/USER_ID',
    headers: {
      authorization: 'Bearer YOUR_MGMT_API_ACCESS_TOKEN',
      'content-type': 'application/json'
    },
    data: {user_metadata: {consentDate: '01/24/2018'}}
  };

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

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/users/USER_ID",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_POSTFIELDS => "{"user_metadata":{"consentDate":"01/24/2018"}}",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer YOUR_MGMT_API_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;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{"user_metadata":{"consentDate":"01/24/2018"}}"

  headers = {
      'authorization': "Bearer YOUR_MGMT_API_ACCESS_TOKEN",
      'content-type': "application/json"
      }

  conn.request("PATCH", "/{yourDomain}/api/v2/users/USER_ID", payload, headers)

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

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

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/users/USER_ID")

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

  request = Net::HTTP::Patch.new(url)
  request["authorization"] = 'Bearer YOUR_MGMT_API_ACCESS_TOKEN'
  request["content-type"] = 'application/json'
  request.body = "{"user_metadata":{"consentDate":"01/24/2018"}}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

これにより、ユーザープロファイルに新しいプロパティ **user\_metadata.consentDate** が追加され、顧客が同意した日付がそこに保存されます。レスポンスにはユーザープロファイル全体が返されます。更新後のメタデータは次のようになります:

```json lines theme={null}
{
  "consentGiven": true,
  "consentDate": "01/23/2018",
  "consentDetails": "some-url"
}
```

<div id="update-inner-property">
  #### 内部プロパティを更新する
</div>

内部プロパティを更新するには、1 つのプロパティしか更新しない場合でも、メタデータオブジェクト全体を送信する必要があります。オブジェクト全体を含めないと、Auth0 によって既存のプロパティが削除されます。

同意日の内部プロパティを追加し、その値を `01/23/2018` に設定してみましょう。

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url 'https://{yourDomain}/api/v2/users/USER_ID' \
    --header 'authorization: Bearer YOUR_MGMT_API_ACCESS_TOKEN' \
    --header 'content-type: application/json' \
    --data '{"user_metadata":{"consent": {"given":true, "date":"01/23/2018", "text_details":"some-url"}}}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/users/USER_ID");
  var request = new RestRequest(Method.PATCH);
  request.AddHeader("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN");
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{"user_metadata":{"consent": {"given":true, "date":"01/23/2018", "text_details":"some-url"}}}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

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

  func main() {

  	url := "https://{yourDomain}/api/v2/users/USER_ID"

  	payload := strings.NewReader("{"user_metadata":{"consent": {"given":true, "date":"01/23/2018", "text_details":"some-url"}}}")

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

  	req.Header.Add("authorization", "Bearer YOUR_MGMT_API_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))

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.patch("https://{yourDomain}/api/v2/users/USER_ID")
    .header("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN")
    .header("content-type", "application/json")
    .body("{"user_metadata":{"consent": {"given":true, "date":"01/23/2018", "text_details":"some-url"}}}")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'PATCH',
    url: 'https://{yourDomain}/api/v2/users/USER_ID',
    headers: {
      authorization: 'Bearer YOUR_MGMT_API_ACCESS_TOKEN',
      'content-type': 'application/json'
    },
    data: {
      user_metadata: {consent: {given: true, date: '01/23/2018', text_details: 'some-url'}}
    }
  };

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

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/users/USER_ID",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_POSTFIELDS => "{"user_metadata":{"consent": {"given":true, "date":"01/23/2018", "text_details":"some-url"}}}",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer YOUR_MGMT_API_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;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{"user_metadata":{"consent": {"given":true, "date":"01/23/2018", "text_details":"some-url"}}}"

  headers = {
      'authorization': "Bearer YOUR_MGMT_API_ACCESS_TOKEN",
      'content-type': "application/json"
      }

  conn.request("PATCH", "/{yourDomain}/api/v2/users/USER_ID", payload, headers)

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

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

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/users/USER_ID")

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

  request = Net::HTTP::Patch.new(url)
  request["authorization"] = 'Bearer YOUR_MGMT_API_ACCESS_TOKEN'
  request["content-type"] = 'application/json'
  request.body = "{"user_metadata":{"consent": {"given":true, "date":"01/23/2018", "text_details":"some-url"}}}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

これにより、ユーザープロファイルに **user\_metadata.consent.date** という新しいプロパティが追加され、顧客が同意した日付がそこに格納されます。レスポンスにはユーザープロファイル全体が返されます。更新後のメタデータは次のようになります。

```json lines theme={null}
{
  "consent": {
    "given": true,
    "date": "01/23/2018",
    "text_details": "some-url"
  }
}
```

<div id="export-consent-information">
  ### 同意情報をエクスポートする
</div>

Management API を使用してユーザー一覧をエクスポートするには、[**User Export** エンドポイント](/docs/ja-jp/manage-users/user-search/user-search-best-practices)を使用します。

このエンドポイントでは、接続に関連付けられたすべてのユーザーをエクスポートする `job` が作成されます。接続の ID が必要です。この ID を確認するには、[**Get Connections** エンドポイント](https://auth0.com/docs/api/management/v2#!/Connections/get_connections)を使用します (**name** パラメーターに接続名を設定すると、その接続のみを取得できます) 。

接続 ID と Management API 用のアクセストークンを取得したら、ユーザーのエクスポートを開始できます。リクエストとレスポンスの例については、[Import and Export Users](/docs/ja-jp/manage-users/user-migration)を参照してください。Management API 用のアクセストークンの取得方法については、[Management API Access Tokens](/docs/ja-jp/secure/tokens/access-tokens/management-api-access-tokens)を参照してください。

また、次のことも必要です。

* 同意をどのように追跡するかを決めます。ユーザーが同意した日付だけでなく、ユーザーが同意した利用規約のバージョン情報も含めることをお勧めします。また、許可を撤回したユーザーに関する情報を保持するための配列を用意することもお勧めします (ユーザーは同意と撤回を複数回行う可能性があることに注意してください) 。
* 同意をどこに保存するかを決めます。Auth0 のデータベースに保存するか、それ以外の場所に保存するかを選択してください。

<div id="withdraw-consent">
  ## 同意の撤回
</div>

ユーザーがアプリ上で同意を撤回できるようにしておく必要があります。この選択肢は見つけやすく、他と明確に区別できるようにしてください。ユーザーが同意を撤回することを決めたら、必要な対応を行う必要があります。

まず、同意の撤回をどのように処理するかを決める必要があります。ユーザーを削除するのか、それとも削除済みとしてフラグを付けるのかを決めてください。

<div id="delete-user">
  ### ユーザーを削除する
</div>

ユーザーを削除するには、[**Delete a User** エンドポイント](https://auth0.com/docs/api/management/v2#!/Users/delete_users_by_id)を使用します。

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request DELETE \
    --url 'https://{yourDomain}/api/v2/users/USER_ID' \
    --header 'authorization: Bearer YOUR_MGMT_API_ACCESS_TOKEN'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/users/USER_ID");
  var request = new RestRequest(Method.DELETE);
  request.AddHeader("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN");
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

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

  func main() {

  	url := "https://{yourDomain}/api/v2/users/USER_ID"

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

  	req.Header.Add("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN")

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

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

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

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.delete("https://{yourDomain}/api/v2/users/USER_ID")
    .header("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'DELETE',
    url: 'https://{yourDomain}/api/v2/users/USER_ID',
    headers: {authorization: 'Bearer YOUR_MGMT_API_ACCESS_TOKEN'}
  };

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

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/users/USER_ID",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "DELETE",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer YOUR_MGMT_API_ACCESS_TOKEN"
    ],
  ]);

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

  curl_close($curl);

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

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

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

  conn.request("DELETE", "/{yourDomain}/api/v2/users/USER_ID", headers=headers)

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

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

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/users/USER_ID")

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

  request = Net::HTTP::Delete.new(url)
  request["authorization"] = 'Bearer YOUR_MGMT_API_ACCESS_TOKEN'

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

このエンドポイントのレスポンスボディは空です。そのため、ユーザーが正常に削除されたことを確認するには、そのメールアドレスを使ってユーザーの取得を試してください。エンドポイントからエラーが返された場合は、ユーザーの削除リクエストは成功しています。

<div id="flag-user-as-deleted">
  ### ユーザーに削除済みフラグを付ける
</div>

ユーザーを削除したくない場合は、[**app\_metadata** endpoint](https://auth0.com/docs/api/management/v2#!/Users/patch_users_by_id) を使用して、そのプロファイルに削除済みフラグを設定します。次に、そのフラグが設定されたユーザーの認証が失敗するように、コードを追加します。

これにより、将来利用するために削除済みユーザーの記録を保持できます。

<div id="flag-the-profile">
  #### プロファイルにフラグを設定する
</div>

ユーザーを削除済みとしてフラグ付けするには、app\_metadata を使用します。次の例では、**app\_metadata** フィールドに **deleted** というプロパティを追加する方法を示します。これにより、認証プロセスで、このプロパティが true に設定されているすべてのユーザーを削除済みとして扱うように設定できます。

ユーザーのメタデータを更新するには、[**ユーザーを更新** エンドポイント](https://auth0.com/docs/api/management/v2#!/Users/patch_users_by_id)を使用します。

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url 'https://{yourDomain}/api/v2/users/USER_ID' \
    --header 'authorization: Bearer YOUR_MGMT_API_ACCESS_TOKEN' \
    --header 'content-type: application/json' \
    --data '{"app_metadata":{"deleted":true}}'
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/api/v2/users/USER_ID");
  var request = new RestRequest(Method.PATCH);
  request.AddHeader("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN");
  request.AddHeader("content-type", "application/json");
  request.AddParameter("application/json", "{"app_metadata":{"deleted":true}}", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

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

  func main() {

  	url := "https://{yourDomain}/api/v2/users/USER_ID"

  	payload := strings.NewReader("{"app_metadata":{"deleted":true}}")

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

  	req.Header.Add("authorization", "Bearer YOUR_MGMT_API_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))

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.patch("https://{yourDomain}/api/v2/users/USER_ID")
    .header("authorization", "Bearer YOUR_MGMT_API_ACCESS_TOKEN")
    .header("content-type", "application/json")
    .body("{"app_metadata":{"deleted":true}}")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'PATCH',
    url: 'https://{yourDomain}/api/v2/users/USER_ID',
    headers: {
      authorization: 'Bearer YOUR_MGMT_API_ACCESS_TOKEN',
      'content-type': 'application/json'
    },
    data: {app_metadata: {deleted: true}}
  };

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

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/api/v2/users/USER_ID",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_POSTFIELDS => "{"app_metadata":{"deleted":true}}",
    CURLOPT_HTTPHEADER => [
      "authorization: Bearer YOUR_MGMT_API_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;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "{"app_metadata":{"deleted":true}}"

  headers = {
      'authorization': "Bearer YOUR_MGMT_API_ACCESS_TOKEN",
      'content-type': "application/json"
      }

  conn.request("PATCH", "/{yourDomain}/api/v2/users/USER_ID", payload, headers)

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

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

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/api/v2/users/USER_ID")

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

  request = Net::HTTP::Patch.new(url)
  request["authorization"] = 'Bearer YOUR_MGMT_API_ACCESS_TOKEN'
  request["content-type"] = 'application/json'
  request.body = "{"app_metadata":{"deleted":true}}"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

<div id="disable-login-for-flagged-users">
  #### フラグが付けられたユーザーのログインを無効にする
</div>

次に、削除済みとしてフラグが付けられたユーザーがログインできないようにする必要があります。そのために、ルール (authentication パイプラインの一部として実行される JavaScript スニペット) を追加します。

1. [Auth0 Dashboard > Auth Pipeline > Rules](https://manage.auth0.com/#/rules) に移動し、ルールを作成します。
2. 以下のスクリプトをコピーします。

   ```javascript lines theme={null}
   function (user, context, callback) {
     user.app_metadata = user.app_metadata || {};
     if (user.app_metadata.deleted){
     	return callback(new UnauthorizedError('Access denied (deleted user)'));
     }
     callback(null, user, context);
   }
   ```

   このスクリプトでは次の処理を行います。

   1. **deleted** メタデータプロパティ (`user.app_metadata.deleted`) の値を確認します。
   2. `user.app_metadata.deleted = true` の場合、アプリに `Access denied (deleted user)` エラーを返します。
3. ルールに名前を付けて、変更を保存します。

また、次のことも必要です。

* 同意撤回の仕組みが十分に細かく設定されていることを確認します。
* 顧客が同意を撤回できる箇所をアプリ内に設けます。

<div id="learn-more">
  ## 詳細はこちら
</div>

* [GDPR: データ最小化](/docs/ja-jp/secure/data-privacy-and-compliance/gdpr/gdpr-data-minimization)
* [GDPR: データポータビリティ](/docs/ja-jp/secure/data-privacy-and-compliance/gdpr/gdpr-data-portability)
* [GDPR: ユーザーデータを保護し、安全性を確保する](/docs/ja-jp/secure/data-privacy-and-compliance/gdpr/gdpr-protect-and-secure-user-data)
* [GDPR: データへのアクセス、訂正、削除の権利](/docs/ja-jp/secure/data-privacy-and-compliance/gdpr/gdpr-right-to-access-correct-and-erase-data)
