클라이언트 응용 프로그램에서 사용자 인증을 설계하는 방법은 무엇입니까?


14

많은 사용자를 지원하는 응용 프로그램을 개발하고 있습니다. 문제는 클라이언트 / 사용자를 인증하는 방법을 알 수 없다는 것입니다.

http://quickblox.com/ 과 같은 응용 프로그램 을 만들고 있는데 사용자에게 자격 증명을 제공하고 인증을 위해 사용자 이름과 암호를 넣을 수없는 N 응용 프로그램 을 빌드하는 데 사용 합니다.

다음과 같이 진행한다고 가정 해 봅시다. (QuickBlox와 동일)

1. 사용자가 내 웹 사이트에서 계정을 만듭니다.
2. 사용자는 N API 키를 생성하고 자격 증명을 숨길 수 있습니다. (여러 앱의 경우)
3. 사용자는 애플리케이션 (Android, iOS, Javascript 등)에서이 자격 증명을 사용하여 REST API와 대화합니다.
REST API에는 읽기 및 쓰기 권한이 있습니다.

내 관심사?

사용자는 자신이 만든 응용 프로그램에 자격 증명 (API 키 및 비밀 키)을 넣습니다. 누군가이 키를 가져 와서 사용자를 모방하려고하면 어떻게됩니까? (DK를 디 컴파일하거나 JavaScript 코드를 직접 살펴봄으로써.

내가 어딘가에 잘못인가?
이 세 가지 수준의 사용자 메커니즘을 설계하는 데 혼란을 느낍니다.


당신이하려고하는 것 같지 않습니다.
user253751

동일한 작업을 수행하는 많은 응용 프로그램이 있습니다. 그들이 어떻게 사용자를 인증하는지 잘 모르겠습니다.
Alok Patel

클라이언트 응용 프로그램 또는 사용자 를 인증하려고 합니까? 많은 앱이 사용자를 인증합니다. 그들 중 누구도 깨지지 않는 방식으로 클라이언트 응용 프로그램을 인증하지 않습니다.
user253751

예, 클라이언트에서는 사용자 만 인증하고 싶습니다.
Alok Patel

4
그렇다면 가장 일반적인 인증 시스템에서 사용자는 사용자 이름과 비밀번호를 입력하고이를 확인하고 세션 토큰을 반환하는 서버로 안전하게 보낸 다음 세션 토큰을 보냅니다. 미래의 모든 요청.
user253751

답변:


7

지난 몇 년 동안 REST API를 설계 해 왔습니다. 당신은 너무 걱정하고 있습니다. 최근에이 보드의 다른 사용자 가 자신의 JavaScript 클라이언트 측 코드에 URI 엔드 포인트를 저장하는 것에 대해 걱정하는 질문 을했습니다 .

JavaScript 개발자에게 적용되는 것과 동일한 규칙이 적용됩니다. 외부 사용자가 API를 통합 할 수 있도록 허용하는 경우 API는 일반 웹 사이트와 동일한 가시성을 가지며 동일한 방식으로 처리해야합니다.

원래 답변에서 인용하십시오.

웹 사이트를 만들 때 사용자가 무언가를하지 않으려는 경우 해당 기능을 구현하거나 특정 사용자가 웹 사이트를 사용하지 못하도록 금지하지 않습니다. 퍼블릭 엔드 포인트를 가져야하는 REST API는 거의 동일하므로 퍼블릭 웹 사이트처럼 취급해야합니다.

REST API는 다른 사용자의 데이터에 대한 액세스와 같은 유효하지 않은 조작을 허용하지 않을 정도로 강력해야합니다.

허용하려는 작업 만 허용하도록 응용 프로그램 액세스 토큰을 설계해야합니다. 두 가지 유형의 액세스 토큰을 가질 수 있습니다.

  • 마스터 토큰 : 응용 프로그램 작성자가 사용할 수 있으며 API에서 더 많은 기능을 제공합니다.
  • 응용 프로그램 토큰 : 실제로 응용 프로그램 내에 저장되고 API 또는 응용 프로그램 프로그래머의 데이터를 손상시킬 수없는 작업에만 API에 대한 액세스가 제한되는 토큰입니다.

그러나 누군가 소스 코드를 해체하고 토큰을 응용 프로그램에서 꺼내고 공개 엔드 포인트가 무엇인지 파악하고 웹 서비스를 악용하는 것은 무엇입니까?

API를 사용하는 애플리케이션의 개발을 직접 관리하지 않는 한, 사람들이 앱에서 직접 동일한 방식으로 API를 악용하는 것을 막을 수있는 것은 없습니다.


지금까지 좋은 설명이지만 질문이 있습니다. 내 API 중 하나가 내 사용자 의 모든 관련 데이터 (A + B)를 가져 오기 위해 빌드되었다고 가정 해 봅시다 . 내 사용자는 얻가 자신의 응용 프로그램이 API를 사용하는 filtered data의 (B) 자신의 사용자 만. 이제 세 번째 사용자내 사용자 의 모든 데이터 (A + B)를 훔치는 것을 방지 할 수있는 방법 이 있습니까 ? 말이 되나요?
Alok Patel

@AlokPatel 기능을 구현하지 않는 다른 해결 방법은 없습니다. 그렇게하면 항상 누군가가 자신의 신분 해시를 훔쳐 다른 사람처럼 보일 위험이 있습니다. 프로그래밍 방식으로 문제를 해결할 수 없습니다. 내가 말했듯이 일부 기능을 제공하지 않으려면 구현하지 마십시오. 앱은 로그인 해시를 그 안에 저장하기 때문에 앱이 배포되면 API 키도 공개되며 사용할 수 없습니다.
Andy

설명 주셔서 감사합니다. 지금까지 내가 얻은 것은 REST API는 우리가 배포 한 웹 사이트와 동일하며 웹 사이트만큼 열려 있습니다. 사용자가 무언가를하지 않으려면 REST API에서 단순히 구현하지 않습니다. 따라서 내가 할 수있는 일은 클라이언트 라이브러리 (Android, iOS, JS)에 대한 별도의 키를 가지고 기능이 적고 서버 키 (PHP, Java, node.js)가 확장 기능을 사용하는 다른 키로 손상 될 수 있습니다. 이것이 효과가 있기를 바랍니다!
Alok Patel

이 요점을 설명해 주시겠습니까? API를 사용하는 응용 프로그램의 개발을 직접 관리하지 않는 한
Alok Patel

@AlokPatel 내가 의미하는 바는 지금 누군가에게 API에 대한 액세스 권한을 부여하는 것을 걱정하고 있으며 액세스 권한을 배포하고 API를 악용하기 시작할 수 있습니다. API를 사용하는 응용 프로그램의 개발을 제어 할 수없는 경우 자체적으로도 동일한 작업을 수행 할 수 있습니다.
Andy

5

당신의 문제는 기술적 인 문제가 아닙니다.

일년에 100 파운드의 고정 요금으로 무제한 액세스로 고객 (앱 개발자)에게 판매하는 API가 있다고 가정 해 보겠습니다.

그럼 분명히, 나는 당신의 서비스를 £ 100에 사고 각각 $ 50에 10 명에게 팔 수 있습니다. 당신은 그것을 원하지 않습니다! 따라서 귀하는 API를 차익 거래에 개방하지 않고도 판매 할 수있는 제한 사항을 생각하려고합니다.

  • Apps 수만 제한하면 고객이 다른 앱의 연결을 수락하고 전달하는 단일 앱을 만들 수 있습니다.

  • 사용자를 제한하면 고객은 자신의 인증 뒤에있는 사용자를 숨기고 단일 사용자 인 것처럼 보일 수 있습니다.

당신이해야 할 일은 고객에게 각 API 호출 비용을 전달하는 것입니다. 즉, API 호출 당 청구 또는 연간 호출 할당량을 설정합니다.

이는 고객에게 동일한 차익 거래 문제를 제기합니다. 사용자가 키를 훔치지 않도록 조치를 취합니다. 이 경우 자신의 사용자 인증 API 뒤에 API를 숨 깁니다.


이미 API 호출 수를 기반으로 API 사용을 제한하려고 계획 했으므로 비즈니스 관련 문제는 현재 내 관심사가 아니며 키 도난에 대해서만 걱정하고 있습니다.
Alok Patel

비즈니스 관점에서 볼 때 문제는 해결할 수 없습니다. 안타깝게도 프로그래밍 방식으로 해결할 수 없습니다.
Andy

1
비즈니스 문제는 통화 당 청구로 해결됩니다. 키를 도난 당하면 고객이 손실됩니다. 너 말고. 고객에게 도난당한 키를 취소 할 수있는 방법을
Ewan

2

다른 답변은 소비자 장치의 앱에 비밀을 저장하는 문제를 해결할 수 없음을 제안하는 것 같습니다.

당연히 그렇지.

두 가지 원칙 (구현 세부 사항은 다음과 같습니다) :

  1. 실제 인증 엔드 포인트는 익명으로 공개되어야합니다.
  2. 서버는 어떻게 든 클라이언트 인증 및 API 키 제공에 관여해야합니다.

클라이언트가 자격 증명을 사용하여 인증 끝점에 요청하고 서버가이를 인증하면 서버는 동적 임시 토큰 (임시 의미 시간 기반)을 생성 할 수 있습니다 . 이 토큰은 클라이언트 내에서 기억되고 후속 요청과 함께 전송되어야합니다.

토큰을 주기적으로 "새로 고침"하는 메커니즘이 필요합니다. 즉, 새 토큰을 얻습니다. 신임 정보에서 다시 인증하지 않아도 기존 토큰에서 새 토큰을 생성 할 수있는 REST 엔드 포인트를 빌드하십시오.

최종 사용자가 자신을 다시 인증하지 않도록하려는 경우이 인증은 앱이 설치 될 때 앱에서 초기 일회성 설정이 될 수 있습니다.

이 솔루션은 응용 프로그램 바이너리 내에 포함 된 정적 토큰을 저장할 필요가 없습니다. 성공적인 인증에 대한 응답으로 만 서버에서 토큰을 즉시 생성합니다. 악의적 인 사용자가 응용 프로그램을 검사하고 무단 API 액세스 권한을 얻으려면 다른 사람과 마찬가지로 인증해야합니다.


흥미로운 솔루션이지만 대부분 OP 고객이 앱을 코딩하는 방법에 의존합니다. 즉, 제안 된 접근 방식은 API 키 서버 측을 저장할 수 있으며 자신의 사용자를 성공적으로 인증 한 후 실제 앱이 사용할 임시 키를 전달할 수 있습니다. 이 방법으로 앱 자체에는 아무것도 저장되지 않습니다.
Newtopian

그것은 모든 API에 해당됩니다. API 소비자가 올바르게 소비하지 않으면 작동하지 않을 수 있습니다. 이것은 API의 문서화 된 부분이어야합니다.
Brandon

그건 그렇고, OAuth와 같이 이것을 쉽게하는 데 도움이되는 표준이 있습니다.
Brandon

0

고유 한 앱별 키가있는 경우 클라이언트가 시작한 초기 연결 인증 중에 만 해당 키를 사용할 수 있으며 그 후에는 롤링 된 앱별 고유 인증 토큰으로 전환 할 수 있습니다.

서버는 때때로 각 클라이언트 앱의 토큰을 변경 (롤)합니다 (예 : 주기적으로 임의의 퍼지 / 임의 지연을 플러스 / 빼기). 롤링 토큰은 서버와 인증 된 클라이언트 사이에서만 알려져 있습니다.

새로운 토큰은 정식 답장에 피기 백으로 반환됩니다. 응답에 새로운 토큰이 포함되어 있으면 수신 앱은 후속 요청에서 토큰을 사용하도록 전환해야합니다.

클라이언트와의 교환이 동기화되지 않을 때 (일부 프로토콜 오류가 발생하면) 서버는 다음 클라이언트 요청에 대한 오류 응답을 통해 재 인증을 요청하거나 클라이언트 요청에 대한 유효한 응답을 피기 백합니다. 예).

