Google, Siyah topluluklar için ırksal eşitliği ilerletmeye kararlıdır. Nasıl olduğunu gör.
Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Kullanıcı Oturumlarını Yönetme

Firebase Kimlik Doğrulama oturumları uzun ömürlüdür. Bir kullanıcı her oturum açtığında, kullanıcı kimlik bilgileri Firebase Kimlik Doğrulaması arka ucuna gönderilir ve bir Firebase ID jetonu (JWT) ve yenileme jetonu ile değiştirilir. Firebase ID belirteçleri kısa ömürlüdür ve bir saat sürer; yenileme kodu yeni kimlik belirteçlerini almak için kullanılabilir. Yenileme simgelerinin süresi yalnızca aşağıdakilerden biri olduğunda sona erer:

  • Kullanıcı silinir
  • Kullanıcı devre dışı
  • Kullanıcı için önemli bir hesap değişikliği tespit edildi. Bu, şifre veya e-posta adresi güncellemeleri gibi etkinlikleri içerir.

Firebase Yönetici SDK'sı, belirtilen bir kullanıcı için yenileme jetonlarını iptal etme olanağı sağlar. Ayrıca, kimlik belirtecinin iptali için bir API da kullanıma sunulmuştur. Bu yeteneklerle kullanıcı oturumları üzerinde daha fazla kontrole sahip olursunuz. SDK, oturumların şüpheli durumlarda kullanılmasını önlemek için kısıtlamalar ve potansiyel jeton hırsızlığından kurtulma mekanizması ekleyebilir.

Yenileme jetonlarını iptal et

Bir kullanıcı kaybolan veya çalınan bir cihazı bildirdiğinde kullanıcının mevcut yenileme jetonunu iptal edebilirsiniz. Benzer şekilde, genel bir güvenlik açığı keşfederseniz veya geniş çapta etkin belirteç sızıntısı olduğundan şüpheleniyorsanız, tüm kullanıcıları aramak ve belirtilen proje için belirteçlerini iptal etmek için listUsers API'sını kullanabilirsiniz.

Parola sıfırlamaları aynı zamanda kullanıcının mevcut belirteçlerini iptal eder; ancak, Firebase Kimlik Doğrulaması arka ucu bu durumda iptal işlemini otomatik olarak gerçekleştirir. İptal durumunda, kullanıcının oturumu kapatılır ve yeniden kimlik doğrulaması istenir.

Aşağıda, belirli bir kullanıcının yenileme jetonunu iptal etmek için Yönetici SDK'sını kullanan örnek bir uygulama yer almaktadır. Yönetici SDK'sını başlatmak için kurulum sayfasındaki talimatları uygulayın.

node.js

 // Revoke all refresh tokens for a specified user for whatever reason.
// Retrieve the timestamp of the revocation, in seconds since the epoch.
admin.auth().revokeRefreshTokens(uid)
  .then(() => {
    return admin.auth().getUser(uid);
  })
  .then((userRecord) => {
    return new Date(userRecord.tokensValidAfterTime).getTime() / 1000;
  })
  .then((timestamp) => {
    console.log('Tokens revoked at: ', timestamp);
  });
 

Java

 FirebaseAuth.getInstance().revokeRefreshTokens(uid);
UserRecord user = FirebaseAuth.getInstance().getUser(uid);
// Convert to seconds as the auth_time in the token claims is in seconds too.
long revocationSecond = user.getTokensValidAfterTimestamp() / 1000;
System.out.println("Tokens revoked at: " + revocationSecond);
 

piton

 # Revoke tokens on the backend.
auth.revoke_refresh_tokens(uid)
user = auth.get_user(uid)
# Convert to seconds as the auth_time in the token claims is in seconds.
revocation_second = user.tokens_valid_after_timestamp / 1000
print('Tokens revoked at: {0}'.format(revocation_second))
 

Git

 client, err := app.Auth(ctx)
if err != nil {
	log.Fatalf("error getting Auth client: %v\n", err)
}
if err := client.RevokeRefreshTokens(ctx, uid); err != nil {
	log.Fatalf("error revoking tokens for user: %v, %v\n", uid, err)
}
// accessing the user's TokenValidAfter
u, err := client.GetUser(ctx, uid)
if err != nil {
	log.Fatalf("error getting user %s: %v\n", uid, err)
}
timestamp := u.TokensValidAfterMillis / 1000
log.Printf("the refresh tokens were revoked at: %d (UTC seconds) ", timestamp) 

C #

 await FirebaseAuth.DefaultInstance.RevokeRefreshTokensAsync(uid);
var user = await FirebaseAuth.DefaultInstance.GetUserAsync(uid);
Console.WriteLine("Tokens revoked at: " + user.TokensValidAfterTimestamp); 

Kimlik jetonunun iptali algılandı

