여러 사용자 계정을 병합하기위한 아키텍처


176

자, 당신은 당신이 자신을 등록하고 로그인 할 수있는 웹 사이트를 가지고있다. 페이스 북, 트위터 또는 링크 인 계정으로 로그인 할 수도 있습니다.

사용자는 하나의 계정 만 등록해야합니다. 어떻게 든 다른 방법으로 로그인하는 사용자 계정을 병합하고 싶습니다. 이것을 해결하는 가장 좋은 해결책은 무엇입니까?

예를 들어, 사용자는 자신의 Facebook 계정으로 로그인합니다. 데이터를 사용하여 계정을 자동으로 등록합니다. 웹 사이트의 사용자 이름과 비밀번호를 이메일로 보내야합니까? (Facebook의 정책에 문제가없는 경우). 사용자 이름과 비밀번호를 입력 할 수있는 두 번째 화면을 제공해야합니까? 그러나 그것은 페이스 북 계정으로 로그인하는 아이디어가 아닙니다. 참여 절차를 단순화해야합니다.

사용자가 우리 웹 사이트에 등록하고 다음에 트위터 계정으로 로그인 할 수도 있습니다. 이 두 계정을 하나로 병합하려면 어떻게해야합니까? 가장 좋은 방법은 무엇입니까?

그래서 기본적으로 내 질문은 : 사용자가 우리 웹 사이트의 회원이되는 4 가지 방법이 있습니다. 사용자가 여러 방법을 사용하기로 결정한 경우이 4 가지 방법을 모두 하나의 계정 만 만들려면 어떻게해야합니까? 사용자 자신에게 번거롭지 않게하는 가장 좋은 방법은 무엇입니까?


편집하다:

이 질문을한지 3 년 후, 나는 일련의 기사에서 스스로 답을하고있다 : https://www.peternijssen.nl/social-network-authentication-setup/
https://www.peternijssen.nl/social- network-authentication-google /
https://www.peternijssen.nl/social-network-authentication-merging-accounts/
https://www.peternijssen.nl/social-network-authentication-twitter-facebook/


7
물론 스택 오버플로와 같은 여러 로그인 방법을 허용하여 사용자가 여러 계정을 갖지 못하도록하는 것이 가장 좋습니다. 그러나 SO에서도 중재자가 계정을 병합 할 수 있습니다. 나는 이것을 허용하기 위해 아키텍처를 설명 할 수있는 사람에게 현상금을 제공하고 있습니다. "Update post set UserID = 2 여기서 UserID = 1"보다 나은 솔루션이 있어야합니다.
David Boike

전자 메일과 전화를 병합 키로 사용할 수 있습니까?
Wuaner

안녕하세요, 제공하신 링크가 작동하지 않는 것 같습니다.
vigamage

링크를 업데이트했습니다. 기사는 6 살입니다.
PT

답변:


120

나는 현재 똑같은 일에 직면하고 있습니다. 내가 디자인 한 디자인은 다소 간단하지만 잘 작동합니다.

핵심 아이디어는 로컬 사이트 아이덴티티 및 타사 사이트 아이덴티티의 모델은 격리 된 상태로 유지하지만 나중에 연결되는 것입니다. 따라서 사이트에 로그인하는 모든 사용자는 여러 타사 사이트 ID에 매핑되는 로컬 ID를 갖습니다.

로컬 ID 레코드에는 최소한의 정보가 포함되어 있습니다. 단일 키일 수도 있습니다. 기본 키일뿐입니다. (응용 프로그램의 경우 사용자의 이메일, 이름 또는 생년월일은 신경 쓰지 않습니다.이 계정에 로그인 한 사람인지 알고 싶습니다.)

타사 ID에는 타사 인증과 관련된 정보 만 포함됩니다. OAuth의 경우 이는 일반적으로 사용자 식별자 (ID, 이메일 또는 사용자 이름 등)와 서비스 식별자 (인증 된 사이트 또는 서비스를 나타내는)를 의미합니다. 응용 프로그램의 다른 부분에서는 데이터베이스 외부에서 해당 서비스 식별자가 해당 서비스에서 관련 사용자 식별자를 검색하는 방법과 쌍을 이루어 인증이 수행되는 방식입니다. OpenID의 경우 인증 방법이 더 일반화되는 것을 제외하고 동일한 접근 방식을 사용합니다 (다른 식별 URL을 사용하고 서비스 식별자 인 경우를 제외하고는 거의 항상 동일한 프로토콜을 수행 할 수 있기 때문에).

