見出し画像

MERNスタック:「Signin with Google」の実装が簡単に

こんにちは、おおとろ(@digiangler)です。

Google を使用してユーザーを登録するオプションがあることには、たくさんの利点があります。安全であるだけでなく、多くの時間を節約できます。

この note では、passport-google-oauth2 を使用して新しいユーザーを登録し、このユーザーをデータベースに保存する方法を紹介します。MERN スタックの操作については、すでに基本的な知識があることを前提としています。


セットアップ

バックエンド

アプリケーションのルートには、「backend」という名前のフォルダがあります。このフォルダには、「server.js」ファイルと .env ファイルがあります。

フロントエンド

コンポーネントフォルダには、「App.js」ファイルで呼び出される「Authentication.js」という名前のコンポーネントがあります。サーバーはポート 4000 で実行されており、React アプリはポート 3000 で実行されています。


データベースの設定

npm を使用してマングースをインストールします。

npm i mongoose

「server.js」ファイルの先頭に mongoose をインポートします。

const mongoose = require('mongoose');

これで、新しいデータベースに接続できます。

私の場合、DB 名を「projectDB」としています。また、「useCreateIndex」を true に設定することを忘れないでください。これは後で必要になります。

mongoose.connect('mongodb://127.0.0.1:27017/projectDB', {
    useNewUrlParser: true, useUnifiedTopology: true
});

mongoose.set("useCreateIndex", true);

ユーザーを保存したいので、userSchema を作成しましょう。

const userSchema = new mongoose.Schema ({
    username: String,
    name: String,
    googleId: String,
    secret: String
});

スキーマができたので、ユーザーを作成できます。

const User = new mongoose.model("User", userSchema);

最後に、タイプミスが無いか確認しましょう!


Passport.js

Passport.js は、Node.js の認証ミドルウェアです。

詳しくはこちらのドキュメントを読んでください。

まず、次のパッケージをインストールする必要があります。

npm i dotenv mongoose-findorcreate passport passport-google-oauth20 passport-local passport-local-mongoose express-session

※ 長いので注意

これらがインストールされている間に、コーディングを開始していきましょう。ファイルの先頭に dotenv が必要です。.env ファイルから情報を取得できるようにするには、これが必要になります。

require("dotenv").config();

他の dependencies の下に、以下を追加します。

const session = require("express-session");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const findOrCreate = require("mongoose-findorcreate");

mongoose.connect(“…”); の直前に、セッションとパスポートを初期化します。

app.use(session( {
    secret: "Our little secret.",
    resave: false,
    saveUninitialized: false
}));

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

userSchema の下、const User =… 行のすぐ上に、次のプラグインを追加します。

userSchema.plugin(passportLocalMongoose);
userSchema.plugin(findOrCreate);

先に進む前に、まず OAuth クライアント ID とクライアントシークレットを取得する必要があります。


OAuth クライアント ID とクライアントシークレットを取得

次のページに移動します。

※ 以下のスクリーンショットは、この記事からお借りしたものです。

詳しい内容はブログをお読みください。

まず、新しいプロジェクトを作成して名前を付けます。

画像2

それが完了したら、[作成] をクリックします。

画像3

次に、作成したプロジェクトを選択します。

画像4

ここで、アプリに名前を付けることができます。

画像5

それが完了したら、OAuth クライアント ID とシークレットを作成します。

画像6

[アプリケーションの種類] で [Webアプリケーション] を選択します。また、次のように、承認された JavaScript のオリジンを入力することを忘れないでください。

画像7

通常、クライアント ID とクライアントシークレットが必要です。

画像8

コードに戻りましょう。


Google Strategy の追加

.env ファイルにクライアント ID とシークレットを追加します。

CLIENT_ID=longstringofcharactersendingingoogleeusercontent.com
CLIENT_SECRET=mediumsizedstringofcharachters

server.js ファイルに戻ります。const User = … 行の下に、次のコード行を追加します。

passport.use(User.createStrategy());
passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
        done(err, user);
    });
});

passport.use(new GoogleStrategy( {
    clientID: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    callbackURL: "http://localhost:4000/auth/google/callback",
    userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
},
function(accessToken, refreshToken, profile, cb) {
    User.findOrCreate({ googleId: profile.id, username: profile.id }, function (err, user) {
        return cb(err, user);
    });
}
));

ここでは、.env ファイルから CLIENT_ID と CLIENT_SECRET にアクセスしています。また、新しいユーザーを作成する場合は、middelware のルートで行いましょう。

app.get("/auth/google",
    passport.authenticate("google", { scope: ["profile"] })
);

