Secure Google Cloud Functions http trigger with auth

前端 未结 6 1831
小鲜肉
小鲜肉 2020-12-02 22:33

I am trying out Google Cloud Functions today following this guide: https://cloud.google.com/functions/docs/quickstart

I created a function with an HTTP trigger, and

6条回答
  •  执笔经年
    2020-12-02 23:10

    After looking into this further, and taking a hint from @ricka's answer, I have decided to implement an authentication check for my cloud functions with a JWT token passed in in the form of an Authorization header access token.

    Here's the implementation in Node:

    const client = jwksClient({
      cache: true,
      rateLimit: true,
      jwksRequestsPerMinute: 5,
      jwksUri: "https://.auth0.com/.well-known/jwks.json"
    });
    
    function verifyToken(token, cb) {
      let decodedToken;
      try {
        decodedToken = jwt.decode(token, {complete: true});
      } catch (e) {
        console.error(e);
        cb(e);
        return;
      }
      client.getSigningKey(decodedToken.header.kid, function (err, key) {
        if (err) {
          console.error(err);
          cb(err);
          return;
        }
        const signingKey = key.publicKey || key.rsaPublicKey;
        jwt.verify(token, signingKey, function (err, decoded) {
          if (err) {
            console.error(err);
            cb(err);
            return
          }
          console.log(decoded);
          cb(null, decoded);
        });
      });
    }
    
    function checkAuth (fn) {
      return function (req, res) {
        if (!req.headers || !req.headers.authorization) {
          res.status(401).send('No authorization token found.');
          return;
        }
        const parts = req.headers.authorization.split(' ');
        if (parts.length != 2) {
          res.status(401).send('Bad credential format.');
          return;
        }
        const scheme = parts[0];
        const credentials = parts[1];
    
        if (!/^Bearer$/i.test(scheme)) {
          res.status(401).send('Bad credential format.');
          return;
        }
        verifyToken(credentials, function (err) {
          if (err) {
            res.status(401).send('Invalid token');
            return;
          }
          fn(req, res);
        });
      };
    }
    

    I use jsonwebtoken to verify the JWT token, and jwks-rsa to retrieve the public key. I use Auth0, so jwks-rsa reaches out to the list of public keys to retrieve them.

    The checkAuth function can then be used to safeguard the cloud function as:

    exports.get = checkAuth(function (req, res) {
        // do things safely here
    });
    

    You can see this change on my github repo at https://github.com/tnguyen14/functions-datastore/commit/a6b32704f0b0a50cd719df8c1239f993ef74dab6

    The JWT / access token can be retrieved in a number of way. For Auth0, the API doc can be found at https://auth0.com/docs/api/authentication#authorize-client

    Once this is in place, you can trigger the cloud function (if you have yours enabled with http trigger) with something like

    curl -X POST -H "Content-Type: application/json" \
    -H "Authorization: Bearer access-token" \
    -d '{"foo": "bar"}' \
    "https://.cloudfunctions.net/get"
    

提交回复
热议问题