Google มุ่งมั่นที่จะพัฒนาความเท่าเทียมทางเชื้อชาติสำหรับชุมชนคนผิวดำ มาดูกันว่า
หน้านี้ได้รับการแปลโดย Cloud Translation API
Switch to English

จัดการเซสชันคุกกี้

Firebase Auth ให้การจัดการคุกกี้เซสชันฝั่งเซิร์ฟเวอร์สำหรับเว็บไซต์ดั้งเดิมที่ต้องใช้คุกกี้เซสชัน โซลูชันนี้มีข้อดีหลายประการเกี่ยวกับโทเค็น ID แบบสั้นของฝั่งไคลเอ็นต์ซึ่งอาจต้องใช้กลไกการเปลี่ยนเส้นทางในแต่ละครั้งเพื่ออัปเดตคุกกี้เซสชันเมื่อหมดอายุ:

  • ปรับปรุงความปลอดภัยผ่านโทเค็นเซสชันที่ใช้ JWT ซึ่งสามารถสร้างได้โดยใช้บัญชีบริการที่ได้รับอนุญาตเท่านั้น
  • คุกกี้เซสชันไร้สัญชาติที่มาพร้อมกับประโยชน์ทั้งหมดของการใช้ JWT สำหรับการตรวจสอบสิทธิ์ คุกกี้เซสชั่นมีการเรียกร้องเดียวกัน (รวมถึงการเรียกร้องที่กำหนดเอง) เป็นโทเค็น ID ทำให้การตรวจสอบสิทธิ์เดียวกันบังคับใช้กับคุกกี้เซสชัน
  • ความสามารถในการสร้างคุกกี้เซสชั่นที่มีเวลาหมดอายุที่กำหนดเองตั้งแต่ 5 นาทีถึง 2 สัปดาห์
  • ความยืดหยุ่นในการบังคับใช้นโยบายคุกกี้ตามข้อกำหนดของแอปพลิเคชัน: โดเมน, เส้นทาง, ปลอดภัย, httpOnly , ฯลฯ
  • ความสามารถในการเพิกถอนคุกกี้เซสชันเมื่อสงสัยว่ามีการขโมยโทเค็นโดยใช้ API การเพิกถอนโทเค็นที่มีอยู่เดิม
  • ความสามารถในการตรวจสอบการเพิกถอนเซสชันในการเปลี่ยนแปลงบัญชีที่สำคัญ

เข้าสู่ระบบ

สมมติว่าแอปพลิเคชันใช้คุกกี้ httpOnly ฝั่งเซิร์ฟเวอร์ให้ลงชื่อเข้าใช้ผู้ใช้ในหน้าเข้าสู่ระบบโดยใช้ SDK ไคลเอ็นต์ โทเค็น Firebase ID ถูกสร้างขึ้นและโทเค็น ID จะถูกส่งผ่าน HTTP POST ไปยังจุดสิ้นสุดการเข้าสู่ระบบของเซสชั่นโดยใช้ Admin SDK จะมีการสร้างคุกกี้เซสชัน ในความสำเร็จสถานะควรถูกล้างออกจากที่เก็บข้อมูลฝั่งไคลเอ็นต์

 firebase.initializeApp({
  apiKey: 'AIza…',
  authDomain: '<PROJECT_ID>.firebasepp.com'
});

// As httpOnly cookies are to be used, do not persist any state client side.
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE);

// When the user signs in with email and password.
firebase.auth().signInWithEmailAndPassword('user@example.com', 'password').then(user => {
  // Get the user's ID token as it is needed to exchange for a session cookie.
  return user.getIdToken().then(idToken = > {
    // Session login endpoint is queried and the session cookie is set.
    // CSRF protection should be taken into account.
    // ...
    const csrfToken = getCookie('csrfToken')
    return postIdTokenToSessionLogin('/sessionLogin', idToken, csrfToken);
  });
}).then(() => {
  // A page redirect would suffice as the persistence is set to NONE.
  return firebase.auth().signOut();
}).then(() => {
  window.location.assign('/profile');
});
 

