Firebase,React:如何在不使令牌过期的情况下发出经过身份验证的POST请求?

时间:2020-10-11 08:52:12

标签: reactjs firebase firebase-authentication axios

我有一个React组件,用于控制到我的Firestore的授权帖子。用户提交基于文本的信息,然后使用axios作为客户端将其发送到Firebase。唯一的问题是,当我尝试提交数据时,出现以下错误:

Firebase ID令牌已过期。从您的客户端应用中获取新的ID令牌,然后重试”。

我怀疑getIdToken()在客户端发送的令牌已过期,我不确定该如何解决。我尝试将其设置为getIdToken(true),该方法也不起作用。

到目前为止,唯一的“解决方案”是更改笔记本电脑的时间以匹配服务器的时区,这显然不是我要解决的问题。 因此,我只希望已登录的用户能够发布帖子而不会遇到此错误,请提供解决方案/建议。

这是GigRegister组件中的axios帖子。

      handleSubmit(e) {
        let user = auth().currentUser.uid;
        const gigData = {
          name: this.state.name,
          venue: this.state.venue,
          time: this.state.time,
          date: this.state.date,
          genre: this.state.genre,
          tickets: this.state.tickets,
          price: this.state.price,
          user: user
        };

        auth()
          .currentUser.getIdToken()
          .then(function (token) {
            axios(
              "https://us-central1-gig-fort.cloudfunctions.net/api/createGigListing",
              {
                method: "POST",
                headers: {
                  "content-type": "application/json",
                  Authorization: "Bearer " + token,
                },
                data: gigData,
              }
            );
          })
          .then((res) => {
            this.props.history.push("/Homepage");
          })
          .catch((err) => {
            console.error(err);
          });
      }

...这是express / firebase函数。包括FBauth中间件:

const FBAuth = (req, res, next) => {
    let idToken;
    if(req.headers.authorization && req.headers.authorization.startsWith('Bearer ')){
        idToken = req.headers.authorization.split('Bearer ')[1]
    } else {
        console.error('No token found')
        return res.status(403).json({error: 'Unauthorized'})
    }

    admin.auth().verifyIdToken(idToken)
    .then(decodedToken => {
        req.user = decodedToken;
        return db.collection('users')
        .where('userId', '==',req.user.uid)
        .limit(1)
        .get()
    })
    .then(data =>{
        req.user.venueName = data.docs[0].data().venueName;
        return next();
    })
    .catch(err => {
        console.error('Error while verifying token', err)
        return res.status(403).json(err)
    })
}


app.post('/createGigListing', FBAuth, (req,res) => {

    const newGig = {
        venueName: req.user.venueName,
        name: req.body.name,
        time: req.body.time,
        price: req.body.price,
        genre: req.body.genre,
        tickets: req.body.tickets,
        date: req.body.date,
        user:req.body.user,
        createdAt: new Date().toISOString()
    }
    db
    .collection('gig-listing')
    .add(newGig)
    .then(doc => {
        res.json({message: `document ${doc.id} created successfully`})
    })
    .catch(err =>{
        res.status(500).json({error: 'something went wrong'})
        console.error(err)
    })
})

万一有人需要,这里是整个GigRegister组件

