Serverlessなコース-レッスン2:AWS認証を構築する方法


この記事はもともとで公開されました.
https://www.blog.duomly.com/lesson-2-serverless-authentication/

無記名認証へのイントロ


今日のレッスンでは、Serverless認証を学びます.
あなたは、すでに何がServerlessな「エピソードである」を終えましたか?
そうでなければ、ここで見つけることができます.
What is serverless
次に、Serverlessなコースの最初のレッスンを行うべきです.
ここで見つけることができます.
Lesson 1: Serverless how to get started tutorial for beginners
あなたが前にそれらを終えた場合は、今日のレッスンに焦点を当てることができますし、新しい、不可欠なスキルを学ぶ.
必要以上の機能を備えたサーバレス認証の構築に取り組みますので、もう少しコーディングできます.
MongoDBモデルをビルドする方法、Serverlessで登録する方法、MongoDBでログインする方法、およびServerlessでJWTトークンを確認する方法.
始めましょう!
閉じるこの動画はお気に入りから削除されています.

MongoDB接続のセットアップ方法


まず最初に、データベース接続設定を行うべきです.
そのためには、データベースを作成する必要があります.データベース接続に責任があるロジックを含んでいる.
const mongoose = require('mongoose');

let connection;

module.exports = db = () => {
  if(connection) {
    return Promise.resolve();
  }

  return mongoose.connect(process.env.DB)
    .then(database=>{
      connection = database.connections[0].readyState;
    });
}

JWTを無制限に追加します。気象研


次の手順で機能を作成し、ハンドラを指定し、今日のロジックのAPIパスを作成します.
無鉄砲に行きなさい.「YL」という名前の関数を開始し、ハンドラのファイルにパスを渡します.
functions:
  verify-jwt:
    handler: authentication/VerifyJWT.verify

サーバーなしでログインを追加します。気象研


次に、私たちは“login - login”という名前の関数を作成する必要があります.
ノードへのパスを渡します.JSモジュールとセットアップは、PostメソッドでHTTPエンドポイントとして.
API APIを設定します.
login:
  handler: authentication/AuthenticationHandler.login
  events:
    - http:
        path: auth/login
        method: post
        cors: true

Serverlessにレジスタを追加します。気象研


ログインワンに似て、ここでは、我々は機能を作成しなければなりません.
register:
  handler: authentication/AuthenticationHandler.register
  events:
    - http:
        path: auth/register
        method: post
        cors: true

MyProfileをServerlessに追加します。気象研


そして、Serverlessの最後のステップ.YMLは、関数myprofileという名前です.
つの違いがあります.
一つ目はAPI APIが手に入りました.
そして、2番目のものは、私たちが認可者として、Ren - verify JWTを使う必要があります.
myProfile:
  handler: user/UserHandler.myProfile
  events:
    - http:
        path: user/myprofile
        method: get
        cors: true
        authorizer: verify-jwt

MongoDBモデルを作成する方法


私たちのServerless準備ができて、おめでとう!
今、我々はユーザーに入ることができます.ユーザディレクトリのjsとそこにMongoDBモデルを作成します.
ユーザモデルにはいくつかのフィールドが含まれます.
最初の文字列は、文字列として電子メール、文字列としてのパスワードとブールとしてのプレミアム、および日付としてプレミア終了する必要があります.
すべてのスキーマをユーザとしてエクスポートします.
const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({  
  name: String,
  email: String,
  password: String,
  premium: Boolean,
  premiumEnds: Date,
});
mongoose.model('User', UserSchema);

module.exports = mongoose.model('User');

認証ハンドラを作成する


この手順では、私たちはただ、“認証”という名前のディレクトリを作成する必要があります.内部のJS.

認証ヘルパーを作成する


前の手順と同様に、ここでは、単にapi - authenticationherpersという名前のファイルを作成する必要があります.「はい」

で認証を作成する