롤링 토큰이 활발하게 사용되는 동안 클라이언트가 시작한 초기 인증은 의심으로 간주되어야합니다. 이는 모방 시도 일 수 있습니다. 예를 들어 롤링 토큰이없는 새 인스턴스로 인해 클라이언트 중단 / 재시작으로 인해 예상치 못한 간격으로 교환이 유휴 상태 인 경우에만 허용합니다.

다시 시작한 클라이언트가 이전 버전이 남아 있던 곳에서 계속할 수 있도록 클라이언트 측에 토큰을 유지하는 것이 더 좋습니다.

이러한 체계는 최소한 모방하기가 매우 어려울 것입니다. 승인 된 클라이언트가 서버가 규정 된 키를 사용하여 새 클라이언트 인증을 수락해도된다고 결정하기에 충분한 시간 동안 요청 전송을 중단하면 윈도우를 정확하게 예측해야합니다. 허용 된 창을 벗어난 이러한 요청은 모방 시도 감지 및 일부 대책 (IP 블랙리스트 등)을 시작할 수 있습니다.


0

내가 아는 것 중에서, 당신이 언급 한 것은 이것을하는 유일한 방법입니다. 키를 저장하는 응용 프로그램은 확실히 위험하지만이를 우회하는 다양한 방법이 있습니다. 키 스토어를 사용하여 하드 코딩보다 키를 저장하여 한 번 로그인 할 수 있습니다.