마지막으로, 어떤 타사 ID가 어떤 로컬 ID와 연결되어 있는지 기록합니다. 이러한 레코드를 생성하기 위해 흐름은 다음과 같습니다.

  • 사용자가 타사 ID를 사용하여 처음으로 로그인합니다. 로컬 신원 레코드가 생성 된 다음 타사의 신원 레코드가 생성 된 다음 쌍이됩니다.
  • 제어판에서 사용자에게 타사 서비스에 로그인하여 계정을 연결할 수있는 기회가 제공됩니다. (이것이 어떻게 작동하는지 매우 간단합니다.)
  • 사용자가 무심코 여러 계정을 만드는 시나리오에서 솔루션은 매우 간단합니다. 사용자가 계정 중 하나에 로그인 한 상태에서는 이전에 제어판 기능을 통해 이전에 사이트에 로그인 할 때 사용한 다른 계정에 로그인합니다. 웹 서비스는이 충돌을 감지하고 (로그인 한 사용자의 로컬 ID가 방금 로그인 한 타사 ID에 연결된 로컬 ID와 다르므로) 사용자에게 계정 병합 메시지가 표시됩니다.

계정 병합은 로컬 신원의 각 개별 필드 (응용 프로그램마다 다를 수 있으며 로컬 신원 레코드에 몇 개의 필드 만있는 경우 쉬워야 함)와 연결된 타사 신원을 확인하는 문제입니다. 결과 로컬 신원에 연결됩니다.


1
이것은 매우 좋은 솔루션입니다 (로컬 신원 충돌을 자동 감지한다는 아이디어가 마음에 듭니다)! 응용 프로그램에 처음 로그인 한 후 연결된 "추가"계정에 사용자를 자동 로그인하는 방법을 찾았는지 궁금합니다. 방문 할 때마다 사용자가 각 계정에 별도로 로그인해야합니까 (이 공급자와의 활성 세션이없는 경우)?
Alexandra

@Alexandra "추가 계정"이란 무엇입니까? 사용자가 여러 인증자를 통해 응용 프로그램에 로그인 할 때 어떤 일이 발생하는지 물어보고 각각에 대해 새로운 로컬 ID를 만듭니다.
cheeken

:이 보증에게 적절한 설명과 자신의 질문에 생각 stackoverflow.com/questions/11060368/...
알렉산드라

3
질문이지만 사용자가 동일한 이메일 주소를 사용하여 사이트에 등록하면 어떻게됩니까? 이메일이 이미 존재 함 (제 3 자 모델에서 온 이메일)을 프롬프트하거나 사이트에 등록한 후 해당 계정을 병합 했습니까?
user962206

@ user962206 개인 정보 보호를 위해 많은 서비스에서 '실제'이메일 주소를 제공하지 않습니다. 예를 들어, 페이스 북이 "user.name@facebook.com"을 제공하는 한, 트위터는 어떤 이메일 주소도 제공하지 않습니다. 누군가가 등록에 사용하지 않을 것입니다.
kapex

44

이메일 을 기반으로하는 많은 사이트 가 중복되는 결합 요인 으로 발견되는 경향이 있습니다.

이것이 가능한 옵션이라는 것을 알 수 있지만 다시 병합 방법에 대한 선호도에 달려 있습니다. 이메일 주소는 사람들이 비밀번호 변경, 서비스 종료, 계정 잔액 부족 등과 같이 사이트에서 중요한 정보 변경을 확인하는 데 주로 사용하는 방법입니다. 웹의 사회 보장 번호 시스템과 거의 비슷하지만 통신 기능이 있습니다. . 문화적으로 : 전자 메일은 OAuth 인증 서비스에서 매우 고유 한 ID라고 가정하는 것이 합리적이라고 생각합니다. 물론 Facebook과 Google의 로그인 양식이 요구하는 것입니다.

나의 현재 생각 과정.

로그인 페이지에는 3 가지 옵션이 있습니다

  • 자신의 사이트 멤버십
  • 페이스 북으로 로그인
  • Google로 로그인

