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 gereken 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 kopyala ve yapıştır seçeneği olarak da bilinen OAuth bant dışı (OOB), bir kullanıcı OAuth izin isteğini onayladıktan sonra kimlik bilgilerini kabul edecek yönlendirme URI'si olmayan yüklü istemcileri desteklemek için geliştirilmiş eski bir akıştır. OOB akışı, uzaktan kimlik avı riski oluşturur ve istemcilerin bu güvenlik açığına karşı korunmak için alternatif bir yönteme geçmesi gerekir.

OOB akışı; web uygulamaları, Android, iOS, Evrensel Windows Platformu (UWP), Chrome uygulamaları, TV'ler ve sınırlı giriş cihazları, masaüstü uygulamaları gibi tüm uygulama türleri için kullanımdan kaldırılıyor.

Uygunlukla ilgili önemli tarihler

  • 28 Şubat 2022: OOB akışı için yeni OAuth kullanımı engellendi.
  • 5 Eylül 2022: Uyumlu olmayan OAuth istekleri için kullanıcılara yönelik bir uyarı mesajı gösterilebilir.
  • 3 Ekim 2022: OOB akışı, 28 Şubat 2022'den önce oluşturulan OAuth istemcileri için kullanımdan kaldırılır.
  • 31 Ocak 2023: Mevcut tüm istemciler (muaf tutulan istemciler dahil) engellenir.

Uyumlu olmayan istekler için kullanıcılara yönelik bir hata mesajı gösterilir. Mesajda, kullanıcılara uygulamanın engellendiği bildirilir ve Google Cloud Console'daki OAuth kullanıcı rızası ekranında kaydettiğiniz destek e-posta adresi gösterilir.

Taşıma işlemini tamamlamak için iki temel adım vardır:

  1. Bu durumdan etkilenip etkilenmediğinizi belirleyin.
  2. Bu durumdan etkileniyorsanız daha güvenli bir alternatife geçin.

Bu durumdan etkilenip etkilenmediğinizi belirleme

Bu desteği sonlandırma yalnızca üretim uygulamaları (yani yayınlama durumu Üretimde olarak ayarlanmış uygulamalar) için geçerlidir. Akış, Test yayınlama durumuna sahip uygulamalarda çalışmaya devam eder.

Google Cloud Console'un OAuth Markalama sayfasında yayınlama durumunuzu inceleyin ve "Üretimde" yayınlama durumuna sahip bir projede OOB akışını kullanıyorsanız sonraki adıma geçin.

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

Uygulamanızın yaptığı 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ı yaptığınız 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 gibidir:

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 türünüze bağlı olarak 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 gibidir:

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çiş yapın

Mobil uygulama istemcileri (Android ve iOS)

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

SDK, Google API'lerine erişmenize yardımcı olur ve Google'ın OAuth 2.0 yetkilendirme uç noktalarına yapılan tüm çağrıları işler.

Aşağıdaki doküman bağlantılarında, bant dışı yönlendirme URI'si kullanmadan Google API'lerine 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şim

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

List<Scopes> 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));

İçeriği kullanıcının Drive klasörüne kaydetmek için authorizationResult değerini tanımladığınız yönteme iletin. authorizationResult, erişim jetonunu döndüren getAccessToken() yöntemine sahiptir.

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<Scopes> 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, erişim ve yenileme jetonu almak için arka ucunuza gönderebileceğiniz yetkilendirme kodunu döndüren getServerAuthCode() yöntemine sahiptir.

iOS Uygulamasında Google API'lerine Erişme

İstemci tarafı erişim

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()
}

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

Google API'lerine istemci tarafında nasıl erişeceğinizi öğrenmek için istemci tarafı erişim kılavuzunu inceleyin.

Sunucu tarafı (çevrimdışı) erişim

Aşağıdaki örnekte, bir 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ından nasıl erişileceğini öğrenmek için sunucu tarafı erişim kılavuzunu inceleyin.

Chrome uygulaması istemcisi

Uygulamanızın Chrome uygulama istemcisinde OOB akışını 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 following example 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 kullanıcıların kimliğini doğrulama ve Google uç noktalarını çağırma hakkında daha fazla bilgi 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 birini kullanmaya geçmeniz gerekir. Farklı programlama dilleri için Google API istemci kitaplıkları listesine bakın.

Kitaplıklar, Google API'lerine erişimi basitleştirir ve Google uç noktalarına yapılan tüm çağrıları işler.

Sunucu tarafı (çevrimdışı) erişim

Sunucu tarafı (çevrimdışı) erişim modu, aşağıdakileri yapmanızı gerektirir :

Aşağıdaki kod snippet'inde, OOB yönlendirme URI'si kullanmadan bir kullanıcının Google Drive dosyalarını sunucu tarafında listelemek için 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ından nasıl erişileceğini öğrenmek için sunucu tarafı web uygulaması kılavuzunu inceleyin.

İstemci tarafı erişimi

Aşağıdaki JavaScript kod snippet'inde, istemci tarafında kullanıcının takvim etkinliklerine erişmek için Google API'nin kullanımı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ından nasıl erişileceğini öğrenmek için 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ışını kullanmaya geçmeniz gerekir.