Bant Dışı (OOB) akışı Taşıma Rehberi

Genel Bakış

16 Şubat 2022'de, daha güvenli OAuth akışları kullanarak Google OAuth etkileşimlerini daha güvenli hale getirme planlarımızı duyurmuştuk. Bu kılavuz, OAuth bant dışı (OOB) akışından desteklenen alternatiflere başarılı bir şekilde geçiş yapmak için gerekli değişiklikleri ve adımları anlamanıza yardımcı olur.

Bu çalışma, Google'ın OAuth 2.0 yetkilendirme uç noktalarıyla etkileşimler sırasında kimlik avı ve uygulama kimliğine bürünme saldırılarına karşı koruyucu bir önlemdir.

OOB nedir?

Manuel kopyalama/yapıştırma seçeneği olarak da adlandırılan OAuth bant dışı (OOB), kullanıcı bir OAuth izin isteğini onayladıktan sonra kimlik bilgilerini kabul etmek için yönlendirme URI'si olmayan yerel istemcileri desteklemek üzere geliştirilmiş eski bir akıştır. OOB akışı uzaktan kimlik avı riski oluşturur ve istemcilerin bu güvenlik açığını önlemek için alternatif bir yönteme geçmesi gerekir.

Bant dışı akış, web uygulamaları, Android, iOS, Universal Windows Platform (UWP), Chrome uygulamaları, TV'ler ve sınırlı girişli cihazlar, masaüstü uygulamaları gibi tüm istemci türleri için kullanımdan kaldırılıyor.

Önemli uygunluk tarihleri

  • 28 Şubat 2022: OOB akışı için yeni OAuth kullanımı engellendi
  • 5 Eylül 2022: Uyumlu olmayan OAuth isteklerine kullanıcılara yönelik bir uyarı mesajı gösterilebilir
  • 3 Ekim 2022: 28 Şubat 2022'den önce oluşturulan OAuth istemcileri için harici akış desteği sonlandırıldı
  • 31 Ocak 2023: Mevcut tüm istemciler (istisna kapsamındaki istemciler dahil) engellenir

Uyumlu olmayan istekler için kullanıcılara yönelik bir hata mesajı gösterilir. Bu mesaj, kullanıcılara uygulamanın engellendiğini bildirir ve Google API Konsolu'ndaki OAuth kullanıcı rızası ekranında kaydettiğiniz destek e-posta adresini gösterir.

Taşıma işlemini tamamlamak için iki temel adım vardır:
  1. Etkilenip etkilenmediğinizi belirleyin.
  2. Etkilenen kullanıcılar daha güvenli bir alternatife geçebilir.

Etkilenip etkilenmediğinizi belirleme

Bu desteğin sonlandırılması yalnızca üretim uygulamaları (yani yayınlama durumu Üretimde olarak ayarlanmış uygulamalar) için geçerlidir. Akış, Test yayın durumu olan uygulamalarda çalışmaya devam edecek.

"Üretimde" yayınlanma durumuna sahip bir projede OOB akışını kullanıyorsanız OAuth bölümündeki yayınlanma durumunuzu inceleyin ve sonraki adıma geçin.

Uygulamanızın OOB akışını kullanıp kullanmadığını belirleme

Uygulamanızın gönderdiği Google OAuth yetkilendirme isteğinin OOB yönlendirme URI değeri kullanıp kullanmadığını belirlemek için uygulama kodunuzu veya giden ağ çağrısını (uygulamanız bir OAuth kitaplığı kullanıyorsa) inceleyin.

Uygulama kodunuzu inceleme

Uygulama kodunuzun Google OAuth yetkilendirme uç noktalarına çağrı gönderdiğiniz bölümünü inceleyin ve redirect_uri parametresinin aşağıdaki değerlerden herhangi birine sahip olup olmadığını belirleyin:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
Örnek bir OOB yönlendirme akışı isteği aşağıdaki gibi görünür:
https://accounts.google.com/o/oauth2/v2/auth?
response_type=code&
scope=<SCOPES>&
state=<STATE>&
redirect_uri=urn:ietf:wg:oauth:2.0:oob&
client_id=<CLIENT_ID>

Giden ağ çağrısını inceleme

Ağ çağrılarını inceleme yöntemi, uygulama istemci türüne göre değişir.
Ağ çağrılarını incelerken Google OAuth yetkilendirme uç noktalarına gönderilen istekleri arayın ve redirect_uri parametresinin aşağıdaki değerlerden herhangi birine sahip olup olmadığını belirleyin:
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob
  • redirect_uri=urn:ietf:wg:oauth:2.0:oob:auto
  • redirect_uri=oob