ในการสร้างคุกกี้เซสชันเพื่อแลกเปลี่ยนกับโทเค็น ID ที่ให้มาจำเป็นต้องใช้จุดปลาย HTTP ส่งโทเค็นไปยังปลายทางโดยตั้งค่าช่วงเวลาเซสชันที่กำหนดเองโดยใช้ Firebase Admin SDK ควรมีมาตรการที่เหมาะสมเพื่อป้องกันการโจมตีจากการปลอมแปลง (CSRF)

Node.js

 app.post('/sessionLogin', (req, res) => {
  // Get the ID token passed and the CSRF token.
  const idToken = req.body.idToken.toString();
  const csrfToken = req.body.csrfToken.toString();
  // Guard against CSRF attacks.
  if (csrfToken !== req.cookies.csrfToken) {
    res.status(401).send('UNAUTHORIZED REQUEST!');
    return;
  }
  // Set session expiration to 5 days.
  const expiresIn = 60 * 60 * 24 * 5 * 1000;
  // Create the session cookie. This will also verify the ID token in the process.
  // The session cookie will have the same claims as the ID token.
  // To only allow session cookie setting on recent sign-in, auth_time in ID token
  // can be checked to ensure user was recently signed in before creating a session cookie.
  admin.auth().createSessionCookie(idToken, {expiresIn})
    .then((sessionCookie) => {
     // Set cookie policy for session cookie.
     const options = {maxAge: expiresIn, httpOnly: true, secure: true};
     res.cookie('session', sessionCookie, options);
     res.end(JSON.stringify({status: 'success'}));
    }, error => {
     res.status(401).send('UNAUTHORIZED REQUEST!');
    });
});
 

ชวา

 @POST
@Path("/sessionLogin")
@Consumes("application/json")
public Response createSessionCookie(LoginRequest request) {
  // Get the ID token sent by the client
  String idToken = request.getIdToken();
  // Set session expiration to 5 days.
  long expiresIn = TimeUnit.DAYS.toMillis(5);
  SessionCookieOptions options = SessionCookieOptions.builder()
      .setExpiresIn(expiresIn)
      .build();
  try {
    // Create the session cookie. This will also verify the ID token in the process.
    // The session cookie will have the same claims as the ID token.
    String sessionCookie = FirebaseAuth.getInstance().createSessionCookie(idToken, options);
    // Set cookie policy parameters as required.
    NewCookie cookie = new NewCookie("session", sessionCookie /* ... other parameters */);
    return Response.ok().cookie(cookie).build();
  } catch (FirebaseAuthException e) {
    return Response.status(Status.UNAUTHORIZED).entity("Failed to create a session cookie")
        .build();
  }
}
 

หลาม

 @app.route('/sessionLogin', methods=['POST'])
def session_login():
    # Get the ID token sent by the client
    id_token = flask.request.json['idToken']
    # Set session expiration to 5 days.
    expires_in = datetime.timedelta(days=5)
    try:
        # Create the session cookie. This will also verify the ID token in the process.
        # The session cookie will have the same claims as the ID token.
        session_cookie = auth.create_session_cookie(id_token, expires_in=expires_in)
        response = flask.jsonify({'status': 'success'})
        # Set cookie policy for session cookie.
        expires = datetime.datetime.now() + expires_in
        response.set_cookie(
            'session', session_cookie, expires=expires, httponly=True, secure=True)
        return response
    except exceptions.FirebaseError:
        return flask.abort(401, 'Failed to create a session cookie')
 

