모바일 애플리케이션을위한 API 작성-인증 및 권한


189

개요

내 응용 프로그램에 대한 (REST) ​​API를 만들려고합니다. 초기 / 1 차 목적은 모바일 앱 (iPhone, Android, Symbian 등)이 소비하는 것입니다. 웹 기반 API의 인증 및 권한 부여에 대한 다른 메커니즘을 조사했습니다 (다른 구현을 연구함으로써). 나는 기본 개념의 대부분을 머리에 감쌌지만 여전히 몇 가지 영역에서 지침을 찾고 있습니다. 내가하고 싶은 마지막 일은 바퀴를 재창조하는 것이지만 내 기준에 맞는 표준 솔루션을 찾지 못했습니다 (그러나 내 기준이 잘못 인도되었으므로 자유롭게 비판하십시오). 또한 API를 사용하는 모든 플랫폼 / 응용 프로그램에서 API가 동일하기를 원합니다.

oAuth

내가 제안한 첫 번째 해결책이 될 것임을 알기 때문에 계속해서 oAuth에 대한 이의를 제기 할 것입니다. 모바일 응용 프로그램 (또는 웹 이외의 응용 프로그램)의 경우 인증을 위해 응용 프로그램을 웹 브라우저로 두는 것은 잘못된 것 같습니다. 또한 브라우저가 콜백을 응용 프로그램 (특히 크로스 플랫폼)으로 반환 할 수있는 방법이 없습니다. 나는 그것을하는 몇 가지 응용 프로그램을 알고 있지만 잘못 느꼈고 응용 프로그램 UX에서 휴식을줍니다.

요구 사항

  1. 사용자는 응용 프로그램에 사용자 이름 / 암호를 입력합니다.
  2. 모든 API 호출은 호출 애플리케이션으로 식별됩니다.
  3. 오버 헤드는 최소한으로 유지되며 인증 측면은 개발자에게 직관적입니다.
  4. 이 메커니즘은 최종 사용자 (로그인 자격 증명이 노출되지 않음)와 개발자 (응용 프로그램 자격 증명이 노출되지 않음) 모두에 대해 안전합니다.
  5. 가능하면 https를 요구하지 마십시오 (어려운 요구 사항은 아님).

구현에 대한 나의 현재 생각

외부 개발자는 API 계정을 요청합니다. 그들은 apikey와 apisecret을 받게됩니다. 모든 요청에는 최소한 세 개의 매개 변수가 필요합니다.

  • apikey-등록시 개발자에게 제공
  • 타임 스탬프-지정된 apikey에 대한 각 메시지의 고유 식별자로 두 배로 증가
  • 해시-타임 스탬프의 해시 + apisecret

요청을 발행하는 응용 프로그램을 식별하려면 apikey가 필요합니다. 타임 스탬프는 oauth_nonce와 유사하게 작동하며 재생 공격을 방지 / 완화합니다. 해시는 지정된 apikey의 소유자로부터 요청이 실제로 발행되도록합니다.

인증 된 요청 (사용자를 대신하여 수행 된 요청)의 경우 여전히 access_token 경로 또는 사용자 이름과 암호 해시 콤보를 사용하는 것으로 결정되지 않았습니다. 어느 쪽이든 어느 시점에서 사용자 이름 / 암호 콤보가 필요합니다. 따라서 그렇게 할 때 여러 정보 (apikey, apisecret, timestamp) + 암호의 해시가 사용됩니다. 이 부분에 대한 의견을 듣고 싶습니다. 참고로, 해싱없이 암호를 시스템에 저장하지 않기 때문에 암호를 먼저 해시해야합니다.

결론

참고로, 이는 일반적으로 응용 프로그램 내에서만 인증 및 권한 부여를 처리하는 방법 만 API를 빌드 / 구조화하는 방법에 대한 요청이 아닙니다.

임의의 생각 / 보너스 질문

요청의 일부로 apikey 만 필요한 API의 경우, apikey 소유자 이외의 다른 사람이 apikey를 보지 못하도록하고 (정확하게 보내진 이후) 과도한 요청을하여 사용량 제한을 초과하도록하려면 어떻게해야합니까? 어쩌면 나는 이것을 생각하고 있지만 apikey 소유자에게 요청이 확인되었다는 것을 인증 해야하는 것이 없어야합니까? 필자의 경우, 그것은 apisecret의 목적이었습니다. 해시되지 않고 표시 / 전송되지 않습니다.