Örnek bir OOB yönlendirme akışı isteği aşağıdaki gibi görünür:
https://accounts.google.com/o/oauth2/v2/auth?
response_type=code&
scope=<SCOPES>&
state=<STATE>&
redirect_uri=urn:ietf:wg:oauth:2.0:oob&
client_id=<CLIENT_ID>

Güvenli bir alternatife geçme

Mobil istemciler (Android / iOS)

Uygulamanızın Android veya iOS OAuth istemci türüyle OOB akışını kullandığını belirlerseniz önerilen SDK'ları (Android, iOS) kullanmaya geçmeniz gerekir.

SDK, Google API'lerine erişmeyi kolaylaştırır ve Google'ın OAuth 2.0 yetkilendirme uç noktalarına yapılan tüm çağrıları yönetir.

Aşağıdaki doküman bağlantılarında, Google API'lerine OOB yönlendirme URI'si kullanmadan erişmek için önerilen SDK'ların nasıl kullanılacağı hakkında bilgi verilmektedir.

Android'de Google API'lerine erişme

İstemci tarafı erişimi

Aşağıdaki örnekte, önerilen Google Identity Services Android Kitaplığı kullanılarak Android'de istemci tarafında Google API'lerine nasıl erişileceği gösterilmektedir.

  List requestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA);
    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
                    PendingIntent pendingIntent = authorizationResult.getPendingIntent();
                    try {
    startIntentSenderForResult(pendingIntent.getIntentSender(),
    REQUEST_AUTHORIZE, null, 0, 0, 0, null);
                    } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start Authorization UI: " + e.getLocalizedMessage());
                    }
                  } else {
                    // Access already granted, continue with user action
                    saveToDriveAppFolder(authorizationResult);
                  }
                })
            .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));

Kullanıcının Drive klasörüne içerik kaydetmek için authorizationResult değerini, tanımladığınız yönteme iletin. authorizationResult sınıfında, erişim jetonunu döndüren getAccessToken() yöntemi bulunur.

Sunucu tarafı (çevrimdışı) erişim
Aşağıdaki örnekte, Android'de sunucu tarafında Google API'lerine nasıl erişileceği gösterilmektedir.
  List requestedScopes = Arrays.asList(DriveScopes.DRIVE_APPDATA);
    AuthorizationRequest authorizationRequest = AuthorizationRequest.builder()
    .requestOfflineAccess(webClientId)
            .setRequestedScopes(requestedScopes)
            .build();
    Identity.getAuthorizationClient(activity)
            .authorize(authorizationRequest)
            .addOnSuccessListener(
                authorizationResult -> {
                  if (authorizationResult.hasResolution()) {
                    // Access needs to be granted by the user
                    PendingIntent pendingIntent = authorizationResult.getPendingIntent();
                    try {
    startIntentSenderForResult(pendingIntent.getIntentSender(),
    REQUEST_AUTHORIZE, null, 0, 0, 0, null);
                    } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "Couldn't start Authorization UI: " + e.getLocalizedMessage());
                    }
                  } else {
                    String authCode = authorizationResult.getServerAuthCode();
                  }
                })
            .addOnFailureListener(e -> Log.e(TAG, "Failed to authorize", e));

authorizationResult sınıfında, erişim ve yenileme jetonu almak için arka uç sunucunuza gönderebileceğiniz yetkilendirme kodunu döndüren getServerAuthCode() yöntemi bulunur.

iOS uygulamasında Google API'lerine erişme

İstemci tarafı erişimi

Aşağıdaki örnekte, iOS'te istemci tarafında Google API'lerine nasıl erişileceği gösterilmektedir.

user.authentication.do { authentication, error in
  guard error == nil else { return }
  guard let authentication = authentication else { return }
  
  // Get the access token to attach it to a REST or gRPC request.
  let accessToken = authentication.accessToken
  
  // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
  // use with GTMAppAuth and the Google APIs client library.
  let authorizer = authentication.fetcherAuthorizer()
}

API'yi çağırmak için erişim jetonunu kullanın. Bunun için erişim jetonunu bir REST veya gRPC isteğinin başlığına (Authorization: Bearer ACCESS_TOKEN) ekleyerek ya da REST için Objective-C'te Google API'leri istemci kitaplığı ile birlikte alıcı yetkilendiriciyi (GTMFetcherAuthorizationProtocol) kullanarak çağırabilirsiniz.

İstemci tarafında Google API'lerine erişme hakkındaki istemci tarafı erişim kılavuzunu inceleyin. sayfasını inceleyin.