1) 처음으로 사용자 로그인 : 계정이 생성되고 처음으로 채워지는 등록 흐름을 트리거합니다.

 if the user logins using Facebook (or whatever 3rd party login)
      1) call the Facebook api asking for their information (email, name, etc...) 
      2) create an account membership entry in your database somewhat like this 

         Table = Users
         [ UserId   |       Email             | Password ]
         [    23     | "newuser@coolmail.com" |  *null*  ]

      3) create an external auths entry like so
         *ProviderUserId is the unique id of that user on the provider's site

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]

 if the user wants to create an account with your own registration it would just be this           

         Table = Users
         [ UserId   |       Email           |   Password  ]
         [    23     | newuser@coolmail.com |  myCoolPwd  ]

2) 다른 시간에 사용자가 돌아 왔지만 Google 로그인을 클릭하기로 결정했습니다.

      1) call the Google api asking for their information (email, name, etc...) 

      2) once you get the email, match it up to the userId entry with the existing email 

      3) create an additional External auth entry as such

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]
         [    57           |      23        |    Google    |  "1234854368"     ]

3) 이제 데이터베이스 항목의 전자 메일을 신뢰하는 계정을 외부 로그인에서 신뢰하는 계정과 병합했습니다.

후속 로그인의 경우

외부 로그인을 먼저하고 나중에 사용자가 나중에 비밀번호로 로그인 할 수있게하려면 어떻게해야합니까?

이 작업을 수행하는 두 가지 쉬운 방법이 있습니다

  • 외부 인증에서 계정을 만들 때 처음 로그인 할 때 응용 프로그램에 처음으로 입력 할 수 있도록 암호를 요청하십시오.

  • 이미 페이스 북이나 구글을 사용하여 등록했다면 어떻게 든 자신의 사이트 등록 양식을 사용하여 등록하고 싶을 것입니다. 입력 한 이메일 주소가 이미 존재하는지 감지하고 비밀번호를 요청한 후 등록 완료 후 이메일 확인을 보내십시오.


1
외부 인증 체계 (Facebook, Google, Twitter 등)를 사용하면 외부 공급자 암호에 액세스 할 수 없습니다. 위 예의 비밀번호는 OWN 웹앱의 비밀번호입니다.
Max Alexander

6
트위터는 사용자에게 이메일을 제공하지 않습니다. 따라서 Twitter UserId가 존재하지 않으면 첫 번째 인증 후에 이메일과 비밀번호를 입력하라는 메시지가 표시됩니다. 이메일과 비밀번호가 존재하면 계정을 연결하십시오. 그렇지 않은 경우 원활한 후속 인증을 위해 이메일과 비밀번호를 저장하십시오. 그게 전혀 도움이 되었습니까?
Max Alexander

1
부수적으로, 이제는 사용자의 이메일 주소를 얻기 위해 Twitter 앱에 대한 권한요청할 수 있습니다.
Sunil D.

2
페이스 북은 사람들이 이메일을 확인하도록합니까? 예를 들어 Github은 그렇지 않습니다. 악의적 인 사용자가 다른 사람의 전자 메일 이름으로 Github에 가입 한 다음이 전략을 통해 사이트의 계정에 액세스 할 수 있습니다. (Github의 API는 이메일 확인 여부를 알려줍니다. 확인되지 않은 이메일 주소로 Github 인증을받는 사람을 거부 할 수 있습니다)
Matthew Moisen

6
사용자가 소셜 미디어를 통해 가입하고 소셜 미디어에서 이메일 주소를 편집하고 다른 사람이 동일한 이메일 주소를 가져와 소셜 미디어에 등록한 다음 로그인하면 다른 사람 계정과 병합되는 보안 위반입니다. 이것은 매우 드물지만 위반은 적습니다. 아니면 뭔가 빠졌습니까?
Shane

35

sled.com에서이 과정을 거쳤습니다. 계정 생성 및 로그인을위한 여러 타사 계정 지원과 관련하여 여기에는 여러 가지 문제가 있습니다. 그들 중 일부는 다음과 같습니다.

  • 로컬 비밀번호와 타사 로그인을 모두 지원해야합니까?

