提问者:小点点

在Firebase中,创建具有特定exp的自定义令牌?


我注意到文档指定我可以创建一个令牌以在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


共1个答案

匿名用户

您无法更改令牌过期时间。您找到的文档包括以下文字:

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中设置和检索环境变量的信息