Firebase ID belirteçleri durum bilgisi olmayan JWT'ler olduğundan, yalnızca belirtenin durumunu Firebase Kimlik Doğrulaması arka ucundan isteyerek iptal edildiğini belirleyebilirsiniz. Bu nedenle, sunucunuzda bu denetimi yapmak pahalı bir işlemdir ve ekstra bir ağ gidiş dönüşü gerektirir. Denetimi yapmak için Yönetici SDK'sını kullanmak yerine iptal durumunu kontrol eden Firebase Kuralları ayarlayarak bu ağ isteğini yapmaktan kaçınabilirsiniz.

Veritabanı Kurallarında Kimlik belirteci iptali algılandı

Kimlik kodu iptalini veritabanı kurallarını kullanarak algılayabilmek için, önce kullanıcıya özgü bazı meta verileri depolamamız gerekir.

Firebase Gerçek Zamanlı Veritabanı'ndaki kullanıcıya özgü meta verileri güncelleyin.

Yenileme belirteci iptali zaman damgasını kaydedin. Bu, Firebase kuralları aracılığıyla kimlik belirtecinin iptalini izlemek için gereklidir. Bu, veritabanı içinde verimli kontroller yapılmasını sağlar. Aşağıdaki kod örneklerinde, önceki bölümde elde edilen uid ve iptal süresini kullanın.

node.js

 const metadataRef = admin.database().ref('metadata/' + uid);
metadataRef.set({revokeTime: utcRevocationTimeSecs})
  .then(() => {
    console.log('Database updated successfully.');
  });
 

Java

 DatabaseReference ref = FirebaseDatabase.getInstance().getReference("metadata/" + uid);
Map<String, Object> userData = new HashMap<>();
userData.put("revokeTime", revocationSecond);
ref.setValueAsync(userData);
 

piton

 metadata_ref = firebase_admin.db.reference("metadata/" + uid)
metadata_ref.set({'revokeTime': revocation_second})
 

Veritabanı Kurallarına bir kontrol ekleme

Bu denetimi uygulamak için, kullanıcı başına iptal süresini saklamak üzere istemci yazma erişimi olmayan bir kural ayarlayın. Bu, önceki örneklerde gösterildiği gibi son iptal zamanının UTC zaman damgası ile güncellenebilir:

 {
  "rules": {
    "metadata": {
      "$user_id": {
        // this could be false as it is only accessed from backend or rules.
        ".read": "$user_id === auth.uid",
        ".write": "false",
      }
    }
  }
}
 

Kimliği doğrulanmış erişim gerektiren tüm veriler için aşağıdaki kural yapılandırılmalıdır. Bu mantık yalnızca, gönderilmemiş kimlik jetonlarına sahip kimliği doğrulanmış kullanıcıların korunan verilere erişmesine izin verir:

 {
  "rules": {
    "users": {
      "$user_id": {
        ".read": "$user_id === auth.uid && auth.token.auth_time > (root.child('metadata').child(auth.uid).child('revokeTime').val() || 0)",
        ".write": "$user_id === auth.uid && auth.token.auth_time > (root.child('metadata').child(auth.uid).child('revokeTime').val() || 0)"
      }
    }
  }
}
 

SDK'da kimlik belirteci iptali algılandı.

Sunucunuzda, yenileme belirteci iptali ve kimlik belirteci doğrulaması için aşağıdaki mantığı uygulayın:

Bir kullanıcının kimlik belirteci doğrulanacaksa, checkRevoked için ek checkRevoked boolean bayrağının geçirilmesi verifyIdToken . Kullanıcının belirteci iptal edilirse, kullanıcının istemcide oturumu kapatması veya Firebase Kimlik Doğrulama istemcisi SDK'ları tarafından sağlanan yeniden kimlik doğrulama API'larını kullanarak yeniden kimlik doğrulaması yapması istenir.

Platformunuz için Yönetici SDK'sını başlatmak için kurulum sayfasındaki talimatları uygulayın. Kimlik jetonunu alma örnekleri verifyIdToken bölümünde bulunmaktadır.

node.js

 // Verify the ID token while checking if the token is revoked by passing
// checkRevoked true.
let checkRevoked = true;
admin.auth().verifyIdToken(idToken, checkRevoked)
  .then(payload => {
    // Token is valid.
  })
  .catch(error => {
    if (error.code == 'auth/id-token-revoked') {
      // Token has been revoked. Inform the user to reauthenticate or signOut() the user.
    } else {
      // Token is invalid.
    }
  });
 

Java

 try {
  // Verify the ID token while checking if the token is revoked by passing checkRevoked
  // as true.
  boolean checkRevoked = true;
  FirebaseToken decodedToken = FirebaseAuth.getInstance()
      .verifyIdToken(idToken, checkRevoked);
  // Token is valid and not revoked.
  String uid = decodedToken.getUid();
} catch (FirebaseAuthException e) {
  if (e.getErrorCode().equals("id-token-revoked")) {
    // Token has been revoked. Inform the user to re-authenticate or signOut() the user.
  } else {
    // Token is invalid.
  }
}
 

