RESTful 비밀번호 재설정


107

비밀번호 재설정을 위해 RESTful 리소스를 구성하는 적절한 방법은 무엇입니까?

이 리소스는 비밀번호를 분실하거나 잊어 버린 사람을위한 비밀번호 재설정 도구입니다. 이전 암호를 무효화하고 전자 메일로 암호를 보냅니다.

내가 가진 두 가지 옵션은 다음과 같습니다.

POST /reset_password/{user_name}

또는...

POST /reset_password
   -Username passed through request body

요청이 POST 여야한다고 확신합니다. 적절한 이름을 선택했다고 확신하지 못합니다. 그리고 user_name이 URL 또는 요청 본문을 통해 전달되어야하는지 확실하지 않습니다.

답변:


54

업데이트 : (아래에 추가로 설명)

나는 다음과 같이 갈 것입니다.

POST /users/:user_id/reset_password

사용자 모음이 있으며 여기서 단일 사용자는 {user_name}. 그런 다음 작업 할 작업을 지정합니다 reset_password. 이 경우에는입니다 . "에 POST대한 새 reset_password작업 만들기 ( ) "라고 말하는 것과 같습니다 {user_name}.


이전 답변 :

나는 다음과 같이 갈 것입니다.

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

각 사용자에 대한 두 개의 컬렉션, 사용자 컬렉션 및 속성 컬렉션이 있습니다. 사용자는에 의해 지정되고 :user_id속성은에 의해 지정됩니다 password. 이 PUT작업은 컬렉션의 주소가 지정된 구성원을 업데이트합니다.


10
업데이트 된 (POST) 솔루션에 동의합니다. PUT 요청은 멱등 적이어야합니다 (즉, 반복되는 요청은 결과에 영향을주지 않아야 함). POST 요청에는 해당되지 않습니다.
Ross McFarlane

16
reset_password를 password_reset으로 변경합니다
Richard Knop 2014 년

9
잠깐만 요 ... 이것은 본질적으로 누군가가 누군가의 암호를 재설정하는 것을 허용하지 않습니까? 현재 암호를 잊어 버린 사람을위한 것이므로 영향을받는 사용자는 현재 암호로 인증 될 수 없습니다. 따라서 본질적으로 이것은이 API가 어떤 암호도 허용 할 수 없음을 의미합니다. 따라서 누구든지 다른 사람의 암호를 재설정 할 수 있으며 API가 암호를 반환하면 알려진 사용자의 암호도 얻을 수 있습니다. 아니면 내가 뭔가를 놓치고
transient_loop

39
/ user / {id} / password 등의 문제점은 사용자의 "ID"를 모를 수 있다는 것입니다. "사용자 이름", "이메일"또는 "전화"는 알지만 "ID"는 알 수 없습니다.
coolaj86 2014 년

17
이 접근 방식의 근본적인 결함은 이미 사용자 ID를 알고 있다고 가정한다는 것입니다. 이는 일부 상황에서는 사실이지만 사용자가 재설정을 위해 이메일을 지정하기 만하면 사용자 이름이나 사용자 ID를 알 수없는 경우 어떻게해야합니까?
Alappin 2015 년

94

인증되지 않은 사용자

엔드 포인트 에서 PUT요청을 수행 api/v1/account/password하고 사용자가 비밀번호를 재설정 (업데이트)하려는 계정을 식별하기 위해 해당 계정 이메일과 함께 매개 변수가 필요합니다.

PUT : /api/v1/account/password?email={email@example.com}

참고 : @DougDomeny가 URL에 쿼리 문자열로 이메일을 전달하는 그의 코멘트에 언급 된 보안 위험이다. GET 매개 변수는 사용할 때 노출되지 않지만 https( https이러한 요청에 대해 항상 적절한 연결을 사용해야 함 ) 관련된 다른 보안 위험이 있습니다. 여기에 있는 이 블로그 게시물 에서이 주제에 대해 자세히 읽을 수 있습니다 .

요청 본문에 이메일을 전달하는 것이 GET 매개 변수로 전달하는 것보다 더 안전한 대안이 될 것입니다.

PUT : /api/v1/account/password

요청 본문 :

{
    "email": "email@example.com"
}

응답에는 202허용 된 응답 의미가 있습니다.

처리를 위해 요청이 수락되었지만 처리가 완료되지 않았습니다. 요청은 처리가 실제로 수행 될 때 허용되지 않을 수 있으므로 결국 처리되거나 처리되지 않을 수 있습니다. 이와 같은 비동기 작업에서 상태 코드를 다시 보낼 수있는 기능은 없습니다.

사용자는에서 이메일을 받게 email@example.com되며 업데이트 요청 처리 는 이메일 의 링크로 수행 한 작업에 따라 달라집니다.

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

