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 とクライアントシークレットを取得
次のページに移動します。
※ 以下のスクリーンショットは、この記事からお借りしたものです。
詳しい内容はブログをお読みください。
まず、新しいプロジェクトを作成して名前を付けます。
それが完了したら、[作成] をクリックします。
次に、作成したプロジェクトを選択します。
ここで、アプリに名前を付けることができます。
それが完了したら、OAuth クライアント ID とシークレットを作成します。
[アプリケーションの種類] で [Webアプリケーション] を選択します。また、次のように、承認された JavaScript のオリジンを入力することを忘れないでください。
通常、クライアント ID とクライアントシークレットが必要です。
コードに戻りましょう。
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
👇
人気ブログランキング
それでは、また。
是非、感想をコメントや SNS でくださると嬉しいです。
Twitter: @digiangler
Instagram: @digi_angler
また、スキボタンを ”こっそり” 押したり、サポートしてくださるのも、とても嬉しいです。
"こっそり" Twitter からのリツイートでの感想もくださると嬉しいです。