ไป

 return func(w http.ResponseWriter, r *http.Request) {
	// Get the ID token sent by the client
	defer r.Body.Close()
	idToken, err := getIDTokenFromBody(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	// Set session expiration to 5 days.
	expiresIn := time.Hour * 24 * 5

	// Create the session cookie. This will also verify the ID token in the process.
	// The session cookie will have the same claims as the ID token.
	// To only allow session cookie setting on recent sign-in, auth_time in ID token
	// can be checked to ensure user was recently signed in before creating a session cookie.
	cookie, err := client.SessionCookie(r.Context(), idToken, expiresIn)
	if err != nil {
		http.Error(w, "Failed to create a session cookie", http.StatusInternalServerError)
		return
	}

	// Set cookie policy for session cookie.
	http.SetCookie(w, &http.Cookie{
		Name:     "session",
		Value:    cookie,
		MaxAge:   int(expiresIn.Seconds()),
		HttpOnly: true,
		Secure:   true,
	})
	w.Write([]byte(`{"status": "success"}`))
}
 

ค#

 // POST: /sessionLogin
[HttpPost]
public async Task<ActionResult> Login([FromBody] LoginRequest request)
{
    // Set session expiration to 5 days.
    var options = new SessionCookieOptions()
    {
        ExpiresIn = TimeSpan.FromDays(5),
    };

    try
    {
        // Create the session cookie. This will also verify the ID token in the process.
        // The session cookie will have the same claims as the ID token.
        var sessionCookie = await FirebaseAuth.DefaultInstance
            .CreateSessionCookieAsync(request.IdToken, options);

        // Set cookie policy parameters as required.
        var cookieOptions = new CookieOptions()
        {
            Expires = DateTimeOffset.UtcNow.Add(options.ExpiresIn),
            HttpOnly = true,
            Secure = true,
        };
        this.Response.Cookies.Append("session", sessionCookie, cookieOptions);
        return this.Ok();
    }
    catch (FirebaseAuthException)
    {
        return this.Unauthorized("Failed to create a session cookie");
    }
}

 

สำหรับแอปพลิเคชันที่มีความละเอียดอ่อนควรตรวจสอบ auth_time ก่อนที่จะออกคุกกี้เซสชันลดขนาดหน้าต่างการโจมตีในกรณีที่โทเค็น ID ถูกขโมย:

Node.js

 admin.auth().verifyIdToken(idToken)
  .then((decodedIdToken) => {
    // Only process if the user just signed in in the last 5 minutes.
   if (new Date().getTime() / 1000 - decodedIdToken.auth_time < 5 * 60) {
      // Create session cookie and set it.
      return admin.auth().createSessionCookie(idToken, {expiresIn});
    }
    // A user that was not recently signed in is trying to set a session cookie.
   // To guard against ID token theft, require re-authentication.
    res.status(401).send('Recent sign in required!');
  });
 

ชวา

 // To ensure that cookies are set only on recently signed in users, check auth_time in
// ID token before creating a cookie.
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
long authTimeMillis = TimeUnit.SECONDS.toMillis(
    (long) decodedToken.getClaims().get("auth_time"));

// Only process if the user signed in within the last 5 minutes.
if (System.currentTimeMillis() - authTimeMillis < TimeUnit.MINUTES.toMillis(5)) {
  long expiresIn = TimeUnit.DAYS.toMillis(5);
  SessionCookieOptions options = SessionCookieOptions.builder()
      .setExpiresIn(expiresIn)
      .build();
  String sessionCookie = FirebaseAuth.getInstance().createSessionCookie(idToken, options);
  // Set cookie policy parameters as required.
  NewCookie cookie = new NewCookie("session", sessionCookie);
  return Response.ok().cookie(cookie).build();
}
// User did not sign in recently. To guard against ID token theft, require
// re-authentication.
return Response.status(Status.UNAUTHORIZED).entity("Recent sign in required").build();
 

หลาม

 # To ensure that cookies are set only on recently signed in users, check auth_time in
# ID token before creating a cookie.
try:
    decoded_claims = auth.verify_id_token(id_token)
    # Only process if the user signed in within the last 5 minutes.
    if time.time() - decoded_claims['auth_time'] < 5 * 60:
        expires_in = datetime.timedelta(days=5)
        expires = datetime.datetime.now() + expires_in
        session_cookie = auth.create_session_cookie(id_token, expires_in=expires_in)
        response = flask.jsonify({'status': 'success'})
        response.set_cookie(
            'session', session_cookie, expires=expires, httponly=True, secure=True)
        return response
    # User did not sign in recently. To guard against ID token theft, require
    # re-authentication.
    return flask.abort(401, 'Recent sign in required')
except auth.InvalidIdTokenError:
    return flask.abort(401, 'Invalid ID token')
except exceptions.FirebaseError:
    return flask.abort(401, 'Failed to create a session cookie')
 

ไป

 return func(w http.ResponseWriter, r *http.Request) {
	// Get the ID token sent by the client
	defer r.Body.Close()
	idToken, err := getIDTokenFromBody(r)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	decoded, err := client.VerifyIDToken(r.Context(), idToken)
	if err != nil {
		http.Error(w, "Invalid ID token", http.StatusUnauthorized)
		return
	}
	// Return error if the sign-in is older than 5 minutes.
	if time.Now().Unix()-decoded.Claims["auth_time"].(int64) > 5*60 {
		http.Error(w, "Recent sign-in required", http.StatusUnauthorized)
		return
	}

	expiresIn := time.Hour * 24 * 5
	cookie, err := client.SessionCookie(r.Context(), idToken, expiresIn)
	if err != nil {
		http.Error(w, "Failed to create a session cookie", http.StatusInternalServerError)
		return
	}
	http.SetCookie(w, &http.Cookie{
		Name:     "session",
		Value:    cookie,
		MaxAge:   int(expiresIn.Seconds()),
		HttpOnly: true,
		Secure:   true,
	})
	w.Write([]byte(`{"status": "success"}`))
}
 

ค#

 // To ensure that cookies are set only on recently signed in users, check auth_time in
// ID token before creating a cookie.
var decodedToken = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
var authTime = new DateTime(1970, 1, 1).AddSeconds(
    (long)decodedToken.Claims["auth_time"]);

// Only process if the user signed in within the last 5 minutes.
if (DateTime.UtcNow - authTime < TimeSpan.FromMinutes(5))
{
    var options = new SessionCookieOptions()
    {
        ExpiresIn = TimeSpan.FromDays(5),
    };
    var sessionCookie = await FirebaseAuth.DefaultInstance.CreateSessionCookieAsync(
        idToken, options);
    // Set cookie policy parameters as required.
    this.Response.Cookies.Append("session", sessionCookie);
    return this.Ok();
}

// User did not sign in recently. To guard against ID token theft, require
// re-authentication.
return this.Unauthorized("Recent sign in required");
 

หลังจากลงชื่อเข้าใช้แล้วส่วนที่ได้รับการป้องกันการเข้าถึงทั้งหมดของเว็บไซต์ควรตรวจสอบคุกกี้เซสชันและตรวจสอบก่อนที่จะแสดงเนื้อหาที่ถูก จำกัด ตามกฎความปลอดภัยบางอย่าง

Node.js

 // Whenever a user is accessing restricted content that requires authentication.
app.post('/profile', (req, res) => {
  const sessionCookie = req.cookies.session || '';
  // Verify the session cookie. In this case an additional check is added to detect
  // if the user's Firebase session was revoked, user deleted/disabled, etc.
  admin.auth().verifySessionCookie(
    sessionCookie, true /** checkRevoked */)
    .then((decodedClaims) => {
      serveContentForUser('/profile', req, res, decodedClaims);
    })
    .catch(error => {
      // Session cookie is unavailable or invalid. Force user to login.
      res.redirect('/login');
    });
});
 

ชวา

 @POST
@Path("/profile")
public Response verifySessionCookie(@CookieParam("session") Cookie cookie) {
  String sessionCookie = cookie.getValue();
  try {
    // Verify the session cookie. In this case an additional check is added to detect
    // if the user's Firebase session was revoked, user deleted/disabled, etc.
    final boolean checkRevoked = true;
    FirebaseToken decodedToken = FirebaseAuth.getInstance().verifySessionCookie(
        sessionCookie, checkRevoked);
    return serveContentForUser(decodedToken);
  } catch (FirebaseAuthException e) {
    // Session cookie is unavailable, invalid or revoked. Force user to login.
    return Response.temporaryRedirect(URI.create("/login")).build();
  }
}
 

หลาม

 @app.route('/profile', methods=['POST'])
def access_restricted_content():
    session_cookie = flask.request.cookies.get('session')
    if not session_cookie:
        # Session cookie is unavailable. Force user to login.
        return flask.redirect('/login')

    # Verify the session cookie. In this case an additional check is added to detect
    # if the user's Firebase session was revoked, user deleted/disabled, etc.
    try:
        decoded_claims = auth.verify_session_cookie(session_cookie, check_revoked=True)
        return serve_content_for_user(decoded_claims)
    except auth.InvalidSessionCookieError:
        # Session cookie is invalid, expired or revoked. Force user to login.
        return flask.redirect('/login')
 

ไป

 return func(w http.ResponseWriter, r *http.Request) {
	// Get the ID token sent by the client
	cookie, err := r.Cookie("session")
	if err != nil {
		// Session cookie is unavailable. Force user to login.
		http.Redirect(w, r, "/login", http.StatusFound)
		return
	}

	// Verify the session cookie. In this case an additional check is added to detect
	// if the user's Firebase session was revoked, user deleted/disabled, etc.
	decoded, err := client.VerifySessionCookieAndCheckRevoked(r.Context(), cookie.Value)
	if err != nil {
		// Session cookie is invalid. Force user to login.
		http.Redirect(w, r, "/login", http.StatusFound)
		return
	}

	serveContentForUser(w, r, decoded)
}
 

ค#

 // POST: /profile
[HttpPost]
public async Task<ActionResult> Profile()
{
    var sessionCookie = this.Request.Cookies["session"];
    if (string.IsNullOrEmpty(sessionCookie))
    {
        // Session cookie is not available. Force user to login.
        return this.Redirect("/login");
    }

    try
    {
        // Verify the session cookie. In this case an additional check is added to detect
        // if the user's Firebase session was revoked, user deleted/disabled, etc.
        var checkRevoked = true;
        var decodedToken = await FirebaseAuth.DefaultInstance.VerifySessionCookieAsync(
            sessionCookie, checkRevoked);
        return ViewContentForUser(decodedToken);
    }
    catch (FirebaseAuthException)
    {
        // Session cookie is invalid or revoked. Force user to login.
        return this.Redirect("/login");
    }
}

 

ตรวจสอบคุกกี้เซสชันโดยใช้ Admin SDK VerifySessionCookie API นี่คือการดำเนินการค่าใช้จ่ายต่ำ ใบรับรองสาธารณะจะถูกสอบถามเริ่มแรกและเก็บไว้จนกว่าจะหมดอายุ การตรวจสอบคุกกี้เซสชันสามารถทำได้กับใบรับรองสาธารณะที่แคชไว้โดยไม่มีการร้องขอเครือข่ายเพิ่มเติม

หากคุกกี้ไม่ถูกต้องตรวจสอบให้แน่ใจว่าได้ล้างแล้วและขอให้ผู้ใช้ลงชื่อเข้าใช้อีกครั้ง มีตัวเลือกเพิ่มเติมให้ตรวจสอบการเพิกถอนเซสชัน โปรดทราบว่านี่จะเพิ่มคำขอเครือข่ายเพิ่มเติมทุกครั้งที่มีการตรวจสอบคุกกี้เซสชัน

เพื่อเหตุผลด้านความปลอดภัยคุกกี้เซสชัน Firebase ไม่สามารถใช้ร่วมกับบริการ Firebase อื่น ๆ ได้เนื่องจากระยะเวลาที่กำหนดเองซึ่งสามารถกำหนดระยะเวลาสูงสุด 2 สัปดาห์ แอปพลิเคชันทั้งหมดที่ใช้คุกกี้ฝั่งเซิร์ฟเวอร์คาดว่าจะบังคับใช้การตรวจสอบสิทธิ์หลังจากตรวจสอบฝั่งเซิร์ฟเวอร์คุกกี้เหล่านี้

Node.js

 admin.auth().verifySessionCookie(sessionCookie, true)
  .then((decodedClaims) => {
   // Check custom claims to confirm user is an admin.
    if (decodedClaims.admin === true) {
      return serveContentForAdmin('/admin', req, res, decodedClaims);
   }
    res.status(401).send('UNAUTHORIZED REQUEST!');
  })
  .catch(error => {
    // Session cookie is unavailable or invalid. Force user to login.
    res.redirect('/login');
  });
 

ชวา

 try {
  final boolean checkRevoked = true;
  FirebaseToken decodedToken = FirebaseAuth.getInstance().verifySessionCookie(
      sessionCookie, checkRevoked);
  if (Boolean.TRUE.equals(decodedToken.getClaims().get("admin"))) {
    return serveContentForAdmin(decodedToken);
  }
  return Response.status(Status.UNAUTHORIZED).entity("Insufficient permissions").build();
} catch (FirebaseAuthException e) {
  // Session cookie is unavailable, invalid or revoked. Force user to login.
  return Response.temporaryRedirect(URI.create("/login")).build();
}
 

หลาม

 try:
    decoded_claims = auth.verify_session_cookie(session_cookie, check_revoked=True)
    # Check custom claims to confirm user is an admin.
    if decoded_claims.get('admin') is True:
        return serve_content_for_admin(decoded_claims)

    return flask.abort(401, 'Insufficient permissions')
except auth.InvalidSessionCookieError:
    # Session cookie is invalid, expired or revoked. Force user to login.
    return flask.redirect('/login')
 

ไป

 return func(w http.ResponseWriter, r *http.Request) {
	cookie, err := r.Cookie("session")
	if err != nil {
		// Session cookie is unavailable. Force user to login.
		http.Redirect(w, r, "/login", http.StatusFound)
		return
	}

	decoded, err := client.VerifySessionCookieAndCheckRevoked(r.Context(), cookie.Value)
	if err != nil {
		// Session cookie is invalid. Force user to login.
		http.Redirect(w, r, "/login", http.StatusFound)
		return
	}

	// Check custom claims to confirm user is an admin.
	if decoded.Claims["admin"] != true {
		http.Error(w, "Insufficient permissions", http.StatusUnauthorized)
		return
	}

	serveContentForAdmin(w, r, decoded)
}
 

ค#

 try
{
    var checkRevoked = true;
    var decodedToken = await FirebaseAuth.DefaultInstance.VerifySessionCookieAsync(
        sessionCookie, checkRevoked);
    object isAdmin;
    if (decodedToken.Claims.TryGetValue("admin", out isAdmin) && (bool)isAdmin)
    {
        return ViewContentForAdmin(decodedToken);
    }

    return this.Unauthorized("Insufficient permissions");
}
catch (FirebaseAuthException)
{
    // Session cookie is invalid or revoked. Force user to login.
    return this.Redirect("/login");
}

 

ออกจากระบบ

เมื่อผู้ใช้ลงชื่อออกจากฝั่งไคลเอ็นต์ให้จัดการกับฝั่งเซิร์ฟเวอร์ผ่านจุดปลาย คำขอ POST / GET ควรส่งผลให้มีการล้างคุกกี้เซสชัน โปรดทราบว่าแม้ว่าคุกกี้จะถูกล้าง แต่ก็ยังคงใช้งานได้จนกว่าจะหมดอายุตามธรรมชาติ

Node.js

 app.post('/sessionLogout', (req, res) => {
  res.clearCookie('session');
  res.redirect('/login');
});
 

ชวา

 @POST
@Path("/sessionLogout")
public Response clearSessionCookie(@CookieParam("session") Cookie cookie) {
  final int maxAge = 0;
  NewCookie newCookie = new NewCookie(cookie, null, maxAge, true);
  return Response.temporaryRedirect(URI.create("/login")).cookie(newCookie).build();
}
 

หลาม

 @app.route('/sessionLogout', methods=['POST'])
def session_logout():
    response = flask.make_response(flask.redirect('/login'))
    response.set_cookie('session', expires=0)
    return response
 

ไป

 return func(w http.ResponseWriter, r *http.Request) {
	http.SetCookie(w, &http.Cookie{
		Name:   "session",
		Value:  "",
		MaxAge: 0,
	})
	http.Redirect(w, r, "/login", http.StatusFound)
}
 

ค#

 // POST: /sessionLogout
[HttpPost]
public ActionResult ClearSessionCookie()
{
    this.Response.Cookies.Delete("session");
    return this.Redirect("/login");
}

 

การเรียก API การเพิกถอนจะยกเลิกเซสชันและจะยกเลิกเซสชันอื่น ๆ ของผู้ใช้ทั้งหมดโดยบังคับให้ลงชื่อเข้าใช้ใหม่ สำหรับแอปพลิเคชันที่ละเอียดอ่อนแนะนำให้ใช้ช่วงเวลาที่สั้น

Node.js

 app.post('/sessionLogout', (req, res) => {
  const sessionCookie = req.cookies.session || '';
  res.clearCookie('session');
  admin.auth().verifySessionCookie(sessionCookie)
  .then((decodedClaims) => {
    return admin.auth().revokeRefreshTokens(decodedClaims.sub);
  })
  .then(() => {
    res.redirect('/login');
  })
  .catch((error) => {
     res.redirect('/login');
   });
});
 

ชวา

 @POST
@Path("/sessionLogout")
public Response clearSessionCookieAndRevoke(@CookieParam("session") Cookie cookie) {
  String sessionCookie = cookie.getValue();
  try {
    FirebaseToken decodedToken = FirebaseAuth.getInstance().verifySessionCookie(sessionCookie);
    FirebaseAuth.getInstance().revokeRefreshTokens(decodedToken.getUid());
    final int maxAge = 0;
    NewCookie newCookie = new NewCookie(cookie, null, maxAge, true);
    return Response.temporaryRedirect(URI.create("/login")).cookie(newCookie).build();
  } catch (FirebaseAuthException e) {
    return Response.temporaryRedirect(URI.create("/login")).build();
  }
}
 

หลาม

 @app.route('/sessionLogout', methods=['POST'])
def session_logout():
    session_cookie = flask.request.cookies.get('session')
    try:
        decoded_claims = auth.verify_session_cookie(session_cookie)
        auth.revoke_refresh_tokens(decoded_claims['sub'])
        response = flask.make_response(flask.redirect('/login'))
        response.set_cookie('session', expires=0)
        return response
    except auth.InvalidSessionCookieError:
        return flask.redirect('/login')
 

ไป

 return func(w http.ResponseWriter, r *http.Request) {
	cookie, err := r.Cookie("session")
	if err != nil {
		// Session cookie is unavailable. Force user to login.
		http.Redirect(w, r, "/login", http.StatusFound)
		return
	}

	decoded, err := client.VerifySessionCookie(r.Context(), cookie.Value)
	if err != nil {
		// Session cookie is invalid. Force user to login.
		http.Redirect(w, r, "/login", http.StatusFound)
		return
	}
	if err := client.RevokeRefreshTokens(r.Context(), decoded.UID); err != nil {
		http.Error(w, "Failed to revoke refresh token", http.StatusInternalServerError)
		return
	}

	http.SetCookie(w, &http.Cookie{
		Name:   "session",
		Value:  "",
		MaxAge: 0,
	})
	http.Redirect(w, r, "/login", http.StatusFound)
}
 

ค#

 // POST: /sessionLogout
[HttpPost]
public async Task<ActionResult> ClearSessionCookieAndRevoke()
{
    var sessionCookie = this.Request.Cookies["session"];
    try
    {
        var decodedToken = await FirebaseAuth.DefaultInstance
            .VerifySessionCookieAsync(sessionCookie);
        await FirebaseAuth.DefaultInstance.RevokeRefreshTokensAsync(decodedToken.Uid);
        this.Response.Cookies.Delete("session");
        return this.Redirect("/login");
    }
    catch (FirebaseAuthException)
    {
        return this.Redirect("/login");
    }
}

 

ตรวจสอบคุกกี้เซสชันโดยใช้ห้องสมุด JWT บุคคลที่สาม

หากแบ็กเอนด์ของคุณเป็นภาษาที่ไม่รองรับโดย Firebase Admin SDK คุณยังสามารถตรวจสอบคุกกี้เซสชันได้ ขั้นแรกให้ ค้นหาห้องสมุด JWT บุคคลที่สามสำหรับภาษาของคุณ จากนั้นตรวจสอบส่วนหัวเพย์โหลดและลายเซ็นต์ของคุกกี้เซสชัน

ตรวจสอบว่าส่วนหัวของคุกกี้เซสชันสอดคล้องกับข้อ จำกัด ดังต่อไปนี้:

การเรียกร้องส่วนหัวคุกกี้เซสชันของ Firebase
alg ขั้นตอนวิธี "RS256"
kid รหัสคีย์ ต้องสอดคล้องกับหนึ่งในกุญแจสาธารณะที่อยู่ในรายการ https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys

ตรวจสอบว่า payload ของคุกกี้เซสชันสอดคล้องกับข้อ จำกัด ดังต่อไปนี้:

การเรียกร้องให้รับส่วนแบ่งคุกกี้ Firebase ของเซสชัน
exp เวลาหมดอายุ จะต้องอยู่ในอนาคต เวลาถูกวัดเป็นวินาทีตั้งแต่ UNIX ยุค การหมดอายุถูกกำหนดตามระยะเวลาที่กำหนดเองที่ให้ไว้เมื่อมีการสร้างคุกกี้
iat ออกให้ตามเวลา จะต้องอยู่ในอดีต เวลาถูกวัดเป็นวินาทีตั้งแต่ UNIX ยุค
aud ผู้ชม ต้องเป็นรหัสโครงการ Firebase ของคุณตัวระบุเฉพาะสำหรับโครงการ Firebase ของคุณซึ่งสามารถพบได้ใน URL ของคอนโซลของโครงการนั้น
iss บริษัท ผู้ออกหลักทรัพย์ จะต้องเป็น "https://session.firebase.google.com/<projectId>" "ซึ่ง <projectId> คือรหัสโครงการเดียวกับที่ใช้สำหรับ aud ดังกล่าวข้างต้น
sub เรื่อง ต้องเป็นสตริงที่ไม่ว่างเปล่าและต้องเป็น uid ของผู้ใช้หรืออุปกรณ์
auth_time เวลารับรองความถูกต้อง จะต้องอยู่ในอดีต เวลาที่ผู้ใช้รับรองความถูกต้อง สิ่งนี้ตรงกับ auth_time ของโทเค็น ID ที่ใช้ในการสร้างคุกกี้เซสชัน

ในที่สุดตรวจสอบให้แน่ใจว่าคุกกี้เซสชันได้รับการลงนามโดยคีย์ส่วนตัวที่สอดคล้องกับการเรียกร้องสิทธิ์ของโทเค็น รับกุญแจสาธารณะจาก https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys และใช้ห้องสมุด JWT เพื่อตรวจสอบลายเซ็น ใช้ค่า max-age ในส่วนหัว Cache-Control ของการตอบสนองจากปลายทางนั้นเพื่อพิจารณาว่าเมื่อใดที่จะรีเฟรชคีย์สาธารณะ

หากการตรวจสอบข้างต้นทั้งหมดสำเร็จคุณสามารถใช้หัวเรื่อง ( sub ) ของคุกกี้เซสชันเป็น uid ของผู้ใช้หรืออุปกรณ์ที่เกี่ยวข้อง