이 이메일에서 링크를 열면 숨겨진 입력 필드에 대한 입력으로 링크의 비밀번호 재설정 토큰을 사용하는 프런트 엔드 애플리케이션의 비밀번호 재설정 양식으로 연결됩니다 (토큰은 쿼리 문자열로 링크의 일부 임). 다른 입력 필드에서는 사용자가 새 암호를 설정할 수 있습니다. 새 암호를 확인하는 두 번째 입력은 프런트 엔드에서 유효성 검사에 사용됩니다 (오타 방지).

참고 : 이메일에서 사용자가 비밀번호 재설정을 초기화하지 않은 경우 이메일을 무시하고 현재 비밀번호로 애플리케이션을 정상적으로 계속 사용할 수 있다고 언급 할 수도 있습니다.

새 암호와 토큰을 입력으로 사용하여 양식을 제출하면 암호 재설정 프로세스가 수행됩니다. 양식 데이터는 PUT요청 과 함께 다시 전송 되지만 이번에는 토큰을 포함하여 리소스 비밀번호를 새 값으로 바꿉니다.

PUT : /api/v1/account/password

요청 본문 :

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

응답은 204내용 없음 응답이됩니다.

서버가 요청을 수행했지만 엔티티 본문을 반환 할 필요가 없으며 업데이트 된 메타 정보를 반환 할 수 있습니다. 응답은 엔티티 헤더의 형태로 새로운 또는 업데이트 된 메타 정보를 포함 할 수 있으며, 존재하는 경우 요청 된 변형과 연관되어야합니다.

인증 된 사용자

비밀번호를 변경하려는 인증 된 사용자의 PUT경우 이메일없이 요청을 즉시 수행 할 수 있습니다 (비밀번호를 업데이트하는 계정이 서버에 알려져 있음). 이 경우 양식은 두 개의 필드를 제출합니다.

PUT : /api/v1/account/password

요청 본문 :

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

첫 번째 단락에서 PUT이라고 말하지만 아래 예는 DELETE라고 말합니다. 어느 것이 정확합니까?
jpierson 2015

이는 URL에 이메일 주소를 노출하므로 JSON 데이터보다 더 안전합니다.
Doug Domeny

@DougDomeny 예, 이메일을 json 데이터로 보내는 것이 아마도 더 좋을 것입니다. 나는 이것을 더 안전한 대안으로 대답에 추가했습니다. 그렇지 않으면 해결책이 동일 할 수 있습니다.
Wilt

@Wilt : 이것은 PATCH 작업이 아닐까요? PUT는 완전한 리소스를 보내야합니다
j10

1
@jitenshah 좋은 지적입니다. 이 글을 쓸 때 나는 PUT이 더 나을 것이라고 생각했지만 정확히 그 이유를 기억하지 못합니다. 이 경우에 패치가 더 적합 할 수 있다는 귀하의 추론에 동의합니다.
윌트

18

잠시 동안 uber-RESTful을 시작하겠습니다. 재설정을 트리거하기 위해 암호에 DELETE 작업을 사용하지 않는 이유는 무엇입니까? 말이되지 않나요? 결국, 당신은 다른 암호를 위해 기존 암호를 효과적으로 버리는 것입니다.

즉, 다음을 수행 할 것입니다.

DELETE /users/{user_name}/password

이제 두 가지 큰주의 사항 :

  1. HTTP DELETE는 멱등 적이어야합니다 ( "여러 번 수행하면 별거 아님"이라는 멋진 단어). "비밀번호 재설정"이메일을 보내는 것과 같은 일반적인 작업을 수행하는 경우 문제가 발생합니다. 부울 "Is Reset"플래그를 사용하여 사용자 / 암호에 태그를 지정하는 문제를 해결할 수 있습니다. 삭제할 때마다이 플래그를 확인합니다. 이 설정되어 있지 않은 경우 다음 당신은 암호를 재설정하고 이메일을 보낼 수 있습니다. (이 플래그를 사용하면 다른 용도로도 사용할 수 있습니다.)

  2. 양식을 통해 HTTP DELETE를 사용할 수 없으므로 AJAX 호출을 수행하거나 POST를 통해 DELETE를 터널링해야합니다.


9
흥미로운 아이디어. 그러나 나는 DELETE여기에 잘 어울리지 않는다 . 암호를 무작위로 생성 된 암호로 대체 DELETE할 것이므로 오해의 소지가있을 수 있습니다. 나는 Create (POST) new reset_password action당신이 행동 할 명사 (자원)가 "reset_password action"인 것을 선호합니다 . 이 작업은 이러한 모든 하위 수준 세부 정보를 캡슐화하기 때문에 이메일 전송에도 적합합니다. POST멱 등성이 아닙니다.
Daniel Vassallo

