Kimlik doğrulama, bir kişinin kim olduğunu belirler ve genellikle kullanıcı kaydı veya oturum açma olarak adlandırılır. Yetkilendirme, verilere veya kaynaklara erişim izni verme ya da erişimi reddetme sürecidir. Örneğin, uygulamanız kullanıcının Google Drive'ına erişmek için kullanıcıdan izin ister.
Kimlik doğrulama ve yetkilendirme çağrıları, uygulamanın ihtiyaçlarına göre iki ayrı ve farklı akış olmalıdır.
Uygulamanızda Google API'leri verilerini kullanabilen ancak uygulamanızın temel özellikleri için gerekli olmayan özellikler varsa uygulamanızı, API verilerine erişilemediği durumlarda sorunsuz bir şekilde çalışacak şekilde tasarlayın. Örneğin, kullanıcı Drive erişimi vermediğinde son kaydedilen dosyaların listesini gizleyebilirsiniz.
Google API'lerine erişmek amacıyla ihtiyacınız olan kapsamlar için, yalnızca kullanıcının belirli bir API'ye erişim gerektiren bir işlem gerçekleştirdiği durumlarda erişim isteğinde bulunmalısınız. Örneğin, kullanıcı Drive'a kaydet düğmesine her dokunduğunda kullanıcının Drive'ına erişmek için izin istemeniz gerekir.
Yetkilendirmeyi kimlik doğrulamadan ayırarak yeni kullanıcılar için süreci kolaylaştırabilir veya kullanıcıların neden belirli izinler istendiği konusunda kafa karışıklığı yaşanmasını önleyebilirsiniz.
Kimlik doğrulama için Credential Manager API'yi kullanmanızı öneririz. Google tarafından depolanan kullanıcı verilerine erişim gerektiren işlemleri yetkilendirmek için AuthorizationClient'ı kullanmanızı öneririz.
Google Cloud Console projenizi oluşturma
- Cloud Console'da projenizi açın veya henüz projeniz yoksa proje oluşturun.
- Markalama sayfasında tüm bilgilerin eksiksiz ve doğru olduğundan emin olun.
- Uygulamanızın doğru bir uygulama adı, uygulama logosu ve uygulama ana sayfası bulunduğundan emin olun. Bu değerler, kayıt sırasında Google ile oturum açma izni ekranında ve Üçüncü taraf uygulamaları ve hizmetleri ekranında kullanıcılara gösterilir.
- Uygulamanızın gizlilik politikası ve hizmet şartları URL'lerini belirttiğinizden emin olun.
- İstemciler sayfasında henüz yoksa uygulamanız için bir Android istemci kimliği oluşturun. Uygulamanızın paket adını ve SHA-1 imzasını belirtmeniz gerekir.
- Müşteriler sayfasına gidin.
- Create client'ı (İstemci oluştur) tıklayın.
- Android uygulama türünü seçin.
- OAuth istemcisi için bir ad girin. Bu ad, istemciyi tanımlamak için projenizin İstemciler sayfasında gösterilir.
- Android uygulamanızın paket adını girin. Bu değer,
AndroidManifest.xmldosyanızdaki<manifest>öğesininpackageözelliğinde tanımlanır. - App Distribution uygulamasının SHA-1 imzalama sertifikası parmak izini girin.
- Uygulamanız Google Play'den uygulama imzalama özelliğini kullanıyorsa SHA-1 parmak izini Play Console'un uygulama imzalama sayfasından kopyalayın.
- Kendi anahtar deponuzu ve imzalama anahtarlarınızı yönetiyorsanız sertifika bilgilerini okunabilir bir biçimde yazdırmak için Java'da bulunan keytool yardımcı programını kullanın. keytool çıkışının
Certificate fingerprintsbölümündekiSHA-1değerini kopyalayın. Daha fazla bilgi için Android için Google API'leri belgelerindeki İstemcinizin Kimliğini Doğrulama bölümüne bakın. - (İsteğe bağlı) Android uygulamanızın sahipliğini doğrulayın.
- İstemciler sayfasında,
henüz yapmadıysanız yeni bir "Web uygulaması" istemci kimliği oluşturun. "Yetkilendirilmiş JavaScript kaynakları" ve "Yetkilendirilmiş yönlendirme URI'leri" alanlarını şimdilik yoksayabilirsiniz. Bu istemci kimliği, Google'ın kimlik doğrulama hizmetleriyle iletişim kurarken arka uç sunucunuzu tanımlamak için kullanılır.
- Müşteriler sayfasına gidin.
- Create client'ı (İstemci oluştur) tıklayın.
- Web uygulaması türünü seçin.
Uygulama sahipliğini doğrulama
Uygulama kimliğine bürünme riskini azaltmak için uygulamanızın sahipliğini doğrulayabilirsiniz.
Doğrulama sürecini tamamlamak için varsa Google Play Geliştirici Hesabınızı kullanabilirsiniz. Uygulamanızın Google Play Console'da kayıtlı olması gerekir. Doğrulamanın başarılı olması için aşağıdaki koşulların karşılanması gerekir:
- Google Play Console'da, doğrulama işlemini tamamladığınız Android OAuth istemcisiyle aynı paket adına ve SHA-1 imzalama sertifikası parmak izine sahip kayıtlı bir uygulamanız olmalıdır.
- Google Play Console'da uygulama için Yönetici izniniz olmalıdır. Google Play Console'da erişim yönetimi hakkında daha fazla bilgi edinin.
Doğrulama sürecini tamamlamak için Android istemcisinin Uygulama Sahipliğini Doğrulama bölümünde Sahipliği Doğrula düğmesini tıklayın.
Doğrulama başarılı olursa doğrulama sürecinin başarılı olduğunu onaylayan bir bildirim gösterilir. Aksi takdirde bir hata istemi gösterilir.
Başarısız bir doğrulamayı düzeltmek için aşağıdakileri deneyin:
- Doğruladığınız uygulamanın Google Play Console'da kayıtlı bir uygulama olduğundan emin olun.
- Google Play Console'da uygulama için Yönetici izninizin olduğundan emin olun.
Bağımlılıkları bildirme
Modülünüzün build.gradle dosyasında, Google Kimlik Hizmetleri kitaplığının en yeni sürümünü kullanarak bağımlılıkları bildirin.
dependencies {
// ... other dependencies
implementation "com.google.android.gms:play-services-auth:22.0.0"
}
Kullanıcı işlemlerinin gerektirdiği izinleri isteme
Kullanıcı, ek kapsam gerektiren bir işlem gerçekleştirdiğinde AuthorizationClient.authorize() işlevini çağırın. Örneğin, bir kullanıcı Drive uygulama depolama alanına erişim gerektiren bir işlem yaparsa şunları yapın:
Kotlin
val requestedScopes: List<Scope> = listOf(DriveScopes.DRIVE_FILE)
val authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.build()
Identity.getAuthorizationClient(activity)
.authorize(authorizationRequestBuilder.build())
.addOnSuccessListener { authorizationResult ->
if (authorizationResult.hasResolution()) {
val pendingIntent = authorizationResult.pendingIntent
// Access needs to be granted by the user
startAuthorizationIntent.launch(IntentSenderRequest.Builder(pendingIntent!!.intentSender).build())
} else {
// Access was previously granted, continue with user action
saveToDriveAppFolder(authorizationResult);
}
}
.addOnFailureListener { e -> Log.e(TAG, "Failed to authorize", e) }
Java
List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_FILE);
AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.build();
Identity.getAuthorizationClient(activity)
.authorize(authorizationRequest)
.addOnSuccessListener(authorizationResult -> {
if (authorizationResult.hasResolution()) {
// Access needs to be granted by the user
startAuthorizationIntent.launch(
new IntentSenderRequest.Builder(
authorizationResult.getPendingIntent().getIntentSender()
).build()
);
} else {
// Access was previously granted, continue with user action
saveToDriveAppFolder(authorizationResult);
}
})
.addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));
ActivityResultLauncher tanımlanırken yanıtı aşağıdaki snippet'te gösterildiği gibi işleyin. Bu snippet'te, işlemin bir parçada yapıldığı varsayılmıştır. Kod, gerekli izinlerin başarıyla verildiğini kontrol eder ve ardından kullanıcı işlemini gerçekleştirir.
Kotlin
private lateinit var startAuthorizationIntent: ActivityResultLauncher<IntentSenderRequest>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
// ...
startAuthorizationIntent =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
try {
// extract the result
val authorizationResult = Identity.getAuthorizationClient(requireContext())
.getAuthorizationResultFromIntent(activityResult.data)
// continue with user action
saveToDriveAppFolder(authorizationResult);
} catch (e: ApiException) {
// log exception
}
}
}
Java
private ActivityResultLauncher<IntentSenderRequest> startAuthorizationIntent;
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ...
startAuthorizationIntent =
registerForActivityResult(
new ActivityResultContracts.StartIntentSenderForResult(),
activityResult -> {
try {
// extract the result
AuthorizationResult authorizationResult =
Identity.getAuthorizationClient(requireActivity())
.getAuthorizationResultFromIntent(activityResult.getData());
// continue with user action
saveToDriveAppFolder(authorizationResult);
} catch (ApiException e) {
// log exception
}
});
}
Google API'lerine sunucu tarafında erişiyorsanız getServerAuthCode() yöntemini AuthorizationResult üzerinden çağırarak bir yetkilendirme kodu alın. Bu kodu, erişim ve yenileme jetonuyla değiştirmek için arka ucunuza gönderirsiniz. Daha fazla bilgi için Kullanıcı verilerine sürekli erişimi sürdürme bölümünü inceleyin.
Kullanıcı verilerine veya kaynaklarına erişim izinlerini iptal etme
Daha önce verilen erişimi iptal etmek için AuthorizationClient.revokeAccess() işlevini çağırın. Örneğin, kullanıcı hesabını uygulamanızdan kaldırıyorsa ve uygulamanıza daha önce DriveScopes.DRIVE_FILE erişim izni verildiyse erişimi iptal etmek için aşağıdaki kodu kullanın:
Kotlin
val requestedScopes: MutableList<Scope> = mutableListOf(DriveScopes.DRIVE_FILE)
RevokeAccessRequest revokeAccessRequest = RevokeAccessRequest.builder()
.setAccount(account)
.setScopes(requestedScopes)
.build()
Identity.getAuthorizationClient(activity)
.revokeAccess(revokeAccessRequest)
.addOnSuccessListener { Log.i(TAG, "Successfully revoked access") }
.addOnFailureListener { e -> Log.e(TAG, "Failed to revoke access", e) }
Java
List<Scopes> requestedScopes = Arrays.asList(DriveScopes.DRIVE_FILE);
RevokeAccessRequest revokeAccessRequest = RevokeAccessRequest.builder()
.setAccount(account)
.setScopes(requestedScopes)
.build();
Identity.getAuthorizationClient(activity)
.revokeAccess(revokeAccessRequest)
.addOnSuccessListener(unused -> Log.i(TAG, "Successfully revoked access"))
.addOnFailureListener(e -> Log.e(TAG, "Failed to revoke access", e));
Jeton önbelleğini temizleme
OAuth erişim jetonları, sunucudan alındıktan sonra yerel olarak önbelleğe alınır. Bu sayede erişim hızlanır ve ağ çağrıları azalır. Bu jetonlar, süreleri dolduğunda önbellekten otomatik olarak silinir ancak başka nedenlerle de geçersiz hale gelebilir.
Jeton kullanırken IllegalStateException hatası alırsanız erişim jetonu için bir sonraki yetkilendirme isteğinin OAuth sunucusuna gittiğinden emin olmak üzere yerel önbelleği temizleyin. Aşağıdaki snippet, invalidAccessToken öğesini yerel önbellekten kaldırır:
Kotlin
Identity.getAuthorizationClient(activity)
.clearToken(ClearTokenRequest.builder().setToken(invalidAccessToken).build())
.addOnSuccessListener { Log.i(TAG, "Successfully removed the token from the cache") }
.addOnFailureListener{ e -> Log.e(TAG, "Failed to clear token", e) }
Java
Identity.getAuthorizationClient(activity)
.clearToken(ClearTokenRequest.builder().setToken(invalidAccessToken).build())
.addOnSuccessListener(unused -> Log.i(TAG, "Successfully removed the token from the cache"))
.addOnFailureListener(e -> Log.e(TAG, "Failed to clear the token cache", e));
Yetkilendirme sırasında kullanıcı bilgilerini alma
Yetkilendirme yanıtı, kullanılan kullanıcı hesabı hakkında herhangi bir bilgi içermez. Yanıtta yalnızca istenen kapsamlar için bir jeton bulunur. Örneğin, kullanıcının Google Drive'ına erişmek için erişim jetonu alma yanıtı, kullanıcının seçtiği hesabın kimliğini ortaya çıkarmaz. Ancak bu yanıt, kullanıcının Drive'ındaki dosyalara erişmek için kullanılabilir. Kullanıcının adı veya e-posta adresi gibi bilgileri almak için aşağıdaki seçenekleri kullanabilirsiniz:
Yetkilendirme istemeden önce Kimlik Bilgisi Yöneticisi API'lerini kullanarak kullanıcının Google Hesabı ile oturum açmasını sağlayın. Kimlik Bilgisi Yöneticisi'nden gelen kimlik doğrulama yanıtı, e-posta adresi gibi kullanıcı bilgilerini içerir ve uygulamanın varsayılan hesabını seçilen hesap olarak ayarlar. Gerekirse bu hesabı uygulamanızda takip edebilirsiniz. Sonraki bir yetkilendirme isteği, hesabı varsayılan olarak kullanır ve yetkilendirme akışındaki hesap seçimi adımını atlar. Yetkilendirme için farklı bir hesap kullanmak istiyorsanız Varsayılan olmayan bir hesaptan yetkilendirme bölümünü inceleyin.
Yetkilendirme isteğinizde, istediğiniz kapsamlara (ör.
Drive scope) ek olarakuserinfo,profileveopenidkapsamlarını da isteyin. Erişim jetonu döndürüldükten sonra, tercih ettiğiniz HTTP kitaplığını kullanarak ve başlığa aldığınız erişim jetonunu ekleyerek OAuth userinfo uç noktasına (https://www.googleapis.com/oauth2/v3/userinfo)GETHTTP isteği gönderip kullanıcı bilgilerini alın. Bu işlem, aşağıdakicurlkomutuna eşdeğerdir:curl -X GET \ "https://www.googleapis.com/oauth2/v1/userinfo?alt=json" \ -H "Authorization: Bearer $TOKEN"Yanıt, istenen kapsamlarla sınırlı olan ve JSON biçiminde biçimlendirilmiş
UserInfoişlevidir.
Varsayılan olmayan bir hesaptan yetkilendirme
Kimlik doğrulamak için Kimlik Bilgisi Yöneticisi'ni kullanıyorsanız ve AuthorizationClient.authorize() komutunu çalıştırıyorsanız uygulamanızın varsayılan hesabı, kullanıcınız tarafından seçilen hesap olarak ayarlanır. Bu nedenle, sonraki tüm yetkilendirme çağrıları bu varsayılan hesabı kullanır. Hesap seçicinin gösterilmesini zorlamak için
Kimlik Bilgisi Yöneticisi'ndeki clearCredentialState() API'sini kullanarak kullanıcının uygulamadaki oturumunu kapatın.
Kullanıcı verilerine sürekli erişimi sürdürme
Uygulamanızdan kullanıcının verilerine erişmeniz gerekiyorsa AuthorizationClient.authorize() komutunu bir kez çağırın. Sonraki oturumlarda ve verilen izinler kullanıcı tarafından kaldırılmadığı sürece, hedeflerinize ulaşmak için erişim jetonu almak üzere aynı yöntemi kullanıcı etkileşimi olmadan çağırın. Diğer yandan, kullanıcının verilerine arka uç sunucunuzdan çevrimdışı modda erişmeniz gerekiyorsa "yenileme jetonu" adı verilen farklı bir jeton türü istemeniz gerekir.
Erişim jetonları, kısa ömürlü olacak şekilde tasarlanmıştır ve bir saatlik kullanım ömrüne sahiptir. Bir erişim jetonu ele geçirilirse veya güvenliği ihlal edilirse sınırlı geçerlilik süresi, olası kötüye kullanımı en aza indirir. Süresi dolduktan sonra jeton geçersiz hale gelir ve jetonu kullanma girişimleri kaynak sunucusu tarafından reddedilir. Erişim jetonları kısa ömürlü olduğundan sunucular, kullanıcının verilerine sürekli erişim sağlamak için yenileme jetonlarını kullanır. Yenileme jetonları, eski erişim jetonunun süresi dolduğunda istemci tarafından yetkilendirme sunucusundan kısa süreli bir erişim jetonu istemek için kullanılan, uzun ömürlü jetonlardır. Bu işlem için kullanıcı etkileşimi gerekmez.
Yenileme jetonu almak için öncelikle uygulamanızdaki yetkilendirme adımında "çevrimdışı erişim" isteyerek bir kimlik doğrulama kodu (veya yetkilendirme kodu) almanız ve ardından sunucunuzda kimlik doğrulama kodunu yenileme jetonuyla değiştirmeniz gerekir. Uzun ömürlü yenileme jetonları, yeni erişim jetonları almak için tekrar tekrar kullanılabileceğinden sunucunuzda güvenli bir şekilde saklanması çok önemlidir. Bu nedenle, güvenlik endişeleri nedeniyle yenileme jetonlarının cihazda saklanması kesinlikle önerilmez. Bunun yerine, erişim jetonu değişiminin gerçekleştiği uygulamanın arka uç sunucularında depolanmalıdır.
Yetkilendirme kodu uygulamanızın arka uç sunucusuna gönderildikten sonra, hesap yetkilendirme kılavuzundaki adımları uygulayarak sunucuda kısa ömürlü bir erişim jetonu ve uzun ömürlü bir yenileme jetonu ile değiştirebilirsiniz. Bu değişim yalnızca uygulamanızın arka ucunda gerçekleşmelidir.
Kotlin
// Ask for offline access during the first authorization request
val authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.requestOfflineAccess(serverClientId)
.build()
Identity.getAuthorizationClient(activity)
.authorize(authorizationRequest)
.addOnSuccessListener { authorizationResult ->
startAuthorizationIntent.launch(IntentSenderRequest.Builder(
pendingIntent!!.intentSender
).build())
}
.addOnFailureListener { e -> Log.e(TAG, "Failed to authorize", e) }
Java
// Ask for offline access during the first authorization request
AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
.setRequestedScopes(requestedScopes)
.requestOfflineAccess(serverClientId)
.build();
Identity.getAuthorizationClient(getContext())
.authorize(authorizationRequest)
.addOnSuccessListener(authorizationResult -> {
startAuthorizationIntent.launch(
new IntentSenderRequest.Builder(
authorizationResult.getPendingIntent().getIntentSender()
).build()
);
})
.addOnFailureListener(e -> Log.e(TAG, "Failed to authorize"));
Aşağıdaki snippet, yetkilendirmenin bir parçadan başlatıldığını varsayar.
Kotlin
private lateinit var startAuthorizationIntent: ActivityResultLauncher<IntentSenderRequest>
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
// ...
startAuthorizationIntent =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
try {
val authorizationResult = Identity.getAuthorizationClient(requireContext())
.getAuthorizationResultFromIntent(activityResult.data)
// short-lived access token
accessToken = authorizationResult.accessToken
// store the authorization code used for getting a refresh token safely to your app's backend server
val authCode: String = authorizationResult.serverAuthCode
storeAuthCodeSafely(authCode)
} catch (e: ApiException) {
// log exception
}
}
}
Java
private ActivityResultLauncher<IntentSenderRequest> startAuthorizationIntent;
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// ...
startAuthorizationIntent =
registerForActivityResult(
new ActivityResultContracts.StartIntentSenderForResult(),
activityResult -> {
try {
AuthorizationResult authorizationResult =
Identity.getAuthorizationClient(requireActivity())
.getAuthorizationResultFromIntent(activityResult.getData());
// short-lived access token
accessToken = authorizationResult.getAccessToken();
// store the authorization code used for getting a refresh token safely to your app's backend server
String authCode = authorizationResult.getServerAuthCode()
storeAuthCodeSafely(authCode);
} catch (ApiException e) {
// log exception
}
});
}