해시라고하면 MD5 대 hmac-sha1은 어떻습니까? 충분히 긴 데이터 (예 : apisecret)로 모든 값을 해시하는 것이 실제로 중요합니까?

이전에는 사용자 / 해당 소금을 사용자 암호 해시에 추가하는 것을 고려하고있었습니다. 그렇게하려면 응용 프로그램에서 사용되는 소금을 모르고 어떻게 일치하는 해시를 만들 수 있습니까?


1
의견 / 제안을 더 받기를 바랐습니다. 질문이 너무 모호하거나 모호합니까?
jsuggs

6
문제는 완벽하지만 거의 2 년이 지난 후에도 oauth 구현은 비열한 것 같습니다 ... 나는 위에서 논의한 것을 정확히 달성하기 위해 가장 어려운 시간을 보내고 있습니다. 추가 차원이 있습니다. loginName / password 쌍을 사용하고 싶지 않습니다.-android / ios에서 Google ID 확인을 사용하고 싶습니다 (심볼은 WWF에서 "거의 멸종 종"으로 선언 함). 윈도우 모바일 (요즘 뭐라고 부르든간에).
tony gil

8
모든 사람들이 oauth 2.0 ive를 제안하는 것처럼 단계, 요구 사항,하지 말아야 할 것과하지 말아야 할 것을 설명하기 위해 일반적인 영어를 사용하는 명확하고 간단한 튜토리얼 또는 예제를 찾지는 못합니다.
ChuckKelly

2
OAuth2.0의 특정 흐름 (자원 소유자 암호 흐름)을 읽으십시오. 웹 사이트로 리디렉션하지 않습니다. techblog.hybris.com/2012/06/11/…
프랭클린

1
나는 또한 같은 대답을 찾고 있습니다. 최근에 쓰여진 좋은 기사를 찾았습니다. 이게 도움이 되길 바란다. stormpath.com/blog/the-ultimate-guide-to-mobile-api-security
Rails의 새로운 기능

답변:


44

내 프로젝트에서 로그인의 일부를 수행하는 방법은 다음과 같습니다.

  1. 로그인하기 전에 사용자 login_token는 서버에 요청 합니다. 요청시 서버에서 생성 및 저장되며 수명이 제한 될 수 있습니다.

  2. 응용 프로그램에 로그인하면 사용자 비밀번호의 해시를 계산 한 다음 비밀번호를로 해시하여 login_token값을 얻은 다음 login_token및 해시를 모두 반환합니다 .

  3. 서버 login_token는 생성 한 서버를 확인하여 유효한 목록에서 제거합니다 login_token. 그런 다음 서버는 저장된 사용자 비밀번호의 해시 login_token를와 결합하여 제출 된 결합 토큰과 일치하는지 확인합니다. 일치하면 사용자를 인증 한 것입니다.

이것의 장점은 서버에 사용자의 비밀번호를 저장하지 않으며, 비밀번호는 일반 비밀번호로 전달되지 않으며, 비밀번호 해시는 계정 생성시 일반 비밀번호로만 전달된다는 것입니다. login_token사용 중 DB에서 제거 되므로 재생 공격으로부터 안전 합니다.


감사합니다. 응용 프로그램 측에서 암호 해싱에 대한 부분을 추가하는 것을 잊었습니다. 사용자 비밀번호를 명확하게 저장하지 않습니다 (저장하기 전에 해시).
jsuggs

2
이 방법의 단점은 DB에 소금 암호를 저장할 수 없다는 것입니다. 공격자가 DB에 손을 대면 암호를 해독 할 필요가 없습니다. 비밀번호 해시는이 체계에서 실제 비밀번호이므로
sigod

2
@sigod 당신이 맞습니다. 기본적인 이분법이 있다고 생각 하지만 , 운송 수단을 신뢰하거나 스토리지를 신뢰해야합니다. 솔트 된 암호를 사용하는 로그인 시스템은 전송 계층을 신뢰하므로 암호를 사용자의 인증 시스템으로 전달하십시오. 이 사례는 전송 계층을 신뢰하지 않습니다 (타겟팅 한 플랫폼이 SHTTP를 잘못 지원했기 때문이라고 생각합니다). 전송 계층을 신뢰하면 다른 절충안을 만들 수 있습니다.
Michael Anderson