나는 제안을 좋아한다. 문제 1은 조건부 요청, 즉 ETag + DELETE 및 If-Match 헤더를 보내는 HEAD를 사용하여 처리 할 수 ​​있습니다. 사람이 더 이상 활성 상태의 암호를 삭제하려고하면, 그는 412 얻을 것이다
whiskeysierra

1
나는 DELETE를 피할 것입니다. 동일한 엔티티 / 개념이 새로운 가치를 얻게되므로 업데이트하고 있습니다. 그러나 실제로는 일반적으로 지금 일어나지 않지만 나중에 다른 요청에서 새 비밀번호를 보낸 후에 만 ​​(비밀번호 재설정 메일 후)-요즘 아무도 새 비밀번호를 우편으로 보내지 않지만 새 요청에서 재설정하는 토큰 주어진 토큰 맞죠?
antonio.fornie

11
사용자가 재설정 요청을 한 직후 자신의 비밀번호를 기억하면 어떻게됩니까? 임의의 계정을 재설정하려는 일부 봇은 어떻습니까? 이 경우 사용자는 재설정 이메일을 무시할 수 있어야합니다 (이메일에 그렇게 표시되어야 함). 즉, 시스템이 자체적으로 비밀번호를 삭제하거나 업데이트해서는 안됩니다.
Maxime Laval

3
@MaximeLaval 아주 좋은 지적입니다. 정말로, 당신은 POST가 될 "재설정 요청 생성"입니다.
Craig Walker

12

이메일에 대한 액세스 권한이없는 사용자에 의해 (의도적 또는 의도적으로) 트리거되었을 수 있으므로 초기 요청에서 사용자의 기존 비밀번호를 삭제하거나 파기하고 싶지 않은 경우가 많습니다. 대신 사용자 레코드에서 비밀번호 재설정 토큰을 업데이트하고 이메일에 포함 된 링크로 보냅니다. 링크를 클릭하면 사용자가 토큰을 받았음을 확인하고 암호를 업데이트하기를 원합니다. 이상적으로 이것은 시간에 민감합니다.

이 경우 RESTful 작업은 POST : PasswordResets 컨트롤러에서 생성 작업을 트리거합니다. 액션 자체는 토큰을 업데이트하고 이메일을 보냅니다.


9

나는 실제로 답을 찾고 있는데, 하나를 제공한다는 의미가 아닙니다. 그러나 "reset_password"는 명사가 아니라 동사이기 때문에 REST 컨텍스트에서 나에게 잘못 들립니다. 이 정당성을 사용하여 "reset action"명사를한다고해도 모든 동사는 명사입니다.

또한 보안 컨텍스트를 통해 사용자 이름을 얻을 수 있고 URL이나 본문을 통해 보낼 필요가 전혀없는 동일한 답변을 검색하는 사람에게는 발생하지 않았을 수 있습니다.


4
아마도 reset-password동사처럼 들리지만 쉽게 뒤집어서 ( password-reset) 명사로 만들 수 있습니다 . 이벤트 소싱을 사용하여 애플리케이션을 모델링했거나 감사의 종류 만있는 경우에도 실제로이 이름을 가진 실제 엔터티가 있고 사용자 나 관리자가 볼 수 있도록 GET을 허용 할 수도 있습니다. 기록 (분명히 암호 텍스트 마스킹). 나를 전혀 긴장시키지 않습니다. 그리고 서버 측에서 사용자 이름을 자동으로 선택하는 방법은 가능합니다. 그러면 관리 / 가장과 같은 작업을 어떻게 처리합니까?
Aaronaught

1
REST에서 동사를 사용하는 데 아무런 문제가 없습니다. 적절한 장소에서 사용되는 한. 나는 이것이 리소스 라기보다는 컨트롤러 에 가깝다고 생각 하고 reset-password그 효과를 잘 설명 할 수 있습니다.
Anders Östman 2015

6

더 나은 아이디어는 다음과 같습니다.

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)

데이터 제공에 관하여 :

  • 현재 비밀번호를 재설정하려면

    • 이메일은 본문에 제공되어야합니다.
  • 새 암호를 만들려면 (재설정 후)

    • 새 비밀번호, 활성화 코드 및 이메일 ID를 본문에 입력해야합니다.
  • 비밀번호를 업데이트하려면 (로그인 한 사용자의 경우)

    • 이전 암호, 새 암호는 본문에 언급되어야합니다.
    • Params의 UserId.
    • 헤더의 인증 토큰.

2
다른 답변에서 언급했듯이 "DELETE / api / v1 / account / password"는 누구나 다른 사람의 암호를 재설정 할 수 있으므로 나쁜 생각입니다.
maximedupre

비밀번호를 재설정하려면 등록 된 이메일 ID가 필요합니다. 우리가 페이스 북과 같은 사이트를 운영하고 어떤 방법 으로든 수많은 이메일 ID를 수집하지 않는 한 알려지지 않은 사용자의 이메일 ID를 알 가능성은 매우 암울합니다. 그런 다음 그에 따라 보안 정책이 정의됩니다. 다른 사람의 암호를 재설정하라는 제안은 무엇입니까?
codesnooker

