Logowanie przez Google w aplikacjach po stronie serwera

Aby korzystać z usług Google w imieniu użytkownika, gdy jest on offline, musisz: użyj hybrydowego przepływu po stronie serwera, w którym użytkownik autoryzuje aplikację na kliencie; za pomocą klienta JavaScript API i wysyłasz specjalny jednorazowy kod kod autoryzacji do serwera. Twój serwer wymienia ten jednorazowy do uzyskania własnego kodu dostępu i odświeżania tokenów od Google, aby serwer mieć możliwość wykonywania własnych wywołań interfejsu API, co może być wykonywane, gdy użytkownik jest offline. Ten jednorazowy przepływ kodu ma większe zalety w zakresie bezpieczeństwa niż zwykły przepływ po stronie serwera i wysyłać tokeny dostępu do serwera.

Procedura logowania się w celu uzyskania tokena dostępu po stronie serwera aplikacji można znaleźć poniżej.

Kody jednorazowe mają kilka zalet dotyczących bezpieczeństwa. Dzięki kodom udostępnia tokeny bezpośrednio na serwerze bez żadnych pośredników. Chociaż nie zalecamy ujawniania kodów, są one bardzo trudne w użyciu bez tajnego klucza klienta. Nie ujawniaj swojego klienta.

Implementacja jednorazowego kodu

Przycisk logowania przez Google zapewnia zarówno token dostępu, jak i kod autoryzacji. Jest to kod jednorazowy, który serwer może wymieniać z serwerami Google w celu uzyskania tokena dostępu.

Poniższy przykładowy kod pokazuje, jak wykonać w ramach jednorazowego procesu tworzenia kodu.

Uwierzytelnianie logowania przez Google za pomocą jednorazowego kodu wymaga:

Krok 1. Utwórz identyfikator klienta i tajny klucz klienta

Aby utworzyć identyfikator klienta i tajny klucz klienta, utwórz projekt w Konsoli interfejsów API Google. skonfiguruj identyfikator klienta OAuth i zarejestruj źródła JavaScriptu:

  1. Otwórz konsolę interfejsów API Google.

  2. Z menu projektu wybierz istniejący projekt lub utwórz nowy. wybierając Utwórz nowy projekt.

  3. Na pasku bocznym w sekcji „Interfejsy API Services”, wybierz Credentials (Dane logowania) i kliknij Skonfiguruj ekran akceptacji.

    Wybierz Adres e-mail, podaj nazwę produktu i kliknij Zapisz.

  4. Na karcie Dane logowania kliknij menu Utwórz dane logowania. i wybierz Identyfikator klienta OAuth.

  5. W sekcji Typ aplikacji wybierz Aplikacja internetowa.

    Zarejestruj źródła, z których aplikacja ma dostęp do pola interfejsów API Google. Źródło to unikalna kombinacja protokołu, nazwę hosta i port.

    1. W polu Autoryzowane źródła JavaScript wpisz źródło dla do aplikacji. Możesz podać wiele źródeł, aby umożliwić uruchamianie aplikacji z różnych protokołów, domen i subdomen. Nie można używać symboli wieloznacznych. W przykładzie poniżej drugi adres URL może być adresem produkcyjnym.

      http://localhost:8080
      https://myproductionurl.example.com
      
    2. Pole Autoryzowany identyfikator URI przekierowania nie wymaga podania wartości. Przekieruj Identyfikatory URI nie są używane z interfejsami API JavaScript.

    3. Kliknij przycisk Utwórz.

  6. W wyświetlonym oknie Klient OAuth skopiuj identyfikator klienta. Identyfikator Client-ID umożliwia aplikacji dostęp do włączonych interfejsów API Google.

Krok 2. Umieść na stronie bibliotekę platformy Google

Dołącz następujące skrypty demonstrujące anonimową funkcję, która wstawia skrypt do DOM strony internetowej index.html.

<!-- The top of file index.html -->
<html itemscope itemtype="http://schema.org/Article">
<head>
  <!-- BEGIN Pre-requisites -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">
  </script>
  <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer>
  </script>
  <!-- END Pre-requisites -->

Krok 3. Zainicjuj obiekt GoogleAuth

Wczytaj bibliotekę auth2 i wywołaj funkcję gapi.auth2.init(), aby zainicjować GoogleAuth obiekt. Podaj identyfikator klienta i zakresy, których ma dotyczyć żądanie gdy dzwonisz pod numer init().

<!-- Continuing the <head> section -->
  <script>
    function start() {
      gapi.load('auth2', function() {
        auth2 = gapi.auth2.init({
          client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
          // Scopes to request in addition to 'profile' and 'email'
          //scope: 'additional_scope'
        });
      });
    }
  </script>
</head>
<body>
  <!-- ... -->
</body>
</html>

Krok 4. Dodaj do swojej strony przycisk logowania

Dodaj do swojej strony internetowej przycisk logowania i dołącz moduł obsługi kliknięć, aby zadzwonić grantOfflineAccess() aby rozpocząć jednorazowy przepływ kodu.

<!-- Add where you want your sign-in button to render -->
<!-- Use an image that follows the branding guidelines in a real app -->
<button id="signinButton">Sign in with Google</button>
<script>
  $('#signinButton').click(function() {
    // signInCallback defined in step 6.
    auth2.grantOfflineAccess().then(signInCallback);
  });
</script>

Krok 5. Zaloguj się na konto użytkownika