今、我々はもう少し符号化に来ることができます.
認証ヘルパーに入りましょう.jsと、名前付きのエクスポートされたモジュールを作成します.
モジュール内でJJT記号を返し、トークン内にIDを渡します.
module.exports.signJWT = (id) => {
  return jwt.sign({ id: id }, process.env.JWT_SECRET, {expiresIn: 604800});
}

認証検証の登録確認


次のステップでは、次のモジュールを作成します.
これは、“with - validregister”という名前でなければなりません.そして、私たちの呼び出しの本体がすべての必要なデータを含むことを保証するロジックを含んでいます.
この場合、パスワードがあるかどうか確認し、6文字以上を確認する必要があります.
そして、私たちはメールを持っているかどうかを確認する必要があります.何かが欠けているならば、我々は約束を返さなければなりません.メッセージを拒否する.
module.exports.validRegistration = (body) => {
  if (!body.password || body.password.length <= 6) {
    return Promise.reject(new Error('Password need to be at least 7 characters.'));
  }
  if (!body.email) {
    return Promise.reject(new Error('Email is required'));
  }
  return Promise.resolve();
}

ノードでパスワードを比較する方法。js


今、我々は次のモジュールを作成する必要があります、これは“verifypasswordは”として認証プロセスで重要です.
機能の中で、我々は2つのパスワードを比較しなければなりません.
そのためには、このメソッドを使用しなければなりません.と比較して、約束を返します.パスワードが正しくない場合は拒否します.
module.exports.verifyPassword = (sentPassword, realPassword, userId) => {
  return bcrypt.compare(sentPassword, realPassword)
    .then(valid => !valid ? Promise.reject(new Error('Incorrect password.')) : this.signJWT(userId)
  );
}

認証関数とヘルパーを作成する


認証ハンドラに移動する必要があります.JSファイルとエクスポートされたモジュールを作成します.
そのモジュールは2つのargsを取るべきです、最初のものは要求としてのR rです、そして、2番目はCallバックとして、「cb cb」です.
最初のステップでは、コールバックを設定する必要があります.コールバックが発生したときに応答を送信するためにfalseとして呼び出します.
次に、DB接続といくつかの値を返します.
最初の関数は、解析された本体をレジスタ関数に渡し、次にレスポンスを作成し、最後にエラーを処理します.
次に、レジスタの機能を作成し、paramとして“body”を取ります.
レジスタの中で、私たちは入力を有効にします.
次に、ユーザが存在しないかどうかを確認します.もし存在していれば、エラーmsgを返します.そうでなければ、パスワードをbcryptしてユーザを作成します.
最後のステップとして、署名されたJWTをユーザーに返す必要があります.
module.exports.register = (r, cb) => {
  cb.callbackWaitsForEmptyEventLoop = false;
  return db()
    .then(() => register(JSON.parse(r.body)))
    .then(res => success(res))
    .catch(err => errResponse(err));
};

function register(body) {
  return validRegistration(body)
    .then(() => User.findOne({ email: body.email }))
    .then(exists => exists ? Promise.reject(new Error('User exists')) : bcrypt.hash(body.password, 8))
    .then(hashedPass => User.create({ name: body.name, email: body.email, password: hashedPass, premium: false}))
    .then(user => ({ auth: true, token: signJWT(user._id) })); 
}

ログイン機能とヘルパーを作成する


ログインモジュールは、レジスタとほぼ同じように見えます.ただ、レジスタを変更します.
しかし、ログインヘルパー機能は少し異なります.
まず、ユーザが少なくとも存在するかどうかをチェックする必要があります.もしそうでなければ、エラーMSGを返します.
もし存在していれば、すべての場合はVerifyPassword関数を呼び出し、SIGNEDJJWTを返します.
module.exports.login = (r, cb) => {
  cb.callbackWaitsForEmptyEventLoop = false;
  return db()
    .then(() => login(JSON.parse(r.body)))
    .then(res => success(res))
    .catch(err => errResponse(err));
};

function login(body) {
  return User.findOne({ email: body.email })
    .then(user => !user ? Promise.reject(new Error('Incorrect password or username')) : comparePassword(body.password, user.password, user._id))
    .then(signedJWT => ({ auth: true, token: signedJWT }));
}