app.get("/auth/google/callback",
    passport.authenticate("google", { failureRedirect: "http://localhost:3000" }),
 function(req, res) {
     // Successful authentication, redirect secrets.
    res.redirect("http://localhost:3000");
);

認証後にホームルートにリダイレクトする必要があります。あと、ログアウトオプションも追加しましょう。

app.get("/logout", function(req, res){
    res.redirect("http://localhost:3000/");
});


React にサインインボタンを追加する

Authenticate.js コンポーネントで、次のコードをレンダリングしています。これにより、Google ボタンでサインインが作成されます。

<form action="http://localhost:4000/auth/google">
    <button type="submit" className="google-button">
        <span className="google-button__icon">
            <svg viewBox="0 0 366 372" xmlns="http://www.w3.org/2000/svg"><path d="M125.9 10.2c40.2-13.9 85.3-13.6 125.3 1.1 22.2 8.2 42.5 21 59.9 37.1-5.8 6.3-12.1 12.2-18.1 18.3l-34.2 34.2c-11.3-10.8-25.1-19-40.1-23.6-17.6-5.3-36.6-6.1-54.6-2.2-21 4.5-40.5 15.5-55.6 30.9-12.2 12.3-21.4 27.5-27 43.9-20.3-15.8-40.6-31.5-61-47.3 21.5-43 60.1-76.9 105.4-92.4z" id="Shape" fill="#EA4335"/><path d="M20.6 102.4c20.3 15.8 40.6 31.5 61 47.3-8 23.3-8 49.2 0 72.4-20.3 15.8-40.6 31.6-60.9 47.3C1.9 232.7-3.8 189.6 4.4 149.2c3.3-16.2 8.7-32 16.2-46.8z" id="Shape" fill="#FBBC05"/><path d="M361.7 151.1c5.8 32.7 4.5 66.8-4.7 98.8-8.5 29.3-24.6 56.5-47.1 77.2l-59.1-45.9c19.5-13.1 33.3-34.3 37.2-57.5H186.6c.1-24.2.1-48.4.1-72.6h175z" id="Shape" fill="#4285F4"/><path d="M81.4 222.2c7.8 22.9 22.8 43.2 42.6 57.1 12.4 8.7 26.6 14.9 41.4 17.9 14.6 3 29.7 2.6 44.4.1 14.6-2.6 28.7-7.9 41-16.2l59.1 45.9c-21.3 19.7-48 33.1-76.2 39.6-31.2 7.1-64.2 7.3-95.2-1-24.6-6.5-47.7-18.2-67.6-34.1-20.9-16.6-38.3-38-50.4-62 20.3-15.7 40.6-31.5 60.9-47.3z" fill="#34A853"/></svg>
        </span>
        <span className="google-button__text">sign in with Google</span>
    </button>
</form>

参考に、スタイルシート(CSS)は以下になります。

.google-button {
    height: 40px;
    border-width: 0;
    background: white;
    color: #737373;
    border-radius: 5px;
    white-space: nowrap;
    box-shadow: 1px 1px 0px 1px rgba(0,0,0,0.1);
    transition-property: background-color, box-shadow;
    transition-duration: 150ms;
    transition-timing-function: ease-in-out;
    padding: 0;
    transform: scale(1.4);
}
.google-button:hover, .google-button:focus {
    box-shadow: 1px 4px 5px 1px rgba(0,0,0,0.2);
    outline: none;
    transform: scale(1.4) skewX(-0.4deg);
}
.google-button:active {
    outline: none;
    box-shadow: 1px 4px 5px 1px rgba(0,0,0,0.3);
    transition-duration: 10ms;
}
.google-button__icon {
    display: inline-block;
    vertical-align: middle;
    margin: 0px 0 8px 8px;
    width: 18px;
    height: 18px;
    box-sizing: border-box;
}
.google-button__icon--plus {
    width: 27px;
}
.google-button__text {
    display: inline-block;
    vertical-align: middle;
    padding: 0 24px;
    font-size: 14px;
    font-weight: bold;
    font-family: 'Roboto',arial,sans-serif;
}

ボタンをクリックすると、リダイレクトされます。

http://localhost:4000/auth/google

ユーザーがサインアップすると、新しい googleId がデータベースに作成されます。

以上


最後まで、読んで頂きありがとうございました❗

読んだ証明として、1 日 1 回クリックをお願い致します m(_ _)m
👇
人気ブログランキング

それでは、また。

画像1

是非、感想をコメントや SNS でくださると嬉しいです。

Twitter: @digiangler
Instagram: @digi_angler

また、スキボタンを ”こっそり” 押したり、サポートしてくださるのも、とても嬉しいです。

"こっそり" Twitter からのリツイートでの感想もくださると嬉しいです。

よろしければサポートよろしくお願い致します。頂いたサポートはライターとしての活動費に使わせて頂きます❗m(_ _)mまた、感想のツイートやリクエスト、ぜひぜひお寄せください(*⌒▽⌒*)