2013-03-14 4 views
5

사람들이 내 웹 사이트에서 물건을 구입할 수 있도록 Sign in with Google 버튼을 설정하려고합니다.클라이언트 측 로그인 후 서버 측 G + 사용자 인증

클라이언트 측 인증은 매우 간단 해 보이지만 서버 측 인증이 어떻게 작동하는지 이해하기가 어렵습니다. example code에서는 클라이언트 측 "code"매개 변수를 서버에 전달합니다.이 매개 변수는 액세스 토큰에 대해 거래 될 수 있으며, 사용자 토큰을 사용하여 사용자의 친구 목록을 볼 수 있습니다.

하지만 사용자의 친구 목록을보고 싶지 않습니다. 나는 그 고객이 실제로 그들이 누구라고 주장하는지 확실히하고 싶다.

샘플 코드는 토큰을 검색 한 후 세션에 토큰을 넣고 토큰 존재를 사용하여 사용자가 인증되었는지 확인합니다. 그게 정확하고 안전합니까? 구매할 때 내 서버가 토큰을 어떻게 다시 확인해야합니까 (어떻게?)? 요청할 때마다 Google과 토큰을 지속적으로 다시 확인해야합니까? (바라지는 않겠지 만)

+0

페이스 북 API로 표준화 된 방법으로 signed_request 매개 변수를 사용하는 것이지만, Google에 상응하는 매개 변수가없는 것 같아 관련 질문을 게시했습니다. http://stackoverflow.com/questions/15395142/does-google-javascript-api-have-an-equivalent-to-facebooks-signed-request –

답변

2

구매를하기 전에 할 일은 클라이언트의 사용자 ID를 안전하게 서버에 전달하고 사용자 ID와 비교하여 사용자를 확인하는 것입니다. 저장된 자격 증명. 이는 공격자가 세션을 하이재킹하여 사이트 사용자 인 것처럼 가장하는 재생 공격에 대한 추가 보호 기능을 제공하며 사용자로부터 지불을 수락하기 전에 가장 적절한 수표입니다.

나는 사기로부터 보호하기위한 메커니즘으로 사용자 유효성 확인에만 의존하지 않을 것입니다. Google Commerce platform과 같은 안전한 지불 시스템을 사용하고 the best practices for commerce을 따라야합니다.

캐시 된 자격 증명이 초기화 될 때마다 OAuth2 v2 끝점을 사용하여 토큰을 확인해야합니다. 이미 검증되었고 서버 측에 저장된 캐시 된 신임 정보를 사용해야하므로 모든 요청을 확인하는 것이 약간 과한 것으로 보입니다. 대부분의 경우 액세스 토큰을 업데이트 할 때 검사를 수행 할 수 있지만 새로 고침 토큰을 신뢰하는 경우 계정을 만들 때 검사를 수행하고 새로 고침 토큰을 설정하면 충분히 안전해야합니다.

다음 단계는 계정 생성시 사용자 ID 확인에 추가하여 수행됩니다

  • 는 클라이언트가 당신이 될 것으로 기대 누구인지 확인합니다. 이렇게하면 할당량을 사용하여 공격자를 대신하여 효과적으로 요청하기 위해 앱에 전달되는 위조 된 액세스 토큰으로부터 사용자를 보호 할 수 있습니다.
  • 사용자 대신 추가 계정이 생성되는 경우 응용 프로그램에서 계정이 생성되었는지 확인하십시오 (protects you and your users against cross-site request forgery).

연결된 게시물에서 언급했듯이 the Google+ quickstarts의 샘플 코드는 계정 인증을 위해 다양한 프로그래밍 언어로 이러한 검사를 수행하는 방법을 충분히 보여줍니다. HTML/JS 클라이언트 내에서

다음 코드를 보여줍니다 경우 사용자 ID (값, 특수한 캐릭터 "나"반대)의 Google+ 사용자 ID 확인하기 위해 연결 방법에 전달하는 검색됩니다 :