piton

 try:
    # Verify the ID token while checking if the token is revoked by
    # passing check_revoked=True.
    decoded_token = auth.verify_id_token(id_token, check_revoked=True)
    # Token is valid and not revoked.
    uid = decoded_token['uid']
except auth.RevokedIdTokenError:
    # Token revoked, inform the user to reauthenticate or signOut().
    pass
except auth.InvalidIdTokenError:
    # Token is invalid
    pass
 

Git

 client, err := app.Auth(ctx)
if err != nil {
	log.Fatalf("error getting Auth client: %v\n", err)
}
token, err := client.VerifyIDTokenAndCheckRevoked(ctx, idToken)
if err != nil {
	if err.Error() == "ID token has been revoked" {
		// Token is revoked. Inform the user to reauthenticate or signOut() the user.
	} else {
		// Token is invalid
	}
}
log.Printf("Verified ID token: %v\n", token) 

C #

 try
{
    // Verify the ID token while checking if the token is revoked by passing checkRevoked
    // as true.
    bool checkRevoked = true;
    var decodedToken = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(
        idToken, checkRevoked);
    // Token is valid and not revoked.
    string uid = decodedToken.Uid;
}
catch (FirebaseAuthException ex)
{
    if (ex.AuthErrorCode == AuthErrorCode.RevokedIdToken)
    {
        // Token has been revoked. Inform the user to re-authenticate or signOut() the user.
    }
    else
    {
        // Token is invalid.
    }
}
 

İstemcide jeton iptali için yanıt verin

Simge Yönetici SDK'sı aracılığıyla iptal edilirse, müşteri iptal hakkında bilgilendirilir ve kullanıcının yeniden kimlik doğrulaması yapması veya oturumu kapatması beklenir:

 function onIdTokenRevocation() {
  // For an email/password user. Prompt the user for the password again.
  let password = prompt('Please provide your password for reauthentication');
  let credential = firebase.auth.EmailAuthProvider.credential(
      firebase.auth().currentUser.email, password);
  firebase.auth().currentUser.reauthenticateWithCredential(credential)
    .then(result => {
      // User successfully reauthenticated. New ID tokens should be valid.
    })
    .catch(error => {
      // An error occurred.
    });
}
 

Gelişmiş Güvenlik: IP adresi kısıtlamalarını zorunlu kılın

Belirteç hırsızlığını tespit etmek için yaygın bir güvenlik mekanizması, istek IP adresi kökenlerini takip etmektir. Örneğin, istekler her zaman aynı IP adresinden (çağrıyı yapan sunucu) geliyorsa, tek IP adresi oturumları uygulanabilir. Veya, kullanıcının IP adresinin aniden coğrafi konumu değiştirdiğini veya şüpheli bir kaynaktan gelen bir istek aldığınızı tespit ederseniz bir kullanıcının belirtecini iptal edebilirsiniz.

IP adresine göre güvenlik kontrolleri yapmak için, kimliği doğrulanan her istek için kimlik belirtecini inceleyin ve isteğin IP adresinin önceki güvenilir IP adresleriyle eşleşip eşleşmediğini veya güvenilen bir aralıkta olup olmadığını kontrol edin. Örneğin:

 app.post('/getRestrictedData', (req, res) => {
  // Get the ID token passed.
  const idToken = req.body.idToken;
  // Verify the ID token, check if revoked and decode its payload.
  admin.auth().verifyIdToken(idToken, true).then((claims) => {
    // Get the user's previous IP addresses, previously saved.
    return getPreviousUserIpAddresses(claims.sub);
  }).then(previousIpAddresses => {
    // Get the request IP address.
    const requestIpAddress = req.connection.remoteAddress;
    // Check if the request IP address origin is suspicious relative to previous
    // IP addresses. The current request timestamp and the auth_time of the ID
    // token can provide additional signals of abuse especially if the IP address
    // suddenly changed. If there was a sudden location change in a
    // short period of time, then it will give stronger signals of possible abuse.
    if (!isValidIpAddress(previousIpAddresses, requestIpAddress)) {
      // Invalid IP address, take action quickly and revoke all user's refresh tokens.
      revokeUserTokens(claims.uid).then(() => {
        res.status(401).send({error: 'Unauthorized access. Please login again!'});
      }, error => {
        res.status(401).send({error: 'Unauthorized access. Please login again!'});
      });
    } else {
      // Access is valid. Try to return data.
      getData(claims).then(data => {
        res.end(JSON.stringify(data);
      }, error => {
        res.status(500).send({ error: 'Server error!' })
      });
    }
  });
});