twitter护照在生产环境中不起作用

时间:2019-06-22 07:20:33

标签: node.js reactjs graphql

它在开发环境中工作得很好,但在生产环境中不工作。

当您按下正面的登录按钮时,它是“ / auth / twitter”路线 应该经过认证。

这是我的前台代码

import React from "react";
import { Mutation } from "react-apollo";
import { CREATE_USER } from "../../queries";
import { Link, withRouter } from "react-router-dom";
import {
    Grid,
    Form,
    Segment,
    Button,
    Header,
    Message,
    Icon,
    Transition
} from "semantic-ui-react";
import "./Auth.css";

class Signup extends React.Component {
    state = {
        username: "",
        email: "",
        password: "",
        passwordConfirmation: "",
        errors: [],
        onOpen: false
    };

    isFormValid = () => {
        const errors = [];
        let error;
        let valid = true;
        if (this.isFormEmpty(this.state)) {
            error = { message: "全てのフィールドを埋めてください" };
            this.setState({ errors: errors.concat(error) });
            valid = false;
        }
        if (!this.isPasswordValid(this.state)) {
            error = { message: "パスワードが不正です" };
            this.setState({ errors: errors.concat(error) });
            valid = false;
        }
        return valid;
    };

    isFormEmpty = ({ username, email, password, passwordConfirmation }) => {
        return (
            !username.length ||
            !email.length ||
            !password.length ||
            !passwordConfirmation.length
        );
    };

    isPasswordValid = ({ password, passwordConfirmation }) => {
        if (password < 6) {
            return false;
        } else if (password !== passwordConfirmation) {
            return false;
        } else {
            return true;
        }
    };

    displayErrors = errors => {
        return errors.map((error, i) => <p key={i}>{error.message}</p>);
    };

    handleChange = event => {
        const { name, value } = event.target;
        this.setState({ [name]: value });
    };

    handleSubmit = (event, createUser) => {
        event.preventDefault();
        if (this.isFormValid()) {
            this.setState({ errors: [] });
            createUser().then(async ({ data }) => {
                localStorage.setItem("token", data.createUser.token);
                await this.props.refetch();
            });
        }
    };

    handleInputError = (errors, inputName) => {
        return errors.some(error => error.message.includes(inputName))
            ? "error"
            : "";
    };

    render() {
        const {
            username,
            email,
            password,
            passwordConfirmation,
            errors,
            onOpen
        } = this.state;
        return (
            <Grid className="Auth" textAlign="center" verticalAlign="middle">
                <Grid.Column style={{ maxWidth: 367 }}>
                    <Header as="h2" icon color="purple" textAlign="center">
                        <Icon name="new pied piper" color="purple" /> Manehabi 会員登録
                    </Header>
                    {onOpen ? null : (
                        <Mutation
                            mutation={CREATE_USER}
                            variables={{ username, email, password, passwordConfirmation }}
                            onCompleted={() => this.setState({ onOpen: true })}>
                            {(createUser, { data, loading, error }) => {
                                if (errors.length === 0) {
                                    if (error) {
                                        this.setState({ errors: error.graphQLErrors[0].data });
                                    }
                                }

                                return (
                                    <Form
                                        size="large"
                                        onSubmit={event => this.handleSubmit(event, createUser)}>
                                        <Segment stacked>
                                            <Form.Input
                                                fluid
                                                name="username"
                                                icon="user"
                                                iconPosition="left"
                                                placeholder="ユーザ名"
                                                onChange={this.handleChange}
                                                value={username}
                                                className={this.handleInputError(errors, "ユーザー")}
                                                type="text"
                                            />
                                            <Form.Input
                                                fluid
                                                name="email"
                                                icon="mail"
                                                iconPosition="left"
                                                placeholder="Eメールアドレス"
                                                onChange={this.handleChange}
                                                value={email}
                                                className={this.handleInputError(errors, "Eメール")}
                                                type="email"
                                            />
                                            <Form.Input
                                                fluid
                                                name="password"
                                                icon="lock"
                                                iconPosition="left"
                                                placeholder="パスワード"
                                                onChange={this.handleChange}
                                                value={password}
                                                className={this.handleInputError(errors, "パスワード")}
                                                type="password"
                                            />
                                            <Form.Input
                                                fluid
                                                name="passwordConfirmation"
                                                icon="repeat"
                                                iconPosition="left"
                                                placeholder="パスワードの確認"
                                                onChange={this.handleChange}
                                                value={passwordConfirmation}
                                                className={this.handleInputError(errors, "パスワード")}
                                                type="password"
                                            />
                                            <Button
                                                disabled={loading}
                                                className={loading ? "loading" : ""}
                                                color="orange"
                                                size="large"
                                                fluid>
                                                会員登録
                                            </Button>

                                            <Button
                                                disabled={loading}
                                                className={loading ? "loading" : ""}
                                                color="twitter"
                                                size="large"
                                                style={{ margin: "1em 0 0 0" }}
                                                fluid
                                                as="a"
                                                href="/auth/twitter">
                                                <Icon name="twitter" /> Twitterで会員登録する
                                            </Button>
                                        </Segment>
                                    </Form>
                                );
                            }}
                        </Mutation>
                    )}

                    {errors.length > 0 && (
                        <Message error>
                            <h3>エラー</h3>
                            {this.displayErrors(errors)}
                        </Message>
                    )}

                    {onOpen ? null : (
                        <Message>
                            既に会員登録済みの方は
                            <Link to="signin"> こちらからログイン</Link>
                        </Message>
                    )}

                    {/* success message */}
                    <Transition
                        animation="fade"
                        visible={onOpen}
                        duration="2000"
                        onComplete={() => this.props.history.push("/habits")}>
                        <Message icon success size="massive">
                            <Message.Content>
                                <Icon name="check" />
                                <Message.Header>会員登録完了</Message.Header>
                                ようこそ.Manehabiへ
                            </Message.Content>
                        </Message>
                    </Transition>
                </Grid.Column>
            </Grid>
        );
    }
}

