我注意到文档指定我可以创建一个令牌以在3600秒后过期[1],但我不知道如何使用auth(). createCustomToken来做到这一点…我可以使用jsonwektoken手动做到这一点,但似乎这应该可以直接使用fire base-admin库进行寻址。
另一个问题是,验证这样生成的我自己的token需要的秘密是什么,uid?
// demo server generating custom auth for firebase
import Koa from 'koa'
import Koajwt from 'koa-jwt'
import Token from './token'
const app = new Koa()
// Custom 401 handling if you don't want to expose koa-jwt errors to users
app.use(function(ctx, next){
return next().catch((err) => {
if (401 == err.status) {
ctx.status = 401
ctx.body = 'Protected resource, use Authorization header to get access\n'
} else {
throw err
}
})
})
// Unprotected middleware
app.use(function(ctx, next){
if (ctx.url.match(/^\/login/)) {
// use router , post, https to securely send an id
const conf = {
uid: 'sample-user-uid',
claims: {
// Optional custom claims to include in the Security Rules auth / request.auth variables
appid: 'sample-app-uid'
}
}
ctx.body = {
token: Token.generateJWT(conf)
}
} else {
return next();
}
});
// Middleware below this line is only reached if JWT token is valid
app.use(Koajwt({ secret: 'shared-secret' }))
// Protected middleware
app.use(function(ctx){
if (ctx.url.match(/^\/api/)) {
ctx.body = 'protected\n'
}
})
app.listen(3000);
//import jwt from 'jsonwebtoken'
import FirebaseAdmin from 'firebase-admin'
import serviceAccount from 'demo-admin-firebase-adminsdk-$$$$-$$$$$$.json'
export default {
isInitialized: false,
init() {
FirebaseAdmin.credential.cert(serviceAccount)
isInitialized = true
},
/* generateJWTprimiative (payload, signature, conf) {
// like: jwt.sign({ data: 'foobar' }, 'secret', { expiresIn: '15m' })
jwt.sign(payload, signature, conf)
} */
generateJWT (conf) {
if(! this.isInitialized)
init()
FirebaseAdmin.auth().createCustomToken(conf.uid, conf.claims)
.then(token => {
return token
})
.catch(err => {
console.log('no token generate because', err)
})
}
}
[1] https://firebase.google.com/docs/auth/admin/create-custom-tokens
您无法更改令牌过期时间。您找到的文档包括以下文字:
Firebase令牌符合OpenID ConnectJWT规范,这意味着保留以下声明,并且不能在附加声明中指定:… exp…
通过检查GitHub上的Firebase AdminSDK源代码进一步支持这一点。
在本节中:
public createCustomToken(uid: string, developerClaims?: {[key: string]: any}): Promise<string> {
// .... cut for length ....
const header: JWTHeader = {
alg: ALGORITHM_RS256,
typ: 'JWT',
};
const iat = Math.floor(Date.now() / 1000);
const body: JWTBody = {
aud: FIREBASE_AUDIENCE,
iat,
exp: iat + ONE_HOUR_IN_SECONDS,
iss: account,
sub: account,
uid,
};
if (Object.keys(claims).length > 0) {
body.claims = claims;
}
// .... cut for length ....
您可以看到exp
属性被硬编码为iatONE_HOUR_IN_SECONDS
其中常量在代码的其他地方定义为60*60
…
如果您想自定义到期时间,您必须通过第三方JWT包创建自己的令牌。
关于你的第二个问题,秘密通常存储在服务器环境变量中,是预先设置的字符串或密码。从技术上讲,你可以使用UID作为秘密,但从安全角度来看,这是一个可怕的想法——请不要这样做。你的秘密应该像你的密码一样,保持安全,不要把它和你的源代码一起上传到GitHub。你可以在这里的这些文档中阅读更多关于在Firebase中设置和检索环境变量的信息