次の認証とMongoDBを使用して資格情報を使用した認証-パート1


セッション管理のように、いくつかのルート/ページを保護し、パスワードをハッシュして、サインアップとサインの間、ユーザーの資格情報を確認して、私たちが気をつけなければならないとき、認証は時々少しスケッチをすることができます.また、ゼロから認証を作成する作業の多くすることができます.
あなたが次に働いているならば.それはJWT、クッキーなどのような多くの認証スキームを提供し、また、Google、Facebookのようなサードパーティ製の認証プロバイダを使用して、そして、(はい!)不和でも.
また、次のAuthは、サーバーが簡単にトリミングすることはできませんので、セッション管理に役立ちます.
プロバイダー側は、メールやパスワードのようなユーザーの資格情報に基づいて認証を設定することを検討していきます.

次のauth 認証中に考慮すべきこと

  • クライアントフォームの検証
  • サーバーフォーム値の検証
  • 明白な理由のためにサインアップの間、ユーザーのパスワードをハッシュ化している

  • データベース
  • に格納する

  • のサインの間のハッシュされたパスワードのチェック
    非認証ユーザーのための経路を保護する
  • フロントエンドとバックエンド
  • の両方の適切なエラー処理

    必要なパッケージ


    私は次に使います.デモのフレームワークとしてのJS.

    それに沿って


  • 次の認証認証

  • パスワード
  • をハッシュするためのbycryptjs

  • MongoDB機能のためのMongoDB
  • ノート
    これはフロントエンドのチュートリアルではありませんので、成功したイベントやCSSについての通知は一切行いません.

    ウェブサイト足場


    ウェブサイトは4ページで構成されており、明らかにより良いデモのためのナババーです.
  • ホームページ
  • サインイン/サインアップページ
  • 変更パスワードページ

  • パッケージのインストールとデータベースの設定


    npm i next-auth mongodb bcryptjs
    
    インストール中に、当社のウェブサイト上で無料MongoDBアカウントを登録します.
    さて、ダッシュボードから接続コードを使用してデータベースに接続できます.我々は、より洗練された安全なコードのための.env.localファイルの中からMongurlを使用する必要があります.

    サインアップルート


    サインの前に、ユーザーはその特定のウェブサイトのためにサインアップする必要があります.NextJSは、私たちにNODEJS環境を使用してpages/apiフォルダでAPIコードを書くようにします.また、同じフォルダ構造ルートに従います.
    サインアップルートにはpages/api/auth/signup.js経路を作成します.また、POSTメソッドだけが受け入れられていることを確認する必要があります.

    サインアップルートで行うこと

  • ユーザー資格情報を得る
  • 検証
  • ならば、エラーコードを送ります
    に接続する
  • が既存のユーザーが同じ電子メールアドレス
  • で存在するかどうかチェックする
    を使用しているハッシュパスワード
    Bycrypt JSはパスワードのハッシュの間、約束を返します.
    password: await hash(password, 12)
    //hash(plain text, no. of salting rounds)
    
  • すべてがうまくいくなら、応答を送って、データベースとの密接な接続を送ってください
  • import { MongoClient } from 'mongodb';
    import { hash } from 'bcryptjs';
    async function handler(req, res) {
        //Only POST mothod is accepted
        if (req.method === 'POST') {
            //Getting email and password from body
            const { email, password } = req.body;
            //Validate
            if (!email || !email.includes('@') || !password) {
                res.status(422).json({ message: 'Invalid Data' });
                return;
            }
            //Connect with database
            const client = await MongoClient.connect(
                `mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASS}@${process.env.MONGO_CLUSTER}.n4tnm.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`,
                { useNewUrlParser: true, useUnifiedTopology: true }
            );
            const db = client.db();
            //Check existing
            const checkExisting = await db
                .collection('users')
                .findOne({ email: email });
            //Send error response if duplicate user is found
            if (checkExisting) {
                res.status(422).json({ message: 'User already exists' });
                client.close();
                return;
            }
            //Hash password
            const status = await db.collection('users').insertOne({
                email,
                password: await hash(password, 12),
            });
            //Send success response
            res.status(201).json({ message: 'User created', ...status });
            //Close DB connection
            client.close();
        } else {
            //Response for other than POST method
            res.status(500).json({ message: 'Route not valid' });
        }
    }
    
    export default handler;
    
    今、我々のサインアップルートが適当である今、フロントエンドをバックエンドに接続する時間です.

    投稿フォームの登録


    import { signIn } from 'next-auth/client';
    //...
    const onFormSubmit = async (e) => {
            e.preventDefault();
            //Getting value from useRef()
            const email = emailRef.current.value;
            const password = passwordRef.current.value;
            //Validation
            if (!email || !email.includes('@') || !password) {
                alert('Invalid details');
                return;
            }
            //POST form values
            const res = await fetch('/api/auth/signup', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    email: email,
                    password: password,
                }),
            });
            //Await for data for any desirable next steps
            const data = await res.json();
            console.log(data);
        };
    //...
    
    サインアップログインして、ログインロジックで動作しましょう.

    次のauthを使用してログインします


    次のAuthクライアントクライアントAPIだけでなく、残りのAPIを提供して

    The NextAuth.js client library makes it easy to interact with sessions from React applications.

    NextAuth.js exposes a REST API which is used by the NextAuth.js client.


    我々は、ユーザーの署名の両方を使用します.

    To add NextAuth.js to a project create a file called [...nextauth].js in pages/api/auth.

    All requests to /api/auth/* (signin, callback, signout, etc) will automatically be handed by NextAuth.js.


    次のauthからこの助けを借りて、我々はデータベースに格納されたユーザーをチェックするために我々自身のサインイン論理を実装する必要があります.

    経路の中で行うべきこと


    JWT を使用するように設定される
  • 次のAuth(資格情報)からのプロバイダーを指定します
    より多くのプロバイダーのために、
  • に接続する
  • がユーザが存在するかどうかチェックする
  • ならば、エラー応答を送ります
  • ハッシュされたパスワードをDB
  • に格納されているパスワードと比較する
  • は、応答
  • を送ります
  • close db接続
  • [...nextauth].js
    import NextAuth from 'next-auth';
    import Providers from 'next-auth/providers';
    import { MongoClient } from 'mongodb';
    import { compare } from 'bcryptjs';
    
    export default NextAuth({
        //Configure JWT
        session: {
            jwt: true,
        },
        //Specify Provider
        providers: [
            Providers.Credentials({
                async authorize(credentials) {
                    //Connect to DB
                    const client = await MongoClient.connect(
                        `mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASS}@${process.env.MONGO_CLUSTER}.n4tnm.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`,
                        { useNewUrlParser: true, useUnifiedTopology: true }
                    );
                    //Get all the users
                    const users = await client.db().collection('users');
                    //Find user with the email  
                    const result = await users.findOne({
                        email: credentials.email,
                    });
                    //Not found - send error res
                    if (!result) {
                        client.close();
                        throw new Error('No user found with the email');
                    }
                    //Check hased password with DB password
                    const checkPassword = await compare(credentials.passowrd, result.passowrd);
                    //Incorrect password - send response
                    if (!checkPassword) {
                        client.close();
                        throw new Error('Password doesnt match');
                    }
                    //Else send success response
                    client.close();
                    return { email: result.email };
                },
            }),
        ],
    });