Chức năng chặn cho phép bạn thực thi mã tùy chỉnh để sửa đổi kết quả của việc người dùng đăng ký hoặc đăng nhập vào ứng dụng của bạn. Ví dụ: bạn có thể ngăn người dùng xác thực nếu họ không đáp ứng các tiêu chí nhất định hoặc cập nhật thông tin của người dùng trước khi đưa thông tin đó trở lại ứng dụng khách của bạn.
Trước khi bắt đầu
Để sử dụng các chức năng chặn, bạn phải nâng cấp dự án Firebase của mình lên Firebase Authentication with Identity Platform. Nếu bạn chưa nâng cấp, hãy thực hiện trước.
Hiểu chức năng chặn
Bạn có thể đăng ký chức năng chặn cho hai sự kiện:
beforeCreate
: Kích hoạt trước khi người dùng mới được lưu vào cơ sở dữ liệu Xác thực Firebase và trước khi mã thông báo được trả về ứng dụng khách của bạn.beforeSignIn
: Kích hoạt sau khi thông tin đăng nhập của người dùng được xác minh, nhưng trước khi Xác thực Firebase trả lại mã thông báo ID cho ứng dụng khách của bạn. Nếu ứng dụng của bạn sử dụng xác thực đa yếu tố, thì chức năng này sẽ kích hoạt sau khi người dùng xác minh yếu tố thứ hai của họ. Lưu ý rằng việc tạo người dùng mới cũng kích hoạtbeforeSignIn
, ngoàibeforeCreate
.
Hãy ghi nhớ những điều sau đây khi sử dụng chức năng chặn:
Hàm của bạn phải phản hồi trong vòng 7 giây. Sau 7 giây, Xác thực Firebase trả về lỗi và thao tác máy khách không thành công.
Mã phản hồi HTTP khác
200
được chuyển đến ứng dụng khách của bạn. Đảm bảo mã máy khách của bạn xử lý mọi lỗi mà chức năng của bạn có thể trả về.Các chức năng áp dụng cho tất cả người dùng trong dự án của bạn, bao gồm bất kỳ người dùng nào có trong đối tượng thuê . Xác thực Firebase cung cấp thông tin về người dùng cho chức năng của bạn, bao gồm mọi đối tượng thuê mà họ thuộc về, để bạn có thể phản hồi tương ứng.
Việc liên kết một nhà cung cấp danh tính khác với một tài khoản sẽ kích hoạt lại bất kỳ chức năng
beforeSignIn
nào đã đăng ký.Xác thực ẩn danh và tùy chỉnh không kích hoạt chức năng chặn.
Triển khai và đăng ký chức năng chặn
Để chèn mã tùy chỉnh của bạn vào các luồng xác thực người dùng, hãy triển khai và đăng ký các chức năng chặn. Sau khi các chức năng chặn của bạn được triển khai và đăng ký, mã tùy chỉnh của bạn phải hoàn tất thành công để quá trình xác thực và tạo người dùng thành công.
Triển khai chức năng chặn
Bạn triển khai chức năng chặn giống như cách bạn triển khai bất kỳ chức năng nào. (xem trang Bắt đầu Chức năng đám mây để biết chi tiết). Tóm tắt:
Viết Hàm đám mây xử lý sự kiện
beforeCreate
, sự kiệnbeforeSignIn
hoặc cả hai.Ví dụ: để bắt đầu, bạn có thể thêm các hàm cấm hoạt động sau vào
index.js
:const functions = require('firebase-functions'); exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => { // TODO }); exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { // TODO });
Các ví dụ trên đã bỏ qua việc triển khai logic xác thực tùy chỉnh. Xem các phần sau để tìm hiểu cách triển khai các chức năng chặn của bạn và các tình huống phổ biến để biết các ví dụ cụ thể.
Triển khai các chức năng của bạn bằng Firebase CLI:
firebase deploy --only functions
Bạn phải triển khai lại các chức năng của mình mỗi khi cập nhật chúng.
Đăng ký một chức năng chặn
Truy cập trang Cài đặt xác thực Firebase trong bảng điều khiển Firebase.
Chọn tab Chức năng chặn .
Đăng ký chức năng chặn của bạn bằng cách chọn nó từ trình đơn thả xuống bên dưới Trước khi tạo tài khoản (beforeCreate) hoặc Trước khi đăng nhập (beforeSignIn) .
Lưu các thay đổi của bạn.
Lấy thông tin người dùng và ngữ cảnh
Các sự kiện beforeSignIn
và beforeCreate
cung cấp các đối tượng User
và EventContext
chứa thông tin về việc người dùng đăng nhập. Sử dụng các giá trị này trong mã của bạn để xác định xem có cho phép tiến hành một thao tác hay không.
Để biết danh sách các thuộc tính có sẵn trên đối tượng User
, hãy xem tham chiếu API UserRecord
.
Đối tượng EventContext
chứa các thuộc tính sau:
Tên | Sự miêu tả | Ví dụ |
---|---|---|
locale | Ngôn ngữ ứng dụng. Bạn có thể đặt ngôn ngữ bằng SDK máy khách hoặc bằng cách chuyển tiêu đề ngôn ngữ trong API REST. | fr hoặc sv-SE |
ipAddress | Địa chỉ IP của thiết bị mà người dùng cuối đang đăng ký hoặc đăng nhập. | 114.14.200.1 |
userAgent | Tác nhân người dùng kích hoạt chức năng chặn. | Mozilla/5.0 (X11; Linux x86_64) |
eventId | Mã định danh duy nhất của sự kiện. | rWsyPtolplG2TBFoOkkgyg |
eventType | Loại sự kiện. Điều này cung cấp thông tin về tên sự kiện, chẳng hạn như beforeSignIn hoặc beforeCreate và phương thức đăng nhập được liên kết được sử dụng, chẳng hạn như Google hoặc email/mật khẩu. | providers/cloud.auth/eventTypes/user.beforeSignIn:password |
authType | Luôn là USER . | USER |
resource | Dự án hoặc đối tượng thuê Xác thực Firebase. | projects/ project-id /tenants/ tenant-id |
timestamp | Thời gian sự kiện được kích hoạt, được định dạng dưới dạng chuỗi RFC 3339 . | Tue, 23 Jul 2019 21:10:57 GMT |
additionalUserInfo | Một đối tượng chứa thông tin về người dùng. | AdditionalUserInfo |
credential | Một đối tượng chứa thông tin về chứng chỉ của người dùng. | AuthCredential |
Chặn đăng ký hoặc đăng nhập
Để chặn nỗ lực đăng ký hoặc đăng nhập, hãy ném HttpsError
vào hàm của bạn. Ví dụ:
Node.js
throw new functions.auth.HttpsError('permission-denied');
Bảng sau đây liệt kê các lỗi mà bạn có thể nêu ra, cùng với thông báo lỗi mặc định của chúng:
Tên | Mã số | Tin nhắn |
---|---|---|
invalid-argument | 400 | Khách hàng đã chỉ định một đối số không hợp lệ. |
failed-precondition | 400 | Yêu cầu không thể được thực hiện trong trạng thái hệ thống hiện tại. |
out-of-range | 400 | Khách hàng đã chỉ định một phạm vi không hợp lệ. |
unauthenticated | 401 | Mã thông báo OAuth bị thiếu, không hợp lệ hoặc đã hết hạn. |
permission-denied | 403 | Khách hàng không có đủ quyền. |
not-found | 404 | Không tìm thấy tài nguyên được chỉ định. |
aborted | 409 | Xung đột đồng thời, chẳng hạn như xung đột đọc-sửa đổi-ghi. |
already-exists | 409 | Tài nguyên mà khách hàng cố gắng tạo đã tồn tại. |
resource-exhausted | 429 | Hết định mức tài nguyên hoặc đạt đến giới hạn tốc độ. |
cancelled | 499 | Yêu cầu bị hủy bởi khách hàng. |
data-loss | 500 | Mất dữ liệu không thể phục hồi hoặc hỏng dữ liệu. |
unknown | 500 | Lỗi máy chủ không xác định. |
internal | 500 | Lỗi máy chủ nội bộ. |
not-implemented | 501 | Phương thức API không được máy chủ triển khai. |
unavailable | 503 | Dịch vụ Không sẵn có. |
deadline-exceeded | 504 | Đã vượt quá thời hạn yêu cầu. |
Bạn cũng có thể chỉ định một thông báo lỗi tùy chỉnh:
Node.js
throw new functions.auth.HttpsError('permission-denied', 'Unauthorized request origin!');
Ví dụ sau đây cho thấy cách chặn người dùng không thuộc một miền cụ thể đăng ký ứng dụng của bạn:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
// (If the user is authenticating within a tenant context, the tenant ID can be determined from
// user.tenantId or from context.resource, e.g. 'projects/project-id/tenant/tenant-id-1')
// Only users of a specific domain can sign up.
if (user.email.indexOf('@acme.com') === -1) {
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email "${user.email}"`);
}
});
Bất kể bạn sử dụng thông báo mặc định hay tùy chỉnh, Cloud Function sẽ bao bọc lỗi và gửi lại cho khách hàng dưới dạng lỗi nội bộ. Ví dụ:
throw new functions.auth.HttpsError('invalid-argument', `Unauthorized email user@evil.com}`);
Ứng dụng của bạn sẽ phát hiện lỗi và xử lý lỗi tương ứng. Ví dụ:
JavaScript
// Blocking functions can also be triggered in a multi-tenant context before user creation.
// firebase.auth().tenantId = 'tenant-id-1';
firebase.auth().createUserWithEmailAndPassword('johndoe@example.com', 'password')
.then((result) => {
result.user.getIdTokenResult()
})
.then((idTokenResult) => {
console.log(idTokenResult.claim.admin);
})
.catch((error) => {
if (error.code !== 'auth/internal-error' && error.message.indexOf('Cloud Function') !== -1) {
// Display error.
} else {
// Registration succeeds.
}
});
Sửa đổi người dùng
Thay vì chặn nỗ lực đăng ký hoặc đăng nhập, bạn có thể cho phép hoạt động tiếp tục, nhưng sửa đổi đối tượng User
được lưu vào cơ sở dữ liệu của Xác thực Firebase và được trả về ứng dụng khách.
Để sửa đổi người dùng, hãy trả lại một đối tượng từ trình xử lý sự kiện của bạn có chứa các trường để sửa đổi. Bạn có thể sửa đổi các trường sau:
-
displayName
-
disabled
-
emailVerified
-
photoURL
-
customClaims
-
sessionClaims
(chỉbeforeSignIn
)
Ngoại trừ sessionClaims
, tất cả các trường đã sửa đổi đều được lưu vào cơ sở dữ liệu của Xác thực Firebase, nghĩa là chúng được đưa vào mã thông báo phản hồi và tồn tại giữa các phiên của người dùng.
Ví dụ sau đây cho thấy cách đặt tên hiển thị mặc định:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
return {
// If no display name is provided, set it to "Guest".
displayName: user.displayName || 'Guest';
};
});
Nếu bạn đăng ký một trình xử lý sự kiện cho cả beforeCreate
và beforeSignIn
, hãy lưu ý rằng beforeSignIn
thực thi sau beforeCreate
. Các trường người dùng được cập nhật trong beforeCreate
hiển thị trong beforeSignIn
. Nếu bạn đặt một trường khác với sessionClaims
trong cả hai trình xử lý sự kiện, thì giá trị được đặt trong beforeSignIn
sẽ ghi đè giá trị được đặt trong beforeCreate
. Chỉ đối với sessionClaims
, chúng được chuyển đến các xác nhận quyền sở hữu mã thông báo của phiên hiện tại, nhưng không được duy trì hoặc lưu trữ trong cơ sở dữ liệu.
Ví dụ: nếu bất kỳ sessionClaims
nào được đặt, beforeSignIn
sẽ trả lại chúng cùng với bất kỳ beforeCreate
xác nhận quyền sở hữu nào và chúng sẽ được hợp nhất. Khi chúng được hợp nhất, nếu khóa sessionClaims
khớp với khóa trong customClaims
, thì customClaims
phù hợp đó sẽ bị khóa sessionClaims
ghi đè trong yêu cầu mã thông báo. Tuy nhiên, khóa customClaims
bị ghi đè sẽ vẫn được lưu trong cơ sở dữ liệu cho các yêu cầu trong tương lai.
Thông tin xác thực và dữ liệu OAuth được hỗ trợ
Bạn có thể chuyển thông tin đăng nhập và dữ liệu OAuth để chặn các chức năng từ các nhà cung cấp danh tính khác nhau. Bảng sau đây cho biết thông tin đăng nhập và dữ liệu nào được hỗ trợ cho từng nhà cung cấp danh tính:
Nhà cung cấp danh tính | Mã thông báo ID | Truy cập thẻ | Thời gian hết hạn | Bí mật mã thông báo | Làm mới mã thông báo | Yêu cầu đăng nhập |
---|---|---|---|---|---|---|
Đúng | Đúng | Đúng | KHÔNG | Đúng | KHÔNG | |
KHÔNG | Đúng | Đúng | KHÔNG | KHÔNG | KHÔNG | |
KHÔNG | Đúng | KHÔNG | Đúng | KHÔNG | KHÔNG | |
GitHub | KHÔNG | Đúng | KHÔNG | KHÔNG | KHÔNG | KHÔNG |
Microsoft | Đúng | Đúng | Đúng | KHÔNG | Đúng | KHÔNG |
KHÔNG | Đúng | Đúng | KHÔNG | KHÔNG | KHÔNG | |
Yahoo | Đúng | Đúng | Đúng | KHÔNG | Đúng | KHÔNG |
Quả táo | Đúng | Đúng | Đúng | KHÔNG | Đúng | KHÔNG |
SAML | KHÔNG | KHÔNG | KHÔNG | KHÔNG | KHÔNG | Đúng |
OIDC | Đúng | Đúng | Đúng | KHÔNG | Đúng | Đúng |
Làm mới mã thông báo
Để sử dụng mã thông báo làm mới trong chức năng chặn, trước tiên bạn phải chọn hộp kiểm trên trang Chức năng chặn của bảng điều khiển Firebase.
Bất kỳ nhà cung cấp danh tính nào cũng sẽ không trả lại mã thông báo làm mới khi đăng nhập trực tiếp bằng thông tin xác thực OAuth, chẳng hạn như mã thông báo ID hoặc mã thông báo truy cập. Trong trường hợp này, cùng một chứng chỉ OAuth phía máy khách sẽ được chuyển đến chức năng chặn.
Các phần sau đây mô tả từng loại nhà cung cấp danh tính cũng như thông tin đăng nhập và dữ liệu được hỗ trợ của họ.
Các nhà cung cấp OIDC chung
Khi người dùng đăng nhập bằng nhà cung cấp OIDC chung, thông tin xác thực sau sẽ được chuyển:
- Mã thông báo ID : Được cung cấp nếu luồng
id_token
được chọn. - Mã thông báo truy cập : Được cung cấp nếu dòng mã được chọn. Lưu ý rằng luồng mã hiện chỉ được hỗ trợ qua API REST.
- Làm mới mã thông báo : Được cung cấp nếu phạm vi
offline_access
được chọn.
Ví dụ:
const provider = new firebase.auth.OAuthProvider('oidc.my-provider');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
Khi người dùng đăng nhập bằng Google, thông tin đăng nhập sau sẽ được chuyển:
- mã thông báo ID
- Truy cập thẻ
- Làm mới mã thông báo : Chỉ được cung cấp nếu các thông số tùy chỉnh sau được yêu cầu:
-
access_type=offline
-
prompt=consent
, nếu người dùng đã đồng ý trước đó và không có phạm vi mới nào được yêu cầu
-
Ví dụ:
const provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
'access_type': 'offline',
'prompt': 'consent'
});
firebase.auth().signInWithPopup(provider);
Tìm hiểu thêm về mã thông báo làm mới của Google .
Khi người dùng đăng nhập bằng Facebook, thông tin xác thực sau sẽ được chuyển:
- Mã thông báo truy cập : Mã thông báo truy cập được trả lại có thể đổi lấy mã thông báo truy cập khác. Tìm hiểu thêm về các loại mã thông báo truy cập khác nhau được Facebook hỗ trợ và cách bạn có thể đổi chúng lấy mã thông báo tồn tại lâu dài .
GitHub
Khi người dùng đăng nhập bằng GitHub, thông tin xác thực sau sẽ được chuyển:
- Mã thông báo truy cập : Không hết hạn trừ khi bị thu hồi.
Microsoft
Khi người dùng đăng nhập bằng Microsoft, thông tin xác thực sau sẽ được chuyển:
- mã thông báo ID
- Truy cập thẻ
- Làm mới mã thông báo : Được chuyển đến chức năng chặn nếu phạm vi
offline_access
được chọn.
Ví dụ:
const provider = new firebase.auth.OAuthProvider('microsoft.com');
provider.addScope('offline_access');
firebase.auth().signInWithPopup(provider);
Yahoo
Khi người dùng đăng nhập bằng Yahoo, thông tin xác thực sau sẽ được chuyển mà không có bất kỳ tham số hoặc phạm vi tùy chỉnh nào:
- mã thông báo ID
- Truy cập thẻ
- Làm mới mã thông báo
Khi người dùng đăng nhập bằng LinkedIn, thông tin xác thực sau sẽ được chuyển:
- Truy cập thẻ
Quả táo
Khi người dùng đăng nhập bằng Apple, thông tin xác thực sau sẽ được chuyển mà không có bất kỳ tham số hoặc phạm vi tùy chỉnh nào:
- mã thông báo ID
- Truy cập thẻ
- Làm mới mã thông báo
kịch bản phổ biến
Các ví dụ sau minh họa một số trường hợp sử dụng phổ biến cho chức năng chặn:
Chỉ cho phép đăng ký từ một tên miền cụ thể
Ví dụ sau đây cho thấy cách ngăn người dùng không thuộc miền example.com
đăng ký với ứng dụng của bạn:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (!user.email || user.email.indexOf('@example.com') === -1) {
throw new functions.auth.HttpsError(
'invalid-argument', `Unauthorized email "${user.email}"`);
}
});
Chặn người dùng có email chưa được xác minh đăng ký
Ví dụ sau đây cho thấy cách ngăn người dùng có email chưa được xác minh đăng ký với ứng dụng của bạn:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.email && !user.emailVerified) {
throw new functions.auth.HttpsError(
'invalid-argument', `Unverified email "${user.email}"`);
}
});
Yêu cầu xác minh email khi đăng ký
Ví dụ sau đây cho thấy cách yêu cầu người dùng xác minh email của họ sau khi đăng ký:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
const locale = context.locale;
if (user.email && !user.emailVerified) {
// Send custom email verification on sign-up.
return admin.auth().generateEmailVerificationLink(user.email).then((link) => {
return sendCustomVerificationEmail(user.email, link, locale);
});
}
});
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (user.email && !user.emailVerified) {
throw new functions.auth.HttpsError(
'invalid-argument', `"${user.email}" needs to be verified before access is granted.`);
}
});
Xử lý một số email của nhà cung cấp danh tính là đã được xác minh
Ví dụ sau đây cho thấy cách coi email của người dùng từ một số nhà cung cấp danh tính nhất định là đã được xác minh:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.email && !user.emailVerified && context.eventType.indexOf(':facebook.com') !== -1) {
return {
emailVerified: true,
};
}
});
Chặn đăng nhập từ một số địa chỉ IP nhất định
Ví dụ sau đây về cách chặn đăng nhập từ các dải địa chỉ IP nhất định:
Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => {
if (isSuspiciousIpAddress(context.ipAddress)) {
throw new functions.auth.HttpsError(
'permission-denied', 'Unauthorized access!');
}
});
Đặt tùy chỉnh và yêu cầu phiên
Ví dụ sau đây cho thấy cách đặt yêu cầu tùy chỉnh và phiên:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (context.credential &&
context.credential.providerId === 'saml.my-provider-id') {
return {
// Employee ID does not change so save in persistent claims (stored in
// Auth DB).
customClaims: {
eid: context.credential.claims.employeeid,
},
// Copy role and groups to token claims. These will not be persisted.
sessionClaims: {
role: context.credential.claims.role,
groups: context.credential.claims.groups,
}
}
}
});
Theo dõi địa chỉ IP để giám sát hoạt động đáng ngờ
Bạn có thể ngăn hành vi trộm cắp mã thông báo bằng cách theo dõi địa chỉ IP mà người dùng đăng nhập và so sánh địa chỉ đó với địa chỉ IP trong các yêu cầu tiếp theo. Nếu yêu cầu có vẻ đáng ngờ — ví dụ: IP đến từ các khu vực địa lý khác nhau — bạn có thể yêu cầu người dùng đăng nhập lại.
Sử dụng yêu cầu phiên để theo dõi địa chỉ IP mà người dùng đăng nhập bằng:
Node.js
exports.beforeSignIn = functions.auth.user().beforeSignIn((user, context) => { return { sessionClaims: { signInIpAddress: context.ipAddress, }, }; });
Khi người dùng cố gắng truy cập các tài nguyên yêu cầu xác thực bằng Xác thực Firebase, hãy so sánh địa chỉ IP trong yêu cầu với IP được sử dụng để đăng nhập:
Node.js
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 request IP address const requestIpAddress = req.connection.remoteAddress; // Get sign-in IP address. const signInIpAddress = claims.signInIpAddress; // Check if the request IP address origin is suspicious relative to // the session 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 // geographical change in a short period of time, then it will give // stronger signals of possible abuse. if (!isSuspiciousIpAddressChange(signInIpAddress, requestIpAddress)) { // Suspicious IP address change. Require re-authentication. // You can also revoke all user sessions by calling: // admin.auth().revokeRefreshTokens(claims.sub). 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!' }) }); } }); });
Sàng lọc ảnh người dùng
Ví dụ sau đây cho thấy cách làm sạch ảnh hồ sơ của người dùng:
Node.js
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (user.photoURL) {
return isPhotoAppropriate(user.photoURL)
.then((status) => {
if (!status) {
// Sanitize inappropriate photos by replacing them with guest photos.
// Users could also be blocked from sign-up, disabled, etc.
return {
photoURL: PLACEHOLDER_GUEST_PHOTO_URL,
};
}
});
});
Để tìm hiểu thêm về cách phát hiện và làm sạch hình ảnh, hãy xem tài liệu Cloud Vision .
Truy cập thông tin đăng nhập OAuth của nhà cung cấp danh tính người dùng
Ví dụ sau minh họa cách lấy mã thông báo làm mới cho người dùng đã đăng nhập bằng Google và sử dụng mã đó để gọi API Lịch Google. Mã thông báo làm mới được lưu trữ để truy cập ngoại tuyến.
Node.js
const {OAuth2Client} = require('google-auth-library');
const {google} = require('googleapis');
// ...
// Initialize Google OAuth client.
const keys = require('./oauth2.keys.json');
const oAuth2Client = new OAuth2Client(
keys.web.client_id,
keys.web.client_secret
);
exports.beforeCreate = functions.auth.user().beforeCreate((user, context) => {
if (context.credential &&
context.credential.providerId === 'google.com') {
// Store the refresh token for later offline use.
// These will only be returned if refresh tokens credentials are included
// (enabled by Cloud console).
return saveUserRefreshToken(
user.uid,
context.credential.refreshToken,
'google.com'
)
.then(() => {
// Blocking the function is not required. The function can resolve while
// this operation continues to run in the background.
return new Promise((resolve, reject) => {
// For this operation to succeed, the appropriate OAuth scope should be requested
// on sign in with Google, client-side. In this case:
// https://www.googleapis.com/auth/calendar
// You can check granted_scopes from within:
// context.additionalUserInfo.profile.granted_scopes (space joined list of scopes).
// Set access token/refresh token.
oAuth2Client.setCredentials({
access_token: context.credential.accessToken,
refresh_token: context.credential.refreshToken,
});
const calendar = google.calendar('v3');
// Setup Onboarding event on user's calendar.
const event = {/** ... */};
calendar.events.insert({
auth: oauth2client,
calendarId: 'primary',
resource: event,
}, (err, event) => {
// Do not fail. This is a best effort approach.
resolve();
});
});
})
}
});