sled.com의 경우, 작은 값이 추가되고 암호 입력 양식을 확보하는 데 드는 추가 비용으로 인해 로컬 암호를 삭제하기로 결정했습니다. 암호를 파기하는 알려진 공격이 많이 있으며 암호를 도입하려는 경우 암호를 해독하기 쉽지 않은지 확인해야합니다. 또한 누출 방지를 위해 단방향 해시 또는 이와 유사한 곳에 보관해야합니다.

  • 여러 타사 계정을 지원할 때 어느 정도의 유연성을 원하십니까?

이미 Facebook, Twitter 및 LinkedIn의 세 가지 로그인 공급자를 선택한 것 같습니다. OAuth를 사용하고 잘 정의 된 신뢰할 수있는 공급자 세트와 함께 작업한다는 것을 의미하기 때문에 좋습니다. 저는 OpenID의 팬이 아닙니다. 나머지 질문은 동일한 공급자의 여러 타사 계정을 지원해야하는 경우입니다 (예 : 두 개의 트위터 계정이 연결된 로컬 계정 하나). 나는 아니오라고 가정하지만, 그렇게하면 데이터 모델에 수용해야합니다.

Sled의 경우 Facebook, Twitter 및 Yahoo! 각 사용자 계정 저장소에는 { "_id": "djdjd99dj", "yahoo": "dj39djdj", twitter : "3723828732", "facebook": "12837287"} 각각의 키가 있습니다. Google은 각 타사 계정을 단일 로컬 계정에만 연결할 수 있도록 여러 가지 제약 조건을 설정했습니다.

동일한 타사 제공 업체의 여러 계정을 허용하려는 경우 목록 또는 기타 구조를 사용하여이를 지원하고 고유성을 보장하기 위해 다른 모든 제한 사항을 사용해야합니다.

  • 여러 계정을 연결하는 방법은 무엇입니까?

사용자가 처음으로 서비스에 가입하면 먼저 타사 제공 업체로 가서 확인 된 타사 ID로 돌아옵니다. 그런 다음 해당 계정에 대한 로컬 계정을 만들고 원하는 다른 정보를 수집하십시오. 우리는 그들의 이메일 주소를 수집하고 로컬 사용자 이름을 선택하도록 요청합니다 (우리는 다른 공급자의 기존 사용자 이름으로 양식을 미리 채우려 고합니다). 계정 복구에는 나중에 어떤 형식의 로컬 식별자 (이메일, 사용자 이름)를 갖는 것이 매우 중요합니다.

브라우저에 기존 계정에 대한 세션 쿠키 (유효하거나 만료 된)가없고 사용 된 타사 계정을 찾을 수없는 경우 서버는 처음 로그인임을 알고 있습니다. 우리는 사용자에게 로그인하는 것이 아니라 새 계정을 만들고 있음을 알리기 위해 이미 계정이있는 경우 기존 계정으로 일시 중지하고 로그인하도록합니다.

우리는 정확히 동일한 흐름을 사용하여 추가 계정을 연결하지만 사용자가 타사에서 돌아올 때 유효한 세션 쿠키가 존재하여 새 계정을 로그인 작업에 연결하려는 시도를 구별합니다. 각 유형의 타사 계정은 하나만 허용하고 이미 연결된 계정이 있으면 작업을 차단하십시오. 새 계정을 연결하기위한 인터페이스가 이미있는 경우 (제공자별로) 비활성화되어 있기 때문에 문제가되지 않습니다.

  • 계정을 병합하는 방법?

사용자가 이미 로컬 계정에 연결된 새 타사 계정을 연결하려고하면 두 계정을 병합 할 것인지 묻는 메시지를 표시하기 만하면됩니다 (데이터 세트와의 병합을 처리 할 수 ​​있다고 가정하면 더 쉬울 것입니다) 완료보다). 병합을 요청하는 특수 버튼을 제공 할 수도 있지만 실제로는 다른 계정을 연결하기 만하면됩니다.

이것은 매우 간단한 상태 머신입니다. 사용자가 타사 계정 ID를 사용하여 타사로부터 돌아옵니다. 데이터베이스는 다음 세 가지 상태 중 하나 일 수 있습니다.

  1. 계정이 로컬 계정에 연결되어 있고 세션 쿠키가 없습니다-> 로그인
  2. 계정이 로컬 계정에 연결되어 있고 세션 쿠키가 있습니다-> 병합
  3. 계정이 로컬 계정에 연결되어 있지 않으며 세션 쿠키가 없습니다-> 가입
  4. 계정이 로컬 계정에 연결되어 있지 않고 세션 쿠키가 있습니다-> 추가 계정 연결

    • 타사 제공 업체와 계정 복구를 수행하는 방법은 무엇입니까?