3 가지 문제가 있습니다. 1) 사용자의 비밀번호가 서버에 어떻게 저장되지 않습니까? 2 단계에서 해시 된 사용자의 비밀번호를 저장한다고 언급했습니다. 2) 사용자 비밀번호는 절대로 공개되지 않습니다. 그러나 실제로 클라이언트에서 해시 된 다음 서버에서 해시 된 암호와 비교합니다.이 암호는 명확한 암호로 전달하고 저장하는 것과 거의 동일합니다. 3)이 방법은 공격자가 login_token + password가 해시되는 방법을 모른다고 가정하여 Kerckhoff의 원칙을 위반하여 실제로 안전하지 않은 것으로 가정합니다.
Tamer Shlash

14

그것은 하나의 질문에 대한 많은 질문입니다. 많은 사람들이 끝까지 모든 것을 읽을 수 없었습니다. :)

웹 서비스 인증에 대한 나의 경험은 사람들이 일반적으로 그것을 과도하게 엔지니어링한다는 것입니다. 문제는 웹 페이지에서 겪는 것과 동일합니다. 가능한 매우 간단한 옵션은 로그인 단계에 https를 포함하고, 토큰을 반환하며, 향후 요청에 포함되도록 요구합니다. http 기본 인증을 사용하고 헤더에 내용을 전달할 수도 있습니다. 보안을 강화하려면 토큰을 자주 교체 / 만료하고 동일한 IP 블록에서 요청이 들어오는 지 확인하십시오 (모바일 사용자가 셀 사이를 이동할 때 혼란 스러울 수 있음). API 키 또는 이와 유사한 기능을 결합하십시오. 또는 사용자를 인증하기 전에 oauth의 "요청 키"단계를 수행하고 (누군가 이미 이전 답변에서이를 제안했으며 좋은 아이디어입니다) 액세스 토큰을 생성하는 데 필요한 키로 사용하십시오.

내가 아직 사용하지 않은 대안이지만 oAuth에 대한 장치 친화적 인 대안으로 많이 들었습니다 . xAuth 입니다. 그것을보고 당신이 그것을 사용한다면 나는 당신의 인상이 무엇인지 듣고 싶어 할 것입니다.

해싱의 경우 sha1이 약간 나아지지만 그것에 매달리지 마십시오. 장치가 쉽게 (그리고 성능 적으로 빨리) 구현할 수있는 것은 무엇이든 괜찮을 것입니다.

희망은 행운을 빕니다 :)


답변 주셔서 감사합니다. xAuth를 살펴본 결과 oAuth 설치를 통해 API와 상호 작용하기위한 표준화 된 프로세스를 만들 수있는 경로가 될 수 있습니다.
jsuggs

9

그렇다면 모바일 응용 프로그램의 인증 및 권한 부여 측면을 처리하는 일종의 서버 측 인증 메커니즘이 있습니까?