5

고려해야 할 몇 가지 사항이 있습니다.

비밀번호 재설정은 멱 등성이 아닙니다.

암호 변경은이를 수행하기 위해 자격 증명으로 사용되는 데이터에 영향을 미치므로 저장된 자격 증명이 변경되는 동안 요청이 그대로 반복되는 경우 향후 시도가 무효화 될 수 있습니다. 예를 들어 임시 재설정 토큰을 사용하여 변경을 허용하는 경우 암호를 잊은 상황에서 일반적으로 해당 토큰은 성공적인 암호 변경시 만료되어야하며 요청 복제 시도가 다시 무효화됩니다. 따라서 비밀번호 변경에 대한 RESTful 접근 방식 POSTPUT.

데이터로드시 ID 또는 이메일이 중복 될 수 있음

REST에 위배되지 않고 특별한 목적이있을 수 있지만 비밀번호 재설정을 위해 ID 또는 이메일 주소를 지정할 필요가없는 경우가 많습니다. 생각해보십시오. 인증을 거쳐야하는 요청에 데이터의 일부로 이메일 주소를 제공하는 이유는 무엇입니까? 사용자가 단순히 비밀번호를 변경하는 경우이를 위해 인증해야합니다 (사용자 이름 : 비밀번호, 이메일 : 비밀번호 또는 헤더를 통해 제공된 액세스 토큰을 통해). 따라서 해당 단계에서 해당 계정에 액세스 할 수 있습니다. 비밀번호를 잊어 버린 경우 변경을 수행하기위한 자격 증명으로 사용할 수있는 임시 재설정 토큰 (이메일을 통해)이 제공되었을 것입니다. 그리고이 경우 토큰을 통한 인증은 그들의 계정을 식별하기에 충분해야합니다.

위의 모든 사항을 고려하여 RESTful 암호 변경에 대한 적절한 계획은 다음과 같습니다.

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

자리 표시 자에 대역 외 정보가 필요하다는 진술은 완전히 사실이 아닙니다. 특수 미디어 유형은 요청 또는 응답의 특정 요소에 대한 구문과 의미를 설명 할 수 있습니다. 따라서 미디어 유형은 특정 필드에 포함 된 URI가 특정 데이터에 대한 플레이스 홀더를 정의 할 수 있고 의미론은 인코딩 된 사용자 이메일 또는 플레이스 홀더 대신 포함되지 않아야하는 것을 추가로 정의 할 수 있습니다. 해당 미디어 유형을 존중하는 클라이언트와 서버는 여전히 RESTful 아키텍처 원칙을 준수합니다.
Roman Vottner

1
에 관해서는 POSTPUT 7231 개 RFC 부분 업데이트가이 개 자원의 중복 데이터를 통해 달성 될 수 있지만 같은이 경우는 의심되도록 지정 /v1/account/password정말 실제로 좋은 자원을 만회 않습니다는. 로 POST다른 방법 중 어느 것도 쉽지 않은 경우 고려, 사용할 수있는 웹의 스위스 - 군대 - kniff입니다 PATCH힘도 새 암호를 설정하는 선택은.
Roman Vottner

비밀번호를 모르는 경우 비밀번호 재설정을 요청하는 URL은 어떻게 되나요?
dan carter

2

/ users / {id} / password 메서드를 사용하기로 결정한 경우 암호를 변경하고 새 암호를 보내지 않고 요청이 자체 리소스라는 생각을 고수합니다. 즉 / user-password-request /는 리소스이며 PUT를 사용하고 사용자 정보는 본문에 있어야합니다. 나는 암호를 변경하지 않을 것이며, Id는 POST / user / {id} / password /? request_guid =에 대한 요청과 함께 전달할 수있는 request_guid가 포함 된 페이지에 대한 링크가 포함 된 이메일을 사용자에게 보냅니다. xxxxx

그것은 암호를 변경하고 누군가가 암호 변경을 요청하여 사용자를 호스로 만드는 것을 허용하지 않습니다.

또한 미해결 요청이있는 경우 초기 PUT가 실패 할 수 있습니다.


0

기록 된 사용자 암호 PUT / v1 / users / password를 업데이트합니다-AccessToken을 사용하여 사용자 ID를 식별합니다.

사용자 ID를 교환하는 것은 안전하지 않습니다. Restful API는 HTTP 헤더에서 수신 한 AccessToken을 사용하여 사용자를 식별해야합니다.

스프링 부트의 예

@putMapping(value="/v1/users/password")
public ResponseEntity<String> updatePassword(@RequestHeader(value="Authorization") String token){
/* find User Using token */
/* Update Password*?
/* Return 200 */
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.