또한 클라이언트에 키를 바인딩하는 것을 고려해야합니다. 따라서 누군가가 모방하는 경우 클라이언트, 키 및 사용자 에이전트를 확인하여 요청을 즉시 차단할 수있는 보안 계층이 있어야합니다. 키를 모방하지 않았는지 재발급하거나 재확인 할 수있는 유스 케이스가 있어야합니다.


JavaScript에 대한 해결 방법은 무엇입니까? 그것을 위해 설계하는 방법?
Alok Patel

하이브리드 응용 프로그램을 만드는 것에 대해 이야기하고 있다고 가정합니다. 그렇다면 키를 저장하는 플러그인을 만들 수 있어야합니다. 응용 프로그램을 호스팅하고 모바일 웹 솔루션에 대해 이야기하려는 경우 컨테이너를 사용하여 페이지를 렌더링하는 것에 대해 생각하고 앞에서 제안한 세션 토큰을 사용할 수 있습니다.
Arun

그렇지 않습니다. 나는 세 번째 최고의 API 제공 업체가 될 것이며, 사용자는 자신의 응용 프로그램에서 내 API 서비스를 사용합니다. 그것은 안드로이드, iOS, JavaScript 등이 될 수 있습니다 ...
Alok Patel

0

고객에게 앱에 넣을 수있는 권한 부여 토큰을 제공하는 경우 이론적으로 누군가가 앱을 리버스 엔지니어링하고 추출 할 수 있습니다. 이를 방지하려면 클라이언트 앱 내에서 비밀을 요구하지 않는 메커니즘이 필요합니다. 까다 롭습니다. 나는 당신이 생각할 수있는 몇 가지 옵션을 제안 할 수 있습니다.

