Aby korzystać z usług Google w imieniu użytkownika, gdy ten jest offline, musisz użyć hybrydowego procesu po stronie serwera, w którym użytkownik autoryzuje Twoją aplikację po stronie klienta za pomocą klienta interfejsu JavaScript API, a Ty wysyłasz na serwer specjalny jednorazowy kod autoryzacji. Twój serwer wymienia ten kod jednorazowego użytku na tokeny dostępu i odświeżania od Google, aby móc wykonywać własne wywołania interfejsu API, nawet gdy użytkownik jest offline. Ten proces generowania jednorazowego kodu zapewnia lepsze zabezpieczenia niż proces czysto serwerowy i wysyłanie tokenów dostępu na serwer.
Poniżej przedstawiono proces logowania się, który umożliwia uzyskanie tokena dostępu aplikacji po stronie serwera.
Jednorazowe kody mają kilka zalet związanych z bezpieczeństwem. W przypadku kodów Google dostarcza tokeny bezpośrednio na Twój serwer bez pośredników. Nie zalecamy podawania kodów, ale bez tajnego klucza klienta są one bardzo trudne do użycia. Trzymaj tajny klucz klienta w tajemnicy.
Implementacja jednorazowego kodu
Przycisk Zaloguj się przez Google udostępnia zarówno token dostępu, jak i kod autoryzacji. Kod jest kodem jednorazowym, który Twój serwer może wymienić z serwerami Google na token dostępu.
Poniższy przykładowy kod pokazuje, jak wykonać proces jednorazowego kodu.
Aby uwierzytelnić logowanie Google za pomocą kodu jednorazowego:
Krok 1. Utwórz identyfikator klienta i klucz tajny klienta
Aby utworzyć identyfikator klienta i tajny klucz klienta, utwórz projekt Konsoli interfejsów API Google, skonfiguruj identyfikator klienta OAuth i zarejestruj źródła JavaScript:
Otwórz konsolę interfejsów API Google.
W menu Projekt wybierz istniejący projekt lub utwórz nowy, klikając Utwórz nowy projekt.
Na pasku bocznym w sekcji „Interfejsy API i usługi” wybierz Dane logowania, a następnie kliknij Skonfiguruj ekran zgody.
Wybierz adres e-mail, określ nazwę produktu i kliknij Zapisz.
Na karcie Dane logowania kliknij menu Utwórz dane logowania i wybierz Identyfikator klienta OAuth.
W sekcji Typ aplikacji wybierz Aplikacja internetowa.
W ten sposób zarejestruj źródła, z których Twoja aplikacja może uzyskiwać dostęp do interfejsów API Google: Źródło to niepowtarzalne połączenie protokołu, nazwy hosta i portu.
W polu Autoryzowane źródła JavaScript wpisz źródło aplikacji. Możesz podać wiele źródeł, aby umożliwić uruchamianie aplikacji za pomocą 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 URL wersji produkcyjnej.
http://localhost:8080 https://myproductionurl.example.com
Pole Autoryzowany identyfikator URI przekierowania nie wymaga wartości. Adresy URI przekierowania nie są używane w interfejsach JavaScript API.
Naciśnij przycisk Utwórz.
W wyświetlonym oknie Klient OAuth skopiuj identyfikator klienta. Identyfikator klienta umożliwia aplikacji dostęp do włączonych interfejsów API Google.
Krok 2. Uwzględnij na stronie bibliotekę platformy Google
Umieść poniższe skrypty, które demonstrują anonimową funkcję, która wstawia skrypt do modelu DOM tej 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. Inicjuj obiekt GoogleAuth
Wczytaj bibliotekę auth2 i wywołaj funkcję gapi.auth2.init()
, aby zainicjować obiekt GoogleAuth
. Podczas wywołania funkcji init()
podaj identyfikator klienta i zakresy, których chcesz użyć.
<!-- 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 przycisk logowania do swojej strony internetowej i dołącz do niego uchwyt kliknięcia, aby wywołać funkcję grantOfflineAccess()
, która rozpocznie proces weryfikacji za pomocą kodu jednorazowego.
<!-- 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 użytkownika
Użytkownik klika przycisk logowania i przyznaje aplikacji dostęp do żądanych uprawnień. Następnie funkcji wywołania zwrotnego określonej w metodie grantOfflineAccess().then()
przekazywany jest obiekt JSON z kodem autoryzacji. Na przykład:
{"code":"4/yU4cQZTMnnMtetyFcIWNItG32eKxxxgXXX-Z4yyJJJo.4qHskT-UtugceFc0ZRONyF4z7U4UmAI"}
Krok 6. Wyślij kod autoryzacji na serwer
code
to jednorazowy kod, który serwer może wymienić na własny token dostępu i token odświeżania. Token odświeżania możesz uzyskać dopiero po wyświetleniu użytkownikowi okna autoryzacji z prośbą o dostęp offline.
Jeśli w kroku 4 w polu OfflineAccessOptions
podano wartość select-account
prompt
, musisz przechowywać token odświeżania, który pobierzesz, aby użyć go później, ponieważ kolejne wymiany zwrócą wartość 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 w wyniku wymiany na prawidłowy kod autoryzacji.
Ten skrypt definiuje funkcję wywołania zwrotnego dla przycisku logowania. Jeśli logowanie się powiedzie, funkcja zapisuje token dostępu do użycia po stronie klienta i wysyła jednorazowy kod do serwera 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żywaj tokena dostępu do wywoływania interfejsów API Google w imieniu użytkownika. Opcjonalnie możesz też przechowywać token odświeżania, aby po wygaśnięciu tokena dostępu pobrać nowy.
Jeśli poprosisz o dostęp do profilu, otrzymasz też token tożsamości zawierający podstawowe informacje o profilu 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']