VerifyJWT関数の作成


今、我々はVerifyJWTに入ることができます.JTファイルとJWTトークンにフォーカスします.
最初のステップとして、我々は、エクスポートされたモジュールを作成する必要があります.
このモジュールはJWTを使用します.関数を検証し、トークンが承認されていない場合にエラーを返します.
認可されている場合、コールバックとして返されるAWSセキュリティポリシーを生成する必要があります.
方針を返す可能性があるためには、まずそれを生成する必要があります.
そのためには、プリンシパルID、効果、リソースをparamsとして受け取る機能を生成します.
次に、効果とリソースがあるかどうかを確認します.
yesの場合、APIにアクセスできるポリシーを持つオブジェクトを作成できます.
あなたが方針に興味があるならば、我々はAWS認可されたドキュメンテーションで見つけることができます.
const jwt = require('jsonwebtoken');

module.exports.verify = (r, context, cb) => {
  const token = r.authorizationToken;
  if(token) {
    jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
      if (err)
        return cb(null, 'JWT not authorized');
      return cb(null, generatePolicy(decoded.id, 'Allow', r.methodArn))
    });
  } else {
    return cb(null, 'JWT not authorized');
  }
};

const generatePolicy = (principalId, effect, resource) => {
  const res = {};
  res.principalId = principalId;
  if (effect && resource) {
    const policyDocument = {
      Version: "2012-10-17",
      Statement: [
        {
          Action: "execute-api:Invoke",
          Effect: effect,
          Resource: resource
        }
      ]
    };
    res.policyDocument = policyDocument;
  }
  return res;
}

ユーザーハンドラでの関数とヘルパーの作成


ここでの最初のステップとして、ユーザのディレクトリに移動し、ユーザのディレクトリを作成します.
次に、そのファイルを開き、エクスポートされたモジュールの「myprofile」を作成します.
AuthenticationHandlerのログインまたはregister function handlerと同じように見えるべきです.jsは、しかし、レジスタの代わりに“myMyProfile”でなければなりません.
次に、モデルでFindByIdを返し、それを返します.
const User = require('./User');
const { success, errResponse } = require('../authentication/AuthenticationHelpers');

module.exports.myProfile = (r, cb) => {
  cb.callbackWaitsForEmptyEventLoop = false;
  return db()
    .then(() => myProfile(r.requestContext.authorizer.principalId))
    .then(res => success(res))
    .catch(err => errResponse(err));
};

function myProfile(id) {
  return User.findById(id)
    .then(user => !user ? Promise.reject('User not found.') : user)
    .catch(err => Promise.reject(new Error(err)));
}

テストアプリケーション(認証:トークン)


Woohoo、あなたの認証は準備ができている!
さて、最初に、あなたのアプリケーションをオフラインで起動する必要があります.
そのためには、端末を開き、次のように入力します.
sls offline start —skipCacheInvalidation
次に、郵便配達人を開くことができますし、APIを呼び出します.
最初の呼び出しとして、ポストにデータを送信することでユーザーを登録する必要があります.
http://localhost:3000/dev/auth/register
次に、Getメソッドを使用してプロファイルを取得できます.
そのためには、登録から返されたトークンを取る必要があります.
http://localhost:3000/dev/myprofile
あなたのユーザーは、応答としてプロファイルを取得する必要があります.

無セル認証の結論


おめでとう、あなたはノードでServerlessな認証を構築しました.js
今日、あなたはたくさんのことを学びました.
あなたは完全に働くREST APIを構築しました.そして、MongoDBデータベースに接続しました.
今日のエピソードのコードは次のとおりです
https://github.com/Duomly/aws-serverlesss-nodejs/tree/serverless-course-lesson-2
私は次のレッスンの順序を構築する方法を教えるために次のレッスンに参加するまで待つことができない!
私たちはどのように注文を作成し、それらを編集し、ステータス、削除、およびすべての適切なSaaSアプリケーションを含める必要がありますを更新する方法を学びます.

読書ありがとう.
DuomlyからのRadek