Kullanıcı çevrimdışıyken Google hizmetlerini kullanıcı adına kullanmak için kullanıcının JavaScript API istemcisini kullanarak istemci tarafında uygulamanıza yetki verdiği ve sunucunuza özel bir tek seferlik yetkilendirme kodu gönderdiğiniz karma bir sunucu tarafı akışı kullanmanız gerekir. Sunucunuz, Google'dan kendi erişim ve yenileme jetonlarını almak için bu tek kullanımlık kodu değiştirir. Böylece sunucu kendi API çağrılarını yapabilir. Bu işlem, kullanıcı çevrimdışıyken de yapılabilir. Bu tek kullanımlık kod akışı, hem sunucu tarafı akışa hem de sunucunuza erişim jetonları göndermeye kıyasla güvenlik avantajlarına sahiptir.
Sunucu tarafı uygulamanız için erişim jetonu edinme ile ilgili oturum açma akışı aşağıda gösterilmiştir.
Tek seferlik kodların güvenlik açısından çeşitli avantajları vardır. Google, kodlar sayesinde jetonları herhangi bir aracı olmadan doğrudan sunucunuza sağlar. Kodları sızdırmanızı önermesek de istemci gizli anahtarınız olmadan kullanılması çok zordur. İstemci sırrınızı gizli tutun.
Tek seferlik kod akışını uygulama
Google ile oturum açma düğmesi hem erişim jetonu hem de yetkilendirme kodu sağlar. Kod, sunucunuzun erişim jetonu almak için Google sunucularıyla takas edebileceği tek seferlik bir koddur.
Aşağıdaki örnek kodda, tek seferlik kod akışının nasıl yapılacağı gösterilmektedir.
Google ile oturum açma özelliğinin tek seferlik kod akışı ile kimliğini doğrulaması için şunları yapmanız gerekir:
1. adım: İstemci kimliği ve istemci gizli anahtarı oluşturun
İstemci kimliği ve istemci gizlisi oluşturmak için bir Google API Konsolu projesi oluşturun, OAuth istemci kimliği ayarlayın ve JavaScript kaynaklarınızı kaydedin:
Google API Konsolu'na gidin.
Proje açılır listesinden mevcut bir proje seçin veya Yeni proje oluştur'u seçerek yeni bir proje oluşturun.
"API'ler ve Hizmetler"in altındaki kenar çubuğunda Kimlik bilgileri'ni seçin, ardından İzin ekranını yapılandır'ı tıklayın.
Bir e-posta adresi seçin, ürün adı belirtin ve Kaydet'e basın.
Kimlik bilgileri sekmesinde Kimlik bilgileri oluştur açılır listesini ve ardından OAuth istemci kimliği'ni seçin.
Uygulama türü bölümünde Web uygulaması'nı seçin.
Uygulamanızın Google API'lerine erişmesine izin verilen kaynaklarını aşağıdaki gibi kaydedin. Kaynak, protokol, ana makine adı ve bağlantı noktasının benzersiz bir kombinasyonudur.
Yetkilendirilmiş JavaScript kaynakları alanına uygulamanızın kaynağını girin. Uygulamanızın farklı protokollerde, alanlarda veya alt alan adlarında çalışmasına izin vermek için birden fazla kaynak girebilirsiniz. Joker karakter kullanamazsınız. Aşağıdaki örnekte ikinci URL, üretim URL'si olabilir.
http://localhost:8080 https://myproductionurl.example.com
Yetkilendirilmiş yönlendirme URI'si alanı için bir değer gerekmez. Yönlendirme URI'leri JavaScript API'leriyle kullanılmaz.
Oluştur düğmesine basın.
Açılan OAuth istemcisi iletişim kutusunda istemci kimliğini kopyalayın. İstemci kimliği, uygulamanızın etkin Google API'lerine erişmesine olanak tanır.
2. adım: Google platform kitaplığını sayfanıza ekleyin
Bu index.html
web sayfasının DOM'una komut dosyası ekleyen anonim bir işlevi gösteren aşağıdaki komut dosyalarını ekleyin.
<!-- 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 -->
3. Adım: GoogleAuth nesnesini başlatın
auth2 kitaplığını yükleyin ve GoogleAuth
nesnesini başlatmak için gapi.auth2.init()
işlevini çağırın. init()
çağrısını yaptığınızda istemci kimliğinizi ve istemek istediğiniz kapsamları belirtin.
<!-- 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>
4. Adım: Oturum açma düğmesini sayfanıza ekleyin
Oturum açma düğmesini web sayfanıza ekleyin ve tek kullanımlık kod akışını başlatmak için grantOfflineAccess()
işlevini çağırmak üzere bir tıklama işleyici ekleyin.
<!-- 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>
5. adım: Kullanıcının oturumunu açın
Kullanıcı, oturum açma düğmesini tıklar ve uygulamanıza istediğiniz izinlere erişim izni verir. Ardından, grantOfflineAccess().then()
yönteminde belirttiğiniz geri çağırma işlevine bir yetkilendirme kodu içeren bir JSON nesnesi iletilir. Örneğin:
{"code":"4/yU4cQZTMnnMtetyFcIWNItG32eKxxxgXXX-Z4yyJJJo.4qHskT-UtugceFc0ZRONyF4z7U4UmAI"}
6. adım: Yetkilendirme kodunu sunucuya gönderin
code
, sunucunuzun kendi erişim jetonu ve yenileme jetonuyla takas edebileceği tek seferlik kodunuzdur. Yenileme jetonunu yalnızca kullanıcıya çevrimdışı erişim isteyen bir yetkilendirme iletişim kutusu gösterildikten sonra alabilirsiniz.
4. adımda OfflineAccessOptions
bölümünde select-account
prompt
değerini belirttiyseniz sonraki Exchange'ler yenileme jetonu için null
döndüreceğinden, aldığınız yenileme jetonunu daha sonra kullanmak üzere saklamanız gerekir. Bu akış, standart OAuth 2.0 akışınıza kıyasla daha fazla güvenlik sağlar.
Erişim jetonları her zaman geçerli bir yetkilendirme koduyla birlikte döndürülür.
Aşağıdaki komut dosyası, oturum açma düğmesi için bir geri çağırma işlevi tanımlar. Oturum açmak başarılı olduğunda işlev, erişim jetonunu istemci tarafı kullanımı için depolar ve tek kullanımlık kodu aynı alan adındaki sunucunuza gönderir.
<!-- 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>
7. adım: Yetkilendirme kodunu erişim jetonuyla değiştirin
Sunucuda, yetkilendirme kodunu erişim ve yenileme jetonlarıyla değiştirin. Kullanıcı adına Google API'lerini çağırmak için erişim jetonunu kullanın ve isteğe bağlı olarak, erişim jetonunun süresi dolduğunda yeni bir erişim jetonu almak için yenileme jetonunu saklayın.
Profil erişimi istediyseniz kullanıcının temel profil bilgilerini içeren bir kimlik jetonu da alırsınız.
Örneğin:
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']