web-dev-qa-db-ja.com

RESTfulパスワードのリセット

パスワードをリセットするためのRESTfulリソースを構成する適切な方法は何ですか?

このリソースは、パスワードを紛失または忘れたユーザーのためのパスワード再設定ツールです。古いパスワードを無効にし、パスワードを電子メールで送信します。

私が持っている2つのオプションは次のとおりです。

POST /reset_password/{user_name}

または...

POST /reset_password
   -Username passed through request body

リクエストはPOSTであるべきだと確信しています。適切な名前を選択したかどうかはあまりわかりません。そして、user_nameがURLを介して渡されるのか、リクエスト本文を介して渡されるのかがわかりません。

86
Chris Dutrow

PDATE:(さらにコメントする)

私はこのようなものに行きます:

POST /users/:user_id/reset_password

ユーザーのコレクションがあり、単一のユーザーが{user_name}で指定されています。次に、操作するアクションを指定します。この場合はreset_passwordです。 「reset_passwordの新しい{user_name}アクションを作成(POST)」と言っているようなものです。


前の答え:

私はこのようなものに行きます:

PUT /users/:user_id/attributes/password
    -- The "current password" and the "new password" passed through the body

2つのコレクション、ユーザーコレクション、および各ユーザーの属性コレクションがあります。ユーザーは:user_idで指定され、属性はpasswordで指定されます。 PUT操作は、コレクションのアドレス指定されたメンバーを更新します。

48
Daniel Vassallo

認証されていないユーザー

api/v1/account/passwordエンドポイントでPUTリクエストを行い、ユーザーがパスワードをリセット(更新)したいアカウントを識別するために、対応するアカウントの電子メールにパラメーターが必要です。

PUT : /api/v1/account/password?email={[email protected]}

注:As@ DougDomeny URL内のクエリ文字列として電子メールを渡す彼のコメントはセキュリティリスクです。 httpsを使用する場合、GETパラメーターは公開されません(そのような要求には常に適切なhttps接続を使用する必要があります)が、他のセキュリティリスクが伴います。このトピックの詳細については、 このブログ投稿をご覧ください。

要求本文で電子メールを渡すことは、GETパラメーターとして渡すよりも安全な代替手段です。

PUT : /api/v1/account/password

リクエスト本文:

{
    "email": "[email protected]"
}

応答には、202受け入れ応答の意味があります。

要求は処理のために受け入れられましたが、処理は完了していません。要求は、実際に処理が行われるときに許可されない可能性があるため、最終的に実行される場合と実行されない場合があります。このような非同期操作からステータスコードを再送信する機能はありません。

ユーザーは[email protected]で電子メールを受信し、更新リクエストの処理は、電子メールからのリンクで実行されたアクションに依存します。

https://example.com/password-reset?token=1234567890

このメールからリンクを開くと、非表示の入力フィールドへの入力としてリンクからのリセットパスワードトークンを使用する、フロントエンドアプリケーションのリセットパスワードフォームが表示されます(トークンはクエリ文字列としてリンクの一部です)。別の入力フィールドでは、ユーザーが新しいパスワードを設定できます。新しいパスワードを確認するための2番目の入力は、フロントエンドでの検証に使用されます(入力ミスを防ぐため)。

注:メールでは、ユーザーがパスワードのリセットを初期化していない場合は、電子メールを無視し、現在のパスワードでアプリケーションを通常どおり使用し続けます

新しいパスワードとトークンを入力としてフォームが送信されると、パスワードのリセット処理が行われます。フォームデータはPUTリクエストで再度送信されますが、今回はトークンを含め、リソースパスワードを新しい値に置き換えます。

PUT : /api/v1/account/password

リクエスト本文:

{
    "token":"1234567890",
    "new":"password"
}

応答は204 no content応答になります

サーバーは要求を実行しましたが、エンティティ本体を返す必要はなく、更新されたメタ情報を返したい場合があります。応答には、エンティティヘッダーの形式で新しいメタデータまたは更新されたメタ情報が含まれている場合があります。

認証されたユーザー

パスワードを変更したい認証ユーザーの場合、PUTリクエストはメールなしですぐに実行できます(パスワードを更新するアカウントはサーバーに知られています)。そのような場合、フォームは2つのフィールドを送信します。

PUT : /api/v1/account/password

リクエスト本文:

{
    "old":"password",
    "new":"password"
}
59
Wilt

ちょっと待ってみましょう。パスワードにDELETEアクションを使用してリセットをトリガーしないのはなぜですか?理にかなっていますよね?結局のところ、既存のパスワードを効果的に破棄して、別のパスワードを優先させることになります。

それはあなたがすることを意味します:

DELETE /users/{user_name}/password

次に、2つの大きな注意事項を示します。

  1. HTTP DELETEはべき等であることになっています (「何度もやっても大したことはない」と言うのは派手な言葉です)。 「パスワードリセット」メールを送信するなどの標準的な作業を行っている場合は、問題が発生します。ブール値の「Is Reset」フラグでユーザー/パスワードをタグ付けするこの問題を回避できます。削除するたびに、このフラグをチェックします。設定されていない場合、その後パスワードをリセットしてメールを送信できます。 (このフラグを使用すると、他の用途もあることに注意してください。)

  2. フォームでHTTP DELETEを使用することはできません ですので、AJAXを呼び出すか、POSTでDELETEをトンネルする必要があります。