export default withRouter(Signup);

这是我的后端代码

const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const jwt = require("jsonwebtoken");
const path = require("path");
const passport = require("passport");
const cookieParser = require("cookie-parser"); // parse cookie header
const cookieSession = require("cookie-session");

require("./config/passport");

const { typeDefs } = require("./typeDefs.graphql");
const { resolvers } = require("./resolvers");

const { ApolloServer } = require("apollo-server-express");

const app = express();

const createToken = (user, secret, expiresIn) => {
    const { username, email } = user;
    const token = jwt.sign({ username, email }, secret, { expiresIn });
    return token;
};
const db = require("./config/keys").mongoURI;
const secret = require("./config/keys").secret;
const baseClientURL = require("./config/keys").baseClientURL;
const baseURL =
    process.env.NODE_ENV === "production"
        ? "https://manehabi.herokuapp.com"
        : "http://localhost:3000";

mongoose
    .connect(db, { useNewUrlParser: true })
    .then(() => console.log("MongoDB Connected"))
    .catch(err => console.log(err));

const corsOption = {
    origin: ["https://manehabi.herokuapp.com"],
    methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
    credentials: true
};
app.use(cors("*"));

app.use(passport.initialize());

const cookieKeys = require("./config/keys").cookieKeys;
app.use(
    cookieSession({
        name: "session",
        keys: [cookieKeys],
        maxAge: 24 * 60 * 60 * 100
    })
);

app.use(cookieParser());
app.use(passport.session());

app.get("/return-json", (req, res, next) => {
    res.redirect("/signup");
});
app.get(`/auth/twitter`, passport.authenticate("twitter"));
app.get(
    "/auth/twitter/callback",
    passport.authenticate("twitter", {
        failureRedirect: "/signin"
    }),
    (req, res) => {
        console.log(req.user);

        const token = createToken(req.user, secret, "1hr");
        res.redirect(`${baseURL}/habits?token=${token}`);
    }
);

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: async ({ req }) => {
        let token = null;
        let currentUser = null;

        try {
            token = req.headers["authorization"];
            if (token) {
                currentUser = await jwt.verify(token, secret);
                console.log("aaa");
            }
        } catch (err) {}
        return { currentUser };
    },
    // playground: {
    //  endpoint: `http://localhost:4000/graphql`,
    //  settings: {
    //      "editor.theme": "light"
    //  }
    // },
    formatError(err) {
        if (!err.originalError) {
            return err;
        }
        const data = err.originalError.data;
        const message = err.message || "何かエラーが発生しました。";
        const code = err.originalError.code;
        return { message, status: code, data };
    }
});

server.applyMiddleware({ app });

if (process.env.NODE_ENV === "production") {
    app.use(express.static("client/build"));

    const path = require("path");
    app.get("*", (req, res) => {
        res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
    });
}

const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
    console.log(`Server listhening on PORT ${PORT}`);
});

在生产环境中,按下按钮将不会进行身份验证,仅跳转到URL不会发生任何反应。

这是推特的护照

const passport = require("passport");
const twitterStrategy = require("passport-twitter").Strategy;
const consumerKey = require("./keys").consumerKey;
const consumerSecret = require("./keys").consumerSecret;
const User = require("../models/User");

const url = require("./keys").baseClientURL;

// serialize the user.id to save in the cookie session
// so the browser will remember the user when login
passport.serializeUser((user, done) => {
    done(null, user.id);
});
// deserialize the cookieUserId to user in the database
passport.deserializeUser((id, done) => {
    User.findById(id)
        .then(user => {
            done(null, user);
        })
        .catch(e => {
            done(new Error("Failed to deserialize an user"));
        });
});

passport.use(
    new twitterStrategy(
        {
            consumerKey,
            consumerSecret,
            callbackURL: `${url}/auth/twitter/callback`,
            userProfileURL:
                "https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true"
        },
        async (token, tokenSecret, profile, done) => {
            //認証通過後の処理はここに書く

            const { displayName, emails, photos, id, provider } = profile;
            const existedUser = await User.findOne({ email: emails[0].value });
            //callbackの呼び出し
            if (!existedUser) {
                const newUser = new User({
                    username: displayName,
                    email: emails[0].value,
                    imageUrl: photos[0].value,
                    provider: {
                        authId: id,
                        authType: provider,
                        token,
                        tokenSecret
                    }
                });
                await newUser.save();
                done(null, newUser);
            }

            done(null, existedUser);
        }
    )
);

0 个答案:

没有答案