이것이 사실이라고 가정하면 다음과 같이 접근 할 것입니다 (그러나 'cos 나는 Java 개발자이므로 C # 사람이 다르게 할 것입니다).

RESTful 인증 및 권한 서비스

  1. 도청을 방지하기 위해 HTTPS를 통해서만 작동합니다.
  2. RESTEasy , Spring SecurityCAS 의 조합을 기반으로합니다 (여러 응용 프로그램에서 싱글 사인온하는 경우).
  3. 브라우저 및 웹 지원 클라이언트 응용 프로그램 모두에서 작동합니다.
  4. 사용자가 세부 정보를 편집하고 관리자 (특정 응용 프로그램의 경우)가 권한 수준을 변경할 수있는 웹 기반 계정 관리 인터페이스가 있습니다.

클라이언트 측 보안 라이브러리 / 응용 프로그램

  1. 지원되는 각 플랫폼 (예 : Symbian, Android, iOS 등)에 대해 플랫폼의 고유 언어 (예 : Java, ObjectiveC, C 등)로 보안 라이브러리의 적절한 구현을 작성하십시오.
  2. 라이브러리는 주어진 플랫폼에서 사용 가능한 API를 사용하여 HTTPS 요청 구성을 관리해야합니다 (예 : Java는 URLConnection 등을 사용합니다)
  3. 일반 인증 및 권한 부여 라이브러리 소비자 ( 'co 's all is all)는 특정 인터페이스로 코딩되며 변경이 있어도 마음에 들지 않으므로 매우 유연해야합니다. 스프링 시큐리티와 같은 기존 디자인 선택을 따르십시오.

이제 30,000 피트의 시야가 완성되었으므로 어떻게해야합니까? 글쎄, 브라우저 클라이언트를 사용하여 서버 측에 나열된 기술을 기반으로 인증 및 권한 부여 시스템을 만드는 것은 어렵지 않습니다. 이 프레임 워크는 HTTPS와 함께 인증 프로세스에 의해 생성되고 사용자가 무언가를 원할 때마다 사용되는 공유 토큰 (일반적으로 쿠키로 표시)을 기반으로 안전한 프로세스를 제공합니다. 이 토큰은 요청이 발생할 때마다 클라이언트가 서버에 제공합니다.

로컬 모바일 애플리케이션의 경우 다음을 수행하는 솔루션을 수행 한 것으로 보입니다.

  1. 클라이언트 애플리케이션에는 메소드 호출에 대한 런타임 액세스를 제어하는 ​​정의 된 ACL (Access Control List)이 있습니다. 예를 들어, 지정된 사용자는 메소드에서 콜렉션을 읽을 수 있지만 ACL은 이름에 Q가있는 오브젝트에 대한 액세스 만 허용하므로 콜렉션의 일부 데이터는 보안 인터셉터에 의해 조용히 당겨집니다. Java에서는 간단합니다. 호출 코드에서 Spring Security 주석을 사용하고 적절한 ACL 응답 프로세스를 구현하면됩니다. 다른 언어로, 당신은 당신 자신에 있고 아마도 보안 라이브러리를 호출하는 상용구 보안 코드를 제공해야 할 것입니다. 언어가 AOP (Aspect Oriented Programming)를 지원하는 경우이 상황에서 최대한 활용하십시오.
  2. 보안 라이브러리는 전체 응용 프로그램 목록을 현재 응용 프로그램의 개인 메모리에 캐시하여 연결 상태를 유지할 필요가 없습니다. 로그인 세션의 길이에 따라이 작업은 반복되지 않는 일회성 작업 일 수 있습니다.

무엇을 하든지 자신의 보안 프로토콜을 만들 거나 모호한 보안을 사용 하지 마십시오 . 현재 사용 가능하고 무료 인 알고리즘보다 더 나은 알고리즘을 작성할 수는 없습니다. 또한 사람들은 잘 알려진 알고리즘을 신뢰합니다. 따라서 보안 라이브러리가 SSL, HTTPS, SpringSecurity 및 AES 암호화 토큰의 조합을 사용하여 로컬 모바일 애플리케이션에 대한 권한 부여 및 인증을 제공한다고하면 즉시 시장에서 신용을 얻을 수 있습니다.

이것이 도움이되기를 바랍니다. 더 많은 정보를 원하면 알려주세요-Spring Security, ACL 등을 기반으로 꽤 많은 웹 응용 프로그램을 작성했습니다.


고마워, 좋은 정보. 몇 가지 질문. 먼저, 도청이 허용 가능한지 여부 (확실하지 않은지 확실하지 않은 경우 내 응용 프로그램에 실제 개인 정보 / 귀중한 정보가 없지만 내 근거가 변경된 경우 HTTPS가 실제로 필요합니까)?
jsuggs

원하는 경우 HTTPS 외부에서 전체 시스템을 작동 할 수 있습니다. HTTPS는 비밀 정보 만 보호하기 때문에 인증 단계에서 HTTPS를 통해 사용자 이름 / 암호 / 비밀이 비밀로 유지되도록 보장한다고 가정합니다. 응답에서 토큰을 인계 한 후 스트림에 포함 된 정보 (인증을 위해 필요한 정보)가 도청으로부터 보호 할 필요가없는 경우 추가 요청을 할 수 있습니다.
Gary Rowe

또한 CAS 인증 프로토콜에 대한이 설명이 유용 할 수 있습니다. jasig.org/cas/protocol
Gary Rowe

9

트위터는 xAuth 라고하는 변형을 지원함으로써 oAuth의 외부 애플리케이션 문제를 해결했습니다 . 불행히도이 이름을 가진 수많은 다른 체계가 이미 있으므로 분류하기가 혼란 스러울 수 있습니다.

이 프로토콜 요청 토큰 단계를 건너 뛰고 사용자 이름과 비밀번호를 받으면 즉시 액세스 토큰 쌍을 발행한다는 점을 제외하고 oAuth입니다. ( 여기 에서 E 단계 에서 시작 )이 초기 요청 및 응답 을 보호해야합니다.-사용자 이름과 비밀번호를 일반 텍스트로 보내고 액세스 토큰과 비밀 토큰을 다시받습니다. 액세스 토큰 쌍이 구성되면 초기 토큰 교환이 oAuth 모델을 통한 것인지 또는 xAuth 모델을 통한 것인지는 나머지 세션 동안 클라이언트 및 서버와 관련이 없습니다. 이는 기존 oAuth 인프라를 활용할 수 있고 모바일 / 웹 / 데스크톱 애플리케이션에 대해 거의 동일한 구현을 할 수 있다는 이점이 있습니다. 가장 큰 단점은 응용 프로그램에 클라이언트의 사용자 이름과 암호에 대한 액세스 권한이 부여되지만 요구 사항이이 방법을 요구하는 것처럼 보입니다.

어쨌든, 나는 당신의 직감과 여기에 다른 여러 응답자의 의견에 동의하고 싶습니다 : 처음부터 새로운 것을 만들려고하지 마십시오. 보안 프로토콜은 시작하기 쉽지만 항상 잘 수행하기 어렵고, 복잡성이 높아질수록 타사 개발자가 구현할 가능성이 줄어 듭니다. 가상의 프로토콜은 o (x) Auth-api_key / api_secret, nonce, sha1 hashing과 매우 유사하지만 개발자가 기존 라이브러리를 많이 사용하는 대신 개발자가 직접 롤링해야합니다.


2
또한 '건너 뛰기 요청 토큰'엔드 포인트가 oAuth 2에있는 것처럼 보이고 현재 초안에는 "암호"액세스 권한 부여 유형으로 표시됩니다. 4.1.2 섹션 : tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.2
lantius

내가 Lonra에게 언급 한 것처럼, xAuth에 대해 더 자세히 살펴보고 있습니다. 특히 마지막에 언급 한 이유에 대해 개발자는 "정상적인"oAuth 도구 / lib를 사용하여 API와 상호 작용할 수 있습니다. .
jsuggs

6

파티에 늦었지만 나는이 문제에 관심이있는 사람을 위해 추가 포인트를 던지기를 원했습니다. 저는 모바일 API 보안 솔루션 ( approov )을 수행하는 회사에서 일 하므로이 전체 영역이 제 관심사와 관련이 있습니다.

우선, 모바일 API를 보호하려고 할 때 고려해야 할 가장 중요한 것은 그것이 얼마나 가치가 있는지 입니다. 은행에 적합한 솔루션은 단순히 재미있는 일을하는 사람에게 적합한 솔루션과 다릅니다.

제안 된 솔루션에서 최소 세 개의 매개 변수가 필요하다고 언급했습니다.

  • apikey-등록시 개발자에게 제공
  • 타임 스탬프-지정된 apikey에 대한 각 메시지의 고유 식별자로 두 배로 증가
  • 해시-타임 스탬프의 해시 + apisecret

이는 일부 API 호출의 경우 사용자 이름 / 암호가 필요하지 않음을 의미합니다. 이 기능은 로그인을 강제하지 않으려는 응용 프로그램 (예 : 온라인 상점에서 찾아보기)에 유용 할 수 있습니다.

이것은 사용자 인증과는 약간 다른 문제이며 소프트웨어 인증이나 증명과 비슷합니다. 사용자는 없지만 API에 대한 악의적 인 액세스가 없는지 확인하려고합니다. 따라서 API 시크릿을 사용하여 트래픽에 서명하고 API에 액세스하는 코드를 정품으로 식별합니다. 이 솔루션의 잠재적 인 문제는 모든 버전의 앱 내부에 비밀을 부여해야한다는 것입니다. 누군가 비밀을 추출 할 수 있으면 API를 사용하여 소프트웨어를 가장하면서 원하는대로 할 수 있습니다.

이러한 위협에 대응하기 위해 데이터의 가치에 따라 할 수있는 일이 많이 있습니다. 난독 화 는 비밀을 추출하기 어렵게 만드는 간단한 방법입니다. 당신을 위해, 안드로이드를 위해 그렇게 할 도구가 있지만, 여전히 해시를 생성하는 코드가 있어야하며 충분히 숙련 된 개인은 항상 해싱을 직접 수행하는 함수를 호출 할 수 있습니다.

로그인이 필요없는 API의 과도한 사용을 방지하는 또 다른 방법 은 트래픽 을 제한 하고 의심스러운 IP 주소를 식별하고 차단하는 것입니다. 당신이 가고자하는 노력의 양은 데이터의 가치에 달려 있습니다.

그 외에도 당신은 쉽게 내 일의 영역으로 들어갈 수 있습니다. 어쨌든 중요하다고 생각하고 플래그를 지정하려는 API 보안의 또 다른 측면입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.