Użytkownik klika przycisk logowania i przyzna aplikacji uprawnienia dostępu o które prosisz. Następnie funkcja wywołania zwrotnego określona w tagu Metoda grantOfflineAccess().then() jest przekazywana do obiektu JSON za pomocą funkcji kodu autoryzacji. Na przykład:

{"code":"4/yU4cQZTMnnMtetyFcIWNItG32eKxxxgXXX-Z4yyJJJo.4qHskT-UtugceFc0ZRONyF4z7U4UmAI"}

Krok 6. Wyślij kod autoryzacji na serwer

code to Twój jednorazowy kod, który Twój serwer może wymienić na własny token dostępu i token odświeżania. Token odświeżania możesz uzyskać dopiero po zostało wyświetlone okno autoryzacji z prośbą o dostęp offline. Jeśli parametr select-account prompt został określony w OfflineAccessOptions. w kroku 4 musisz zapisać pobrany token odświeżania do późniejszego użycia bo kolejne giełdy zwracają null dla tokena odświeżania. Ten proces zapewnia większe bezpieczeństwo w porównaniu ze standardowym przepływem OAuth 2.0.

Tokeny dostępu są zawsze zwracane wraz z wymianą prawidłowej autoryzacji w kodzie.

Poniższy skrypt definiuje funkcję wywołania zwrotnego dla przycisku logowania. Kiedy logowanie się powiedzie, funkcja przechowuje token dostępu po stronie klienta. używanie i wysyłanie jednorazowego kodu na serwer w tej samej domenie.

<!-- Last part of BODY element in file index.html -->
<script>
function signInCallback(authResult) {
  if (authResult['code']) {

    // Hide the sign-in button now that the user is authorized, for example:
    $('#signinButton').attr('style', 'display: none');

    // Send the code to the server
    $.ajax({
      type: 'POST',
      url: 'http://example.com/storeauthcode',
      // Always include an `X-Requested-With` header in every AJAX request,
      // to protect against CSRF attacks.
      headers: {
        'X-Requested-With': 'XMLHttpRequest'
      },
      contentType: 'application/octet-stream; charset=utf-8',
      success: function(result) {
        // Handle or verify the server response.
      },
      processData: false,
      data: authResult['code']
    });
  } else {
    // There was an error.
  }
}
</script>

Krok 7. Wymień kod autoryzacji na token dostępu

Wymieniaj kod autoryzacji na serwerze na tokeny dostępu i odśwież. Użyj do wywoływania interfejsów API Google w imieniu użytkownika oraz opcjonalnie token odświeżania, aby uzyskać nowy token dostępu po jego wygaśnięciu.

Jeśli poprosisz o dostęp do profilu, otrzymasz też token tożsamości zawierający podstawowe informacje profilowe użytkownika.

Na przykład:

Java
// (Receive authCode via HTTPS POST)


if (request.getHeader("X-Requested-With") == null) {
  // Without the `X-Requested-With` header, this request could be forged. Aborts.
}

// Set path to the Web application client_secret_*.json file you downloaded from the
// Google API Console: https://console.cloud.google.com/apis/credentials
// You can also find your Web application client ID and client secret from the
// console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest
// object.
String CLIENT_SECRET_FILE = "/path/to/client_secret.json";

// Exchange auth code for access token
GoogleClientSecrets clientSecrets =
    GoogleClientSecrets.load(
        JacksonFactory.getDefaultInstance(), new FileReader(CLIENT_SECRET_FILE));
GoogleTokenResponse tokenResponse =
          new GoogleAuthorizationCodeTokenRequest(
              new NetHttpTransport(),
              JacksonFactory.getDefaultInstance(),
              "https://oauth2.googleapis.com/token",
              clientSecrets.getDetails().getClientId(),
              clientSecrets.getDetails().getClientSecret(),
              authCode,
              REDIRECT_URI)  // Specify the same redirect URI that you use with your web
                             // app. If you don't have a web version of your app, you can
                             // specify an empty string.
              .execute();

String accessToken = tokenResponse.getAccessToken();

// Use access token to call API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Drive drive =
    new Drive.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
        .setApplicationName("Auth Code Exchange Demo")
        .build();
File file = drive.files().get("appfolder").execute();

// Get profile info from ID token
GoogleIdToken idToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = idToken.getPayload();
String userId = payload.getSubject();  // Use this value as a key to identify a user.
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
Python
from apiclient import discovery
import httplib2
from oauth2client import client

# (Receive auth_code by HTTPS POST)


# If this request does not have `X-Requested-With` header, this could be a CSRF
if not request.headers.get('X-Requested-With'):
    abort(403)

# Set path to the Web application client_secret_*.json file you downloaded from the
# Google API Console: https://console.cloud.google.com/apis/credentials
CLIENT_SECRET_FILE = '/path/to/client_secret.json'

# Exchange auth code for access token, refresh token, and ID token
credentials = client.credentials_from_clientsecrets_and_code(
    CLIENT_SECRET_FILE,
    ['https://www.googleapis.com/auth/drive.appdata', 'profile', 'email'],
    auth_code)

# Call Google API
http_auth = credentials.authorize(httplib2.Http())
drive_service = discovery.build('drive', 'v3', http=http_auth)
appfolder = drive_service.files().get(fileId='appfolder').execute()

# Get profile info from ID token
userid = credentials.id_token['sub']
email = credentials.id_token['email']