2013-03-14 24 views
5

Próbuję skonfigurować przycisk Sign in with Google, który pozwoli użytkownikom kupować rzeczy na mojej stronie internetowej.Uwierzytelnianie użytkowników G + po stronie serwera, po zalogowaniu po stronie klienta

Uwierzytelnianie po stronie klienta wygląda dość prosto, ale staram się zrozumieć, jak działa uwierzytelnianie po stronie serwera. W wersji example code przekazują do serwera parametr "kodowy" po stronie klienta, w którym można go sprzedać za token dostępu, który można następnie wykorzystać do wyświetlenia listy znajomych użytkownika.

Ale nie chcę widzieć listy znajomych użytkownika. Chcę tylko mieć pewność, że klient jest tym, za kogo się podają.

Po pobraniu tokena, przykładowy kod umieszcza token w sesji i wydaje się wykorzystywać obecność tokena do sprawdzenia, czy użytkownik jest uwierzytelniony. Czy to jest poprawne/bezpieczne? Powinien (nie) mój serwer ponownie weryfikuje token (jak?), Kiedy nadszedł czas na zakup? Czy muszę ciągle weryfikować token w Google przy każdym żądaniu? (Mam nadzieję, że nie?)

+0

Opublikowaliśmy pokrewne pytanie, ponieważ uważam, że standardowym sposobem zrobienia tego za pomocą interfejsu API Facebooka jest użycie parametru signed_request, ale wygląda na to, że Google nie ma odpowiednika. http://stackoverflow.com/questions/15395142/does-google-javascript-api-have-an-equivalent-to-facebooks-signed-request –

Odpowiedz

2

Co należy zrobić przed dokonaniem zakupu, to sprawdzić, czy użytkownik jest tym, którego się spodziewa, poprzez bezpieczne przekazanie identyfikatora użytkownika z klienta na serwer i zweryfikowanie go pod kątem identyfikatora użytkownika dla zapisanych poświadczeń. Zapewnia to dodatkową ochronę przed atakami typu "powtórka", gdy atakujący podszywa się pod sesję użytkownika i jest najbardziej odpowiednią sprawą przed zaakceptowaniem płatności od użytkownika.

Nie będę polegać wyłącznie na walidacji użytkownika jako mechanizmie ochrony przed oszustwami. Powinieneś użyć bezpiecznego systemu płatności, takiego jak Google Commerce platform i postępować zgodnie z the best practices for commerce.

Jako przypomnienie, punkt końcowy OAuth2 v2 powinien być używany do sprawdzania tokena za każdym razem, gdy inicjowane są buforowane poświadczenia. Sprawdzenie każdego żądania wydaje się nieco przesadzone, ponieważ powinno się używać poświadczeń przechowywanych w pamięci podręcznej, które zostały już sprawdzone i zapisane po stronie serwera. Co najwyżej można przeprowadzić sprawdzanie podczas aktualizowania tokena dostępu, ale jeśli ufasz tokenowi odświeżania, powinieneś być wystarczająco bezpieczny, jeśli wykonasz sprawdzenia podczas tworzenia konta i ustawisz token odświeżania.

Następujące kroki są podejmowane oprócz weryfikacji identyfikatora użytkownika podczas tworzenia konta:

  • Sprawdź, czy klient jest kim można się spodziewać, że będzie. Chroni przed fałszywymi tokenami dostępu przekazywanymi do Twojej aplikacji w celu efektywnego wysyłania żądań w imieniu atakującego przy użyciu limitu.
  • Sprawdź, czy konto zostało utworzone przez aplikację, to protects you and your users against cross-site request forgery w przypadkach, gdy dodatkowe konta są tworzone w imieniu użytkownika.

Jak wspomniano w Twoim postingu, przykładowy kod w wersji the Google+ quickstarts powinien wystarczająco demonstrować sposób przeprowadzania tych kontroli w różnych językach programowania w celu autoryzacji konta.

W HTML/klient JS poniższy kod pokazuje, gdzie identyfikator użytkownika (wartość, w przeciwieństwie do specjalnego napisu „ja”) jest pobierany na przejście do metody connect zweryfikować Google+ userid:

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>')); 
     } 
    }); 

... a poniższy kod zawiera identyfikator Google+.

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 
    }); 
} 

Odpowiedni kod wykonywania tych kontroli w próbce Java jest następujący:

 // 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()); 
    } 

W próbek, ClientID przyszedł z konsoli Google API i będzie odrębny dla danej aplikacji.

+0

1) "przekazując identyfikator użytkownika" masz na myśli parametr "code"? Lub identyfikator użytkownika? 2) "weryfikując go względem zapisanych poświadczeń" przykładowy kod nie przechowuje referencji. Co dokładnie powinno się przechowywać? Jak długo? (Baza danych? Sesja?) Bardziej filozoficznie, próbki kodu wydają się nie robić tego, co sugerujesz. Czy oni? Które linie (powiedzmy) Java próbki robią to, co mówisz? –

+0

1) W metodzie connect klienta HTML/JS przykładowego (index.html) zauważysz, że identyfikator Google+ jest przekazywany jako parametr GET i weryfikowany przy użyciu informacji o tokenach. 2) Próbki * symulują * operację przechowywania poświadczeń użytkownika przy użyciu pamięci sesji i odtworzenia stanu autoryzacji za pomocą zapisanego tokenu dostępu/odświeżenia. Odświeżający token nie wygasa, więc powinien być bezpiecznie utrzymywany, chyba że użytkownik rozłączy swoje konto. Token dostępu wygasa po 3600 sekundach, więc powinien zostać zaktualizowany dopiero po wygaśnięciu. Linie 153-183 przeprowadzają kontrole w próbce Java. – class

+0

Jeden końcowy komentarz, jeśli chcesz zobaczyć bardziej wyczerpujący przykład tego, jak należy zachować tokeny i dane uwierzytelniające, próbki PhotoHunt będą lepiej to demonstrować. Spójrz na saveTokenForUser tutaj: https://github.com/googleplus/gplus-photohunt-server-java/blob/master/src/com/google/plus/samples/photohunt/ConnectServlet.java – class

Powiązane problemy