이것은 여전히 ​​실험 영역입니다. 대부분의 서비스가 타사 계정 옆에 로컬 암호를 모두 제공하므로 "나의 암호를 잊어 버렸습니다"사용 사례에 중점을두기 때문에 완벽한 UX를 보지 못했습니다.

Sled에서는 '로그인에 도움이 필요하십니까?'를 사용하기로했습니다. 클릭하면 사용자에게 이메일 또는 사용자 이름을 묻습니다. 검색하고 일치하는 계정을 찾으면 해당 사용자에게 자동으로 서비스에 로그인 할 수있는 링크를 이메일로 보내십시오 (한 번만 유효). 일단 들어가면 계정 연결 페이지로 바로 이동하여 추가로 계정을 연결하고 연결해야하며 이미 연결 한 타사 계정을 보여줍니다.


이 솔루션은 나에게 훨씬 좋습니다. 감사합니다!
Roy Shoa

2
세션 쿠키는 사용자를 식별하기에 충분하지 않습니다. 다른 사용자가 동일한 장치를 사용하면 어떻게됩니까?
DeepBlue

23

자동 병합 계정에 대한 두 가지 접근 방식은 누군가가 계정을 인수 할 수있는 매우 큰 취약점을 남깁니다. 그들은 둘 다 등록 사용자에게 병합 옵션을 제공 할 때 사용자가 누구인지를 가정하는 것으로 보입니다.

취약점을 완화하기위한 권장 사항은 병합을 수행하기 전에 알려진 아이덴티티 공급자 중 하나를 통해 사용자의 신원을 확인하도록 사용자에게 요청하는 것입니다.

예 : 사용자 A가 Facebook ID로 등록합니다. 나중에 그들은 사이트로 돌아가서 Windows Live ID로 액세스를 시도하고 등록 프로세스를 시작합니다. 귀하의 사이트에서 사용자 A에게 프롬프트를 표시합니다 ... 이전에 Facebook에 등록한 것 같습니다. Facebook (로그인 링크 제공)으로 로그인하면 Windows Live ID를 기존 프로필과 병합 할 수 있습니다.

또 다른 대안은 ID를 병합 할 때 사용자가 제공해야하는 초기 등록에 공유 비밀 (비밀번호 / 개인 질문)을 저장하는 것이지만 공유 비밀을 저장하는 비즈니스로 되돌아갑니다. 또한 사용자가 공유 비밀과 함께 수행되는 워크 플로를 기억하지 못하는 시나리오를 처리해야 함을 의미합니다.


제공자로부터 이메일 주소를받지 못하면 어떻게해야합니까?
fred.kassi

1

게시물의 대부분은 상당히 오래 되었으므로 Google의 무료 Firebase 인증 서비스가 아직 없었습니다. OAuth로 확인한 후 OAuth 토큰을 OAuth 토큰으로 전달하고 참조 용으로 저장할 수있는 고유 한 사용자 ID를 얻습니다. 지원되는 공급자는 Google, Facebook, Twitter, GitHub이며 사용자 지정 및 익명 공급자를 등록하는 옵션이 있습니다.


firebase가 이해가되지 않는 사용 사례가 있습니다. 예를 들어 하나 이상의 로그인이있는 인트라넷 시스템.
Bostwick


-4

계정 에서 로그인을 허용 다음 로그인 할 때 다른 계정을 추가하여 병합 할 수있는 옵션을 제공하십시오.


4
사용자가 그렇게하지 않고 4 개의 다른 계정으로 자신을 찾으면 어떻게됩니까? 이 경우 병합을 허용하는 아키텍처를 어떻게 작성합니까?
David Boike

귀하의 필요에 따라 이것은 실제로 유효한 제안 일 수 있습니다. 계정 병합 또는 연결을 나중에 생각할 수 있다고 생각하는 사람들에게 경고하고 싶습니다. 옵션은 UserGroup 및 UserMapping을 갖는 것입니다. OAuth 사용자 ID 또는 이메일 및 비밀번호 사용자 ID를 사용자 그룹에 맵핑 할 수 있습니다.
BumbleB2na
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.