16
Craig Walker

多くの場合、最初の要求でユーザーの既存のパスワードを削除または破棄したくないのは、これが電子メールにアクセスできないユーザーによって(意図的または意図的に)トリガーされた可能性があるためです。代わりに、ユーザーレコードのリセットパスワードトークンを更新し、メールに含まれるリンクで送信します。リンクをクリックすると、ユーザーがトークンを受信し、パスワードを更新することを確認します。理想的には、これも時間に敏感です。

この場合のRESTfulアクションはPOSTです。PasswordResetsコントローラーでcreateアクションをトリガーします。アクション自体がトークンを更新し、電子メールを送信します。

11
Mark Swardstrom

私は実際に答えを探していますが、答えを提供する意味ではありません-しかし、RESTコンテキストでは、それは名詞ではなく動詞であるため、「reset_password」は間違っているように聞こえます。 「リセットアクション」名詞を実行しています-この正当化を使用して、すべての動詞は名詞です。

また、セキュリティコンテキストを介してユーザー名を取得でき、URLや本文を介してユーザー名を送信する必要がないのと同じ回答を検索しているユーザーには発生しなかった可能性があります。

8
orbfish

私はより良いアイデアがあると思う:

DELETE /api/v1/account/password    - To reset the current password (in case user forget the password)
POST   /api/v1/account/password    - To create new password (if user has reset the password)
PUT    /api/v1/account/{userId}/password    - To update the password (if user knows is old password and new password)

データの提供について:

  • 現在のパスワードをリセットするには

    • 電子メールは本文で提供する必要があります。
  • リセット後に新しいパスワードを作成するには

    • 新しいパスワード、アクティベーションコード、およびemailIDを本文で指定する必要があります。
  • loggedInユーザーのパスワードを更新するには

    • 古いパスワード、新しいパスワードを本文に記載する必要があります。
    • パラメーターのユーザーID。
    • ヘッダー内の認証トークン。
5
codesnooker

考慮すべきいくつかの考慮事項があります。

パスワードのリセットはi等ではありません

パスワードの変更は、それを実行するための資格情報として使用されるデータに影響を与えます。その結果、保存された資格情報が変更されている間にリクエストが単純に繰り返されると、将来の試行が無効になる可能性があります。たとえば、一時的なリセットトークンを使用して変更を許可する場合、パスワードを忘れた場合の慣例であるため、パスワードの変更が成功するとそのトークンは期限切れになり、リクエストの複製の試行がさらに無効になります。したがって、パスワードの変更に対するRESTfulなアプローチは、POSTよりもPUTに適した仕事のようです。

データロードのIDまたは電子メールはおそらく冗長です

これはRESTに反するものではなく、特別な目的がある可能性がありますが、パスワードリセットのためにIDまたはメールアドレスを指定する必要はないことがよくあります。何らかの方法で認証を受けることになっているリクエストへのデータの提供?ユーザーが単にパスワードを変更する場合、そのためには認証が必要です(username:password、email:password、またはヘッダー)。したがって、そのステップからアカウントにアクセスできます。パスワードを忘れた場合は、変更を実行するための資格情報として特に使用できる一時的なリセットトークン(電子メール経由)が提供されます。この場合、トークンを介した認証でアカウントを識別できます。

上記のすべてを考慮に入れると、RESTfulなパスワード変更に対する適切なスキームであると私は信じています:

Method: POST
url: /v1/account/password
Access Token (via headers): pwd_rst_token_b3xSw4hR8nKWE1d4iE2s7JawT8bCMsT1EvUQ94aI
data load: {"password": "This 1s My very New Passw0rd"}
3
Michael Ekoka

/ users/{id}/passwordメソッドを使用することに決めた場合、パスワードを変更して新しいパスワードを送信し、リクエストはそれ自体のリソースであるという考えに固執するものはありません。つまり、/ user-password-request /はリソースであり、PUTを使用しています。ユーザー情報は本文に含める必要があります。ただし、パスワードは変更しません。Idにrequest_guidを含むページへのリンクを含む電子メールをユーザーに送信します。このリンクは、POST/user/{id}/password /?request_guid = xxxxx

それはパスワードを変更し、パスワードの変更を要求することで誰かがユーザーにホースをかけることを許可しません。

さらに、未処理の要求がある場合、最初のPUTが失敗する可能性があります。

2
bpeikes

ログに記録されたユーザーパスワードPUT/v1/users/passwordを更新します-AccessTokenを使用してユーザーIDを識別します。

ユーザーIDを交換することは安全ではありません。 Restful APIは、HTTPヘッダーで受信したAccessTokenを使用してユーザーを識別する必要があります。

Spring-bootの例

@putMapping(value="/v1/users/password")
public ResponseEntity<String> updatePassword(@RequestHeader(value="Authorization") String token){
/* find User Using token */
/* Update Password*?
/* Return 200 */
}
0
Dan