使用Netlify Lambda函数通过Auth0验证Firebase
我有一个用Gatsby构建的web应用程序,它通过Auth0进行客户端身份验证。我想将Firebase用作我的项目的数据库,但我需要先对用户进行身份验证,然后他们才能读/写Firebase Firebase SDK(Firebase admin)有一个名为signInWithCustomToken(token)的函数,我以为可以将令牌从Auth0传递到该函数中,但这不起作用(请参阅:) 相反,我需要通过一个API代理Auth0的令牌,该API将使用firebase admin发布令牌。因为我的盖茨比网站托管在Netlify上,所以我计划使用Netlify Lambda函数获取代理Auth0的令牌。这就是我被卡住的地方 我按照本教程介绍了如何在Gastsby中使用Netlify Lambda函数: 然后,我进入Auth.js文件,其中包含Auth0代码,并在setSession中放弃了一个fetch调用。我将idToken从Auth0传递到fetch函数中的url中。我不确定这样做是否正确。我在教程中读到,它将在授权头中传递,但我不清楚这意味着什么。无论如何,下面是完整的auth.js文件:使用Netlify Lambda函数通过Auth0验证Firebase,firebase,lambda,auth0,Firebase,Lambda,Auth0,我有一个用Gatsby构建的web应用程序,它通过Auth0进行客户端身份验证。我想将Firebase用作我的项目的数据库,但我需要先对用户进行身份验证,然后他们才能读/写Firebase Firebase SDK(Firebase admin)有一个名为signInWithCustomToken(token)的函数,我以为可以将令牌从Auth0传递到该函数中,但这不起作用(请参阅:) 相反,我需要通过一个API代理Auth0的令牌,该API将使用firebase admin发布令牌。因为我的盖
import auth0 from 'auth0-js';
const windowGlobal = typeof window !== 'undefined' && window;
class Auth {
auth0 = new auth0.WebAuth({
domain: process.env.Auth_Domain,
clientID: process.env.Auth_ClientId,
redirectUri: process.env.Auth_Callback,
responseType: 'token id_token',
scope: 'openid profile email',
});
constructor() {
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
this.handleAuthentication = this.handleAuthentication.bind(this);
this.isAuthenticated = this.isAuthenticated.bind(this);
}
login() {
this.auth0.authorize();
}
logout() {
// Remove the locally cached profile to avoid confusing errors.
localStorage.removeItem('access_token');
localStorage.removeItem('id_token');
localStorage.removeItem('expires_at');
localStorage.removeItem('user');
windowGlobal.window.location.replace(`https://login.skillthrive.com/v2/logout/?returnTo=http%3A%2F%2Flocalhost:8000`)
}
handleAuthentication() {
if (typeof window !== 'undefined') {
this.auth0.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.setSession(authResult)
} else if (err) {
console.log(err);
}
});
}
}
isAuthenticated() {
const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
return new Date().getTime() < expiresAt;
}
setSession(authResult) {
const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
localStorage.setItem('access_token', authResult.accessToken);
localStorage.setItem('id_token', authResult.idToken);
localStorage.setItem('expires_at', expiresAt);
fetch(`/.netlify/functions/firebase?id=${authResult.idToken}`)
.then(response => console.log(response))
this.auth0.client.userInfo(authResult.accessToken, (err, user) => {
localStorage.setItem('user', JSON.stringify(user));
})
}
getUser() {
if (localStorage.getItem('user')) {
return JSON.parse(localStorage.getItem('user'));
}
}
getUserName() {
if (this.getUser()) {
return this.getUser().name;
}
}
}
export default Auth;
我试图一次将小部分合并到Lambda函数中:
var admin = require("firebase-admin");
const jwt = require('express-jwt');
const jwks = require('jwks-rsa');
// For more info, check https://www.netlify.com/docs/functions/#javascript-lambda-functions
export function handler(event, context, callback) {
console.log("queryStringParameters", event.queryStringParameters);
const jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${process.env.Auth_Domain}/.well-known/jwks.json`
}),
audience: process.env.Auth_Audience,
issuer: `https://${process.env.Auth_Domain}/`,
algorithm: 'RS256'
});
callback(null, {
// return null to show no errors
statusCode: 200, // http status code
body: JSON.stringify({
msg: "Hello, World! " + Math.round(Math.random() * 10),
}),
})
}
我试图通过控制台记录jwtCheck来查看它返回了什么,但我得到的只是一些奇怪的东西{[Function:d],除非:[Function],UnauthorizedError:[Function:r]}
如何将其合并到Lambda函数中?我发现了一个名为的模块,它允许我编写Lambda函数,就像它是用Express编写的一样。这让我很容易理解正在发生的事情,因此我最终获得了从Firebase返回新铸造令牌的代码:
const jwt = require('express-jwt');
const jwks = require('jwks-rsa');
const firebaseAdmin = require('firebase-admin');
// Config
const config = require('./config');
module.exports = function(app) {
// Auth0 athentication middleware
const jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${config.AUTH0_DOMAIN}/.well-known/jwks.json`
}),
audience: config.AUTH0_API_AUDIENCE,
issuer: `https://${config.AUTH0_DOMAIN}/`,
algorithm: 'RS256'
});
// Initialize Firebase Admin with service account
const serviceAccount = require(config.FIREBASE_KEY);
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: config.FIREBASE_DB
});
app.get('/auth/firebase', jwtCheck, (req, res) => {
// Create UID from authenticated Auth0 user
const uid = req.user.sub;
// Mint token using Firebase Admin SDK
firebaseAdmin.auth().createCustomToken(uid)
.then(customToken =>
// Response must be an object or Firebase errors
res.json({firebaseToken: customToken})
)
.catch(err =>
res.status(500).send({
message: 'Something went wrong acquiring a Firebase token.',
error: err
})
);
});
const express = require('express');
const serverless = require('serverless-http');
const cors = require('cors');
const jwt = require('express-jwt');
const jwks = require('jwks-rsa');
const firebaseAdmin = require('firebase-admin');
const app = express();
app.use(cors());
const jwtCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `${process.env.Auth_Domain}/.well-known/jwks.json`
}),
audience: `${process.env.Auth_ClientId}`,
issuer: `${process.env.Auth_Domain}`,
algorithm: 'RS256'
});
const serviceAccount = require('../firebase/firebase-keys.json');
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(serviceAccount),
databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`
});
// GET object containing Firebase custom token
app.get('/firebase', jwtCheck, async (req, res) => {
const {sub: uid} = req.user;
try {
const firebaseToken = await firebaseAdmin.auth().createCustomToken(uid);
res.json({firebaseToken});
} catch (err) {
res.status(500).send({
message: 'Something went wrong acquiring a Firebase token.',
error: err
});
}
});
module.exports.handler = serverless(app);
然后在客户端,我将fetch调用包装成如下函数,并在需要时使用它:
async setFirebaseCustomToken() {
const response = await fetch('/.netlify/functions/firebase', {
headers: {
'Authorization': `Bearer ${localStorage.getItem('id_token')}`,
},
});
const data = await response.json();
console.log(data.firebaseToken);
}
这段代码只是将新令牌记录到console.log中,但现在您将得到响应,可以在Firebase客户端执行您想要的操作。希望这有帮助