var request = gapi.client.plus.people.get({'userId' : 'me'}); 
    request.execute(function(profile) { 
     $('#profile').empty(); 
     if (profile.error) { 
     $('#profile').append(profile.error); 
     return; 
     } 
     helper.connectServer(profile.id); 
     $('#profile').append(
      $('<p><img src=\"' + profile.image.url + '\"></p>')); 
     $('#profile').append(
      $('<p>Hello ' + profile.displayName + '!<br />Tagline: ' + 
      profile.tagline + '<br />About: ' + profile.aboutMe + '</p>')); 
     if (profile.cover && profile.coverPhoto) { 
     $('#profile').append(
      $('<p><img src=\"' + profile.cover.coverPhoto.url + '\"></p>')); 
     } 
    }); 

... 다음 코드는 전달되는 Google+ ID를 보여줍니다.다음과 같이 자바 샘플에서이 검사를 수행

connectServer: function(gplusId) { 
    console.log(this.authResult.code); 
    $.ajax({ 
    type: 'POST', 
    url: window.location.href + '/connect?state={{ STATE }}&gplus_id=' + 
     gplusId, 
    contentType: 'application/octet-stream; charset=utf-8', 
    success: function(result) { 
     console.log(result); 
     helper.people(); 
    }, 
    processData: false, 
    data: this.authResult.code 
    }); 
} 

관련 코드는 다음과 같습니다

샘플에서
 // Check that the token is valid. 
     Oauth2 oauth2 = new Oauth2.Builder(
      TRANSPORT, JSON_FACTORY, credential).build(); 
     Tokeninfo tokenInfo = oauth2.tokeninfo() 
      .setAccessToken(credential.getAccessToken()).execute(); 
     // If there was an error in the token info, abort. 
     if (tokenInfo.containsKey("error")) { 
     response.status(401); 
     return GSON.toJson(tokenInfo.get("error").toString()); 
     } 
     // Make sure the token we got is for the intended user. 
     if (!tokenInfo.getUserId().equals(gPlusId)) { 
     response.status(401); 
     return GSON.toJson("Token's user ID doesn't match given user ID."); 
     } 
     // Make sure the token we got is for our app. 
     if (!tokenInfo.getIssuedTo().equals(CLIENT_ID)) { 
     response.status(401); 
     return GSON.toJson("Token's client ID does not match app's."); 
     } 
     // Store the token in the session for later use. 
     request.session().attribute("token", tokenResponse.toString()); 
     return GSON.toJson("Successfully connected user."); 
    } catch (TokenResponseException e) { 
     response.status(500); 
     return GSON.toJson("Failed to upgrade the authorization code."); 
    } catch (IOException e) { 
     response.status(500); 
     return GSON.toJson("Failed to read token data from Google. " + 
      e.getMessage()); 
    } 

는, 클라이언트 ID는 구글 API 콘솔에서 와서 응용 프로그램에 대한 별개의 것입니다.

+0

1) "사용자 ID 전달"은 "코드"매개 변수를 의미합니까? 아니면 사용자 ID? 2) "저장된 자격 증명과 대조하여"샘플 코드는 자격 증명을 저장하지 않습니다. 정확히 무엇을 저장해야합니까? 얼마나 오래? (Database? Session?) 더 철학적으로, 코드 샘플은 내가하는 제안을하지 않는 것 같습니다. 그들은 할? Java 샘플의 어떤 라인이 당신이 말하는 것을 수행합니까? –

+0

1) 샘플 HTML/JS 클라이언트 (index.html)의 connect 메소드에서 Google+ ID가 GET 매개 변수로 전달되고 토큰 정보를 사용하여 확인됨을 알 수 있습니다. 2) 샘플은 세션 저장 공간을 사용하여 사용자의 자격 증명을 저장하고 저장된 액세스/새로 고침 토큰을 사용하여 권한 부여 상태를 다시 만드는 작업을 시뮬레이션 *합니다. 새로 고침 토큰은 만료되지 않으므로 사용자가 계정 연결을 끊지 않으면 안전하게 유지되어야합니다. 액세스 토큰은 3600 초 후에 만료되므로 만료 될 때만 업데이트해야합니다. 153-183 행은 Java 샘플에서 검사를 수행합니다. – class

+0

마지막으로 토큰과 자격 증명을 유지하는 방법에 대한보다 포괄적 인 예를 보려면 PhotoHunt 샘플에서 더 잘 보여줄 것입니다. 여기에서 saveTokenForUser를 확인하십시오. https://github.com/googleplus/gplus-photohunt-server-java/blob/master/src/com/google/plus/samples/photohunt/ConnectServlet.java – class

관련 문제