import React from "react";
    import Header from "./Header";
    import TextField from "@material-ui/core/TextField";
    import Button from "@material-ui/core/Button";
    import axios from "axios";
    import * as firebase from 'firebase'
    import { auth } from 'firebase/app'
    import {Link} from 'react-router-dom'
    import UniqueVenueListing from './UniqueVenueListing'


    class GigRegister extends React.Component {
      constructor() {
        super();
        this.state = {
          name: "",
          venue: "",
          time: "",
          date: "",
          genre: "",
          tickets: "",
          price: "",
          userDetails: {},
          filterGigs: [],
          isLoggedIn:false,
          currentToken:{}
        };
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.handleClick = this.handleClick.bind(this);
      }

      handleChange(e) {
        this.setState({
          [e.target.name]: e.target.value,
        });
      }

      handleClick() {
        console.log("handle click reached");
        auth()
          .signOut()
          .then(() => {
            console.log("Successfully signed out");
          })
          .catch((err) => {
            console.log(err);
          });
      }

      authListener() {
        auth().onAuthStateChanged((user) => {
          if (user) {
            this.setState(
              {
                userDetails: user
              },
              () =>
                axios
                  .get(
                    "https://us-central1-gig-fort.cloudfunctions.net/api/getGigListings"
                  )
                  .then((res) => {
                    let filteredGigs = res.data.filter((gig) => {
                      return gig.user === this.state.userDetails.uid;
                    });
                    this.setState({
                      filterGigs: filteredGigs
                    });
                  })
            );
          } else {
            this.setState({
              userDetails: null,
            });
            console.log("no user signed in");
          }
        });
      }

      componentDidMount() {
        this.authListener();
      }


      handleSubmit(e) {
        let user = auth().currentUser.uid;
        const gigData = {
          name: this.state.name,
          venue: this.state.venue,
          time: this.state.time,
          date: this.state.date,
          genre: this.state.genre,
          tickets: this.state.tickets,
          price: this.state.price,
          user: user
        };

        auth()
          .currentUser.getIdToken()
          .then(function (token) {
            axios(
              "https://us-central1-gig-fort.cloudfunctions.net/api/createGigListing",
              {
                method: "POST",
                headers: {
                  "content-type": "application/json",
                  Authorization: "Bearer " + token,
                },
                data: gigData,
              }
            );
          })
          .then((res) => {
            this.props.history.push("/Homepage");
          })
          .catch((err) => {
            console.error(err);
          });
      }

      render() {

        return (
          <div className="gig-register">
            <Header />
            <div className="heading-container">
              <h1>Venue Dashboard</h1> <br></br>
              {this.state.userDetails ? (
                <h3>You are signed in as {this.state.userDetails.email}</h3>
              ) : null}
              <div className="gig-reg-buttons">
                {this.state.userDetails ? (
                  <Button onClick={this.handleClick}>Sign out </Button>
                ) : (
                  <Link to="/" style={{ textDecoration: "none" }}>
                    <Button>Sign In</Button>
                  </Link>
                )}
                <Link to="/Homepage" style={{ textDecoration: "none" }}>
                  <Button>Go to gig listings</Button>
                </Link>
              </div>
            </div>
            <div className="handle-gigs">
              <div className="reg-gig-input">
                <form onSubmit={this.handleSubmit}>
                  <h3>Register a gig</h3>
                  <br></br>
                  <TextField
                    placeholder="Event name"
                    defaultValue="Event name"
                    id="name"
                    name="name"
                    onChange={this.handleChange}
                  />
                  <TextField
                    placeholder="Time"
                    defaultValue="Time"
                    type="time"
                    label="Enter start time"
                    id="time"
                    name="time"
                    InputLabelProps={{
                      shrink: true,
                    }}
                    inputProps={{
                      step: 300, // 5 min
                    }}
                    onChange={this.handleChange}
                  />
                  <TextField
                    id="date"
                    label="Select date"
                    type="date"
                    defaultValue="2017-05-24"
                    InputLabelProps={{
                      shrink: true,
                    }}
                    onChange={(e) => {
                      this.setState({ date: e.target.value });
                    }}
                  />
                  <TextField
                    placeholder="Genre"
                    defaultValue="Genre"
                    id="genre"
                    name="genre"
                    onChange={this.handleChange}
                  />
                  <TextField
                    placeholder="Tickets"
                    defaultValue="Tickets"
                    id="tickets"
                    name="tickets"
                    onChange={this.handleChange}
                  />
                  <TextField
                    placeholder="Price"
                    defaultValue="Price"
                    id="price"
                    name="price"
                    onChange={this.handleChange}
                  />
                  <Button type="submit">Submit</Button>
                </form>
              </div>
              <div className="manage-gigs">
                <h3 className="manage-gig">Manage your gigs</h3>
                <br></br>
                {this.state.userDetails ? (
                  <UniqueVenueListing gigList={this.state.filterGigs} />
                ) : (
                  <h2>no gigs to show</h2>
                )}
              </div>
            </div>
          </div>
        );
      }
    }
    
    export default GigRegister

0 个答案:

没有答案