자격 증명을 제공하면 문제가 있으며 자격 증명이 얼마나 안전하게 저장되는지 제어 할 수 없습니다. 또한 사용자에게 자격 증명을 보내도록 요구하는 경우 누군가가 앱을 리버스 엔지니어링하지 않고도 연결을 MITM하고 토큰을 직접 훔칠 수 있습니다.

인증 토큰을 추출하기 어렵게 만드는 한 가지 방법은 난독 처리하는 것입니다. 이것은 막대를 높이지만 불가능하지는 않으며 비밀을 통제해야합니다. 비밀 정보를 포함하고 각 고객에 고유 한 라이브러리를 구현할 수 있습니다. 라이브러리를 사용하여 서버와 통신 할 수 있으며 사용자에게 비밀 정보를 알려주지 않아도 라이브러리에 내장 될 수 있습니다. 이렇게하면 누군가 라이브러리를 리버스 엔지니어링하는 문제를 해결할 수 없지만 난독 화 수준을 제어 할 수 있습니다. 단점은 한 사람이 라이브러리의 난독 처리를 중단 한 후에는 각 라이브러리를 크게 다르게 만드는 코드를 작성하지 않는 한 모든 라이브러리를 공격 할 수 있다는 것입니다. 그것은 그 자체의 문제 세트를 소개합니다.

이것은 귀하의 질문의 범위에서 약간 벗어날 수 있지만 토큰의 보안과 관련이 있으므로 언급하겠습니다. 와이어를 통한 토큰의 사소한 도난을 방지하기 위해 토큰을 직접 보내지 않고 HMAC 기능을 사용하여 트래픽에 서명 할 수 있습니다. 서버에서 메시지의 HMAC를 계산하고이를 클라이언트에서 보낸 HMAC와 비교하여 메시지 유효성을 확인할 수 있습니다. 토큰을 HMAC 기능의 키로 사용하여 토큰을 아는 사람 만 트래픽에 서명 할 수 있습니다. 토큰을 서버로 직접 보내지 않으므로 직접 가로 채거나 도난 당할 수 없으므로 토큰 보안에 좋습니다. HMACS에 대한 자세한 내용은 다음 질문을 참조하십시오. /security/20129/how-and-when-do-i-use-hmac/20301

보안 솔루션은 절대로 존재하지 않습니다. 구현 비용과 피해 가능성 및 비용을 결정해야합니다.


라이브러리를 만들고 비밀을 넣을 수는 없으며 사용자마다 다릅니다.
Alok Patel

명확히하기 위해 각 사용자별로 사용자 정의 라이브러리를 작성하고 라이브러리 내에서 개별 비밀을 숨길 수 있다고 제안했습니다. 당신이 원하는 것보다 더 많은 일을 할 수있는 각각의 새로운 사용자에 대해 필요할 때 자동으로 라이브러리를 생성하기 위해 시스템을 작성해야 할 것입니다.
ThePragmatist

0

자신을 인용 :

클라이언트 / 사용자를 인증하는 방법을 알 수 없습니다 ... 인증을 받기 위해 사용자 이름과 비밀번호를 넣을 수 없습니다.

이제 약간 모순되지 않습니까? ;)

다른 사람들이 말했듯이, 당신은 할 수 없습니다. 앱이 API 키를 사용하는 경우 키를 가져 와서 사용하도록 지시 한대로 API를 디 컴파일 할 수 있습니다.

추가적인 적절한 사용자 인증이 필요한 경우를 제외하고는 피해 만 제한 할 수 있습니다.

  • 화이트리스트 / 블랙리스트 IP
  • 조절
  • "비정상 활동"탐지 및 출처
  • 쉬운 키 갱신
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.