Sunucu tarafı (çevrimdışı) erişim
Aşağıdaki örnekte, iOS istemcisini desteklemek için sunucu tarafında Google API'lerine nasıl erişileceği gösterilmektedir.
GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
  guard error == nil else { return }
  guard let user = user else { return }
  
  // request a one-time authorization code that your server exchanges for
  // an access token and refresh token
  let authCode = user.serverAuthCode
}

Google API'lerine sunucu tarafında nasıl erişileceğine dair sunucu tarafı erişim kılavuzunu inceleyin.

Chrome Uygulama İstemcisi

Uygulamanızın Chrome uygulama istemcisinde bant dışı akışı kullandığını belirlerseniz Chrome Identity API'yi kullanmaya geçmeniz gerekir.

Aşağıdaki örnekte, OOB yönlendirme URI'si kullanılmadan tüm kullanıcı kişilerinin nasıl alınacağı gösterilmektedir.

window.onload = function() {
  document.querySelector('button').addEventListener('click', function() {

  
  // retrieve access token
  chrome.identity.getAuthToken({interactive: true}, function(token) {
  
  // ..........


  // the example below shows how to use a retrieved access token with an appropriate scope
  // to call the Google People API contactGroups.get endpoint

  fetch(
    'https://people.googleapis.com/v1/contactGroups/all?maxMembers=20&key=API_KEY',
    init)
    .then((response) => response.json())
    .then(function(data) {
      console.log(data)
    });
   });
 });
};

Chrome Identity API ile kimliği doğrulanmış kullanıcılara erişme ve Google uç noktalarını çağırma hakkında daha fazla bilgi edinmek için Chrome Identity API kılavuzunu inceleyin.

Web Uygulaması

Uygulamanızın bir web uygulaması için OOB akışını kullandığını belirlerseniz Google API istemci kitaplıklarımızdan birine geçmeniz gerekir. Farklı programlama dilleri için istemci kitaplıkları burada listelenmiştir.

Kitaplıklar, Google API'lerine erişmeyi ve Google uç noktalarına yapılan tüm çağrıları yönetmeyi kolaylaştırır.

Sunucu tarafı (çevrimdışı) erişim
Sunucu tarafı (çevrimdışı) erişim modu için aşağıdakileri yapmanız gerekir:
  • Yetkilendirme kodunu almak için bir sunucu oluşturun ve herkese açık erişilebilir bir uç nokta (yönlendirme URI'si) tanımlayın.
  • bölümündeki yönlendirme URI'sini yapılandırın

Aşağıdaki kod snippet'inde, bir kullanıcının Google Drive dosyalarını sunucu tarafında listelemek için OOB yönlendirme URI'si kullanmadan Google Drive API'nin kullanıldığı bir NodeJS örneği gösterilmektedir.

async function main() {
  const server = http.createServer(async function (req, res) {

  if (req.url.startsWith('/oauth2callback')) {
    let q = url.parse(req.url, true).query;

    if (q.error) {
      console.log('Error:' + q.error);
    } else {
      
      // Get access and refresh tokens (if access_type is offline)
      let { tokens } = await oauth2Client.getToken(q.code);
      oauth2Client.setCredentials(tokens);

      // Example of using Google Drive API to list filenames in user's Drive.
      const drive = google.drive('v3');
      drive.files.list({
        auth: oauth2Client,
        pageSize: 10,
        fields: 'nextPageToken, files(id, name)',
      }, (err1, res1) => {
        // TODO(developer): Handle response / error.
      });
    }
  }
}

Google API'lerine sunucu tarafında nasıl erişileceğine dair sunucu tarafı web uygulaması kılavuzunu inceleyin.

İstemci tarafı erişimi

JavaScript'te yazılmış aşağıdaki kod snippet'inde, istemci tarafında kullanıcının takvim etkinliklerine erişmek için Google API'nin kullanılmasına dair bir örnek gösterilmektedir.


// initTokenClient() initializes a new token client with your
// web app's client ID and the scope you need access to

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  
  // callback function to handle the token response
  callback: (tokenResponse) => {
    if (tokenResponse && tokenResponse.access_token) { 
      gapi.client.setApiKey('YOUR_API_KEY');
      gapi.client.load('calendar', 'v3', listUpcomingEvents);
    }
  },
});

function listUpcomingEvents() {
  gapi.client.calendar.events.list(...);
}

Google API'lerine istemci tarafında nasıl erişileceğine dair istemci tarafı web uygulaması kılavuzunu inceleyin.

Masaüstü istemcisi

Uygulamanızın bir masaüstü istemcisinde OOB akışını kullandığını belirlerseniz loopback IP adresi (localhost veya 127.0.0.1) akışına geçmeniz gerekir.