Programing

암호화 된 보안 인증 토큰 생성

crosscheck 2020. 12. 31. 22:50
반응형

암호화 된 보안 인증 토큰 생성


배경:

이것은 실제로 일반적인 모범 사례 질문이지만 특정 상황에 대한 배경 지식이 도움이 될 수 있습니다.

우리는 iPhone 용 "연결된"애플리케이션을 개발하고 있습니다. REST 서비스를 통해 백엔드 애플리케이션과 통신합니다. 사용자가 응용 프로그램을 시작할 때마다 사용자 이름과 암호를 입력하라는 메시지를 표시 할 필요가 없도록 초기 실행시 사용자 이름과 암호를 확인하고 향후 웹에 사용할 수있는 인증 토큰을 반환하는 "로그인"서비스를 노출합니다. 실제 데이터에 대한 서비스 요청. 토큰에는 만료 시간이있을 수 있으며 그 이후에는 사용자 이름 / 비밀번호로 다시 인증하도록 요청할 것입니다.

질문:

인증에 사용할 이러한 종류의 토큰을 생성하는 모범 사례는 무엇입니까?

예를 들어, 우리는 ...

  • 임의의 문자열을 해시 (SHA-256 등)하고 만료 날짜와 함께 지정된 사용자의 데이터베이스에 저장합니다. 후속 요청에서 토큰을 간단히 조회하여 일치하는지 확인하십시오.
  • 사용자 ID와 일부 추가 정보 (타임 스탬프 등)를 비밀 키로 암호화합니다. 후속 요청에서 토큰을 해독하여 당사에서 발행했는지 확인하십시오.

이것은 해결 된 문제인 것 같습니다.


이 질문에 대한 다른 답변, 추가 연구 및 오프라인 토론의 피드백을 기반으로하여 최종적으로 수행 한 작업은 다음과 같습니다.

여기서 상호 작용 모델은 "기억하기"확인란을 선택했을 때 ASP.NET의 폼 인증에서 사용하는 모델과 본질적으로 정확히 동일하다는 사실이 매우 빠르게 지적되었습니다. HTTP 요청을 만드는 것은 웹 브라우저가 아닙니다. 우리의 "티켓"은 양식 인증이 설정하는 쿠키와 동일합니다. 양식 인증은 기본적으로 기본적으로 "비밀 키로 일부 데이터 암호화"접근 방식을 사용합니다.

로그인 웹 서비스에서 다음 코드를 사용하여 티켓을 만듭니다.

string[] userData = new string[4];

// fill the userData array with the information we need for subsequent requests
userData[0] = ...; // data we need
userData[1] = ...; // other data, etc

// create a Forms Auth ticket with the username and the user data. 
FormsAuthenticationTicket formsTicket = new FormsAuthenticationTicket(
    1,
    username,
    DateTime.Now,
    DateTime.Now.AddMinutes(DefaultTimeout),
    true,
    string.Join(UserDataDelimiter, userData)
    );

// encrypt the ticket
string encryptedTicket = FormsAuthentication.Encrypt(formsTicket);

그런 다음 요청에 대한 HTTP 헤더에서 유효한 티켓을 확인하는 IParameterInspector를 추가하는 WCF 서비스에 대한 작업 동작 특성이 있습니다. 개발자는 인증이 필요한 작업에이 작업 동작 특성을 추가합니다. 이 코드가 티켓을 구문 분석하는 방법은 다음과 같습니다.

// get the Forms Auth ticket object back from the encrypted Ticket
FormsAuthenticationTicket formsTicket = FormsAuthentication.Decrypt(encryptedTicket);

// split the user data back apart
string[] userData = formsTicket.UserData.Split(new string[] { UserDataDelimiter }, StringSplitOptions.None);

// verify that the username in the ticket matches the username that was sent with the request
if (formsTicket.Name == expectedUsername)
{
    // ticket is valid
    ...
}

자신 만의 인증 시스템을 구축하는 것은 항상 "최악의 관행"입니다. 이는 인증 시스템을 전문으로하는 전문가에게 가장 잘 남겨진 종류입니다.

기존의 것을 재사용하는 대신 자신 만의 "로그인 서비스에서 만료되는 티켓"아키텍처를 구축하는 데 관심이 있다면 적어도 Kerberos와 같은 유사한 시스템의 설계를 주도한 문제에 익숙해지는 것이 좋습니다. . 여기에 부드러운 소개가 있습니다.

http://web.mit.edu/kerberos/dialogue.html

또한 지난 20 년 동안 Kerberos (및 유사 시스템)에서 발견 된 보안 허점을 살펴보고 복제하지 않도록하는 것도 좋은 생각입니다. Kerberos는 보안 전문가에 의해 구축되었으며 수십 년 동안 신중하게 검토되었지만 여전히 다음과 같은 심각한 알고리즘 결함이 발견되고 있습니다.

http://web.mit.edu/kerberos/www/advisories/MITKRB5-SA-2003-004-krb4.txt

It's a lot better to learn from their mistakes than your own.


Amazon.com uses a HMAC SHA-1 message token to authenticate and authorize requests. They use this for a fairly large commercial service, so I'd be liable to trust their engineering decisions. Google publishes the OpenSocial API which is somewhat similar. Based on Google and Amazon.com using similar and openly published approaches to securing web requests, I suspect these are probably good ways to go.


Either of the two answers you've provided will suffice. You may find frameworks out there that do this for you, but the truth is it's not that hard to build. (Every company I've worked for has rolled their own.) The choice of database-stored tokens versus encrypted data "cookies" is an architectural decision -- do you want to incur a database lookup on every page view, or would you rather chew up CPU with cookie decryption? In most applications, using encrypted cookies provides a performance win at scale (if that's a concern). Otherwise it's just a matter of taste.


Since you're using WCF, you have a variety of options if using CFNetwork -- for instance NTLM or Digest Authentication:

http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/Concepts/Concepts.html#//apple_ref/doc/uid/TP30001132-CH4-SW7

I know this doesn't answer your specific question, but I have also been faced with this problem (iPhone - Tomcat) and decided to use the authentication services on the web server as much as possible. There's no significant penalty for including the authentication information with each request in most cases. A quick Google turns up lots of blog posts about WCF and RESTful services (and some related questions on StackOverflow).

Hope this helps!


You should implement:

  1. OAuth2 Implicit Grant - for third-party applications http://tools.ietf.org/html/rfc6749#section-1.3.2
  2. OAuth2 Resource Owner Password Credentials — for your own mobile application http://tools.ietf.org/html/rfc6749#section-1.3.3

which are exactly the workflows, from OAuth2, that you are looking for. Do not reinvent the wheel.


This simply sounds like a session identifier with a long expiration time. The same principles used for this in web applications could apply here.

Rather than encoding information, session identifiers are randomly chosen from a very large space (128 bits). The server keeps a record associating the session identifier with the user and other desired information such as expiration time. The client presents the session identifier over a secure channel with each request.

Security relies on the unpredictability of the session identifiers. Generate them with a cryptographic RNG, from a very large space.

ReferenceURL : https://stackoverflow.com/questions/840537/generating-cryptographically-secure-authentication-tokens

반응형