railsAPIを使ったログイン認証について

## この記事でどういう順番で実装していくかを記載しています。
今回この記事ではrails APIを使って簡単なAPIを作成できるようになるための手順をSTEPごとに分けて解説していきたいと思います。分からないことは別の記事や公式のリファレンスを確認して実装してください。

そもそも未経験エンジニアがAPIを学習しなければいけない理由としては、昨今の開発ではフロントエンドとバックエンドを分けて開発し、新しいサービスを作るごとに作りなおさずにバックエンドのアプリケーションからAPIをフロント側から呼び込んで使うことが増えてきているそうです。

私も理解して実装するまでにはかなりの時間がかかりましたが、順を追って学習していけばrailsAPIを使ったログイン認証を実装してみましょう！


## では実装の流れ
①railsAPIモードで新規プロジェクトを作成し、ユーザーモデルを作成する。
```ruby
rails new (プロジェクト名) --api
#ユーザー名とパスワードの実装は自分で調べましょう。パスワードはsecureにしてください。
rails generate model user (ユーザー名とパスワード)
```
②ユーザーのアプリケーションコントローラーを作成する
```
class Api::UsersController < ApplicationController
  def create
    user = User.new(user_params)
    if user.save
      render json:
        { user:{id: user.id, username: user.username, email: user.email }}, status: :created
    else
      render json: { errors: user.errors.full_messages }, status: :unprocessable_entity
    end
  end

  private

  def user_params
    params.require(:user).permit(:username, :email, :password)
  end
end
```

③JWTトークンと、リフレッシュトークンを発行するアプリケーションコントローラーを作成する
```ruby
#jwtのgemを読み込む  gemの詳細はこちらhttps://rubygems.org/gems/jwt/versions/2.2.1?locale=ja
gem 'jwt'  

#apprication_contoroller
class Api::SessionsController < ApplicationController
require 'jwt'
  # POST /api/login
  def create
    # userデータベースから入力されたemailとpasswordの組み合わせが正しければユーザーを取得する
    if 
      #正しい組み合わせのユーザーがいた場合トークンをレスポンスする部分は調べて作成してみてください！
      access_token = JWT.encode({}, 'secret_key')
      refresh_token = JWT.encode({}, 'refresh_secret')
      user.update(refresh_token: refresh_token)
        #レンダリングとしてjson形式でアクセストークンとリフレッシュトークンをレスポンスする。
      render json: { accessToken: access_token, refreshToken: refresh_token }, status: :ok
    else # 正しい組み合わせでない場合はunauthorizedで認証できない旨をレスポンス
    
    render status: :unauthorized
    end
  end

  # POST /api/refresh
  def refresh
    refresh_token = request.headers['X-Refresh-Token']
    return render status: :unauthorized unless refresh_token

    user = User.find_by(refresh_token: refresh_token)
    return render status: :forbidden unless user

    payload, = JWT.decode(refresh_token, 'refresh_secret')
    return render status: :forbidden unless payload['data']['user_id'] == user.id

    data = { user_id: user.id }
    access_token = JWT.encode({ data: data, exp: Time.current.since(30.seconds).to_i }, 'secret')
    render json: { accessToken: access_token } , status: :ok
  end
end

```

発行されたトークンからユーザーIDを取得する。

```ruby
class ApplicationController < ActionController::API

def current_user
  # トークンを取得する
  token = request.headers["Authorization"].split(" ")[1]
  # トークンからペイロードを取得する
  begin
    payload = JWT.decode(token, "secret_key", true, algorithm: "HS256")[0]
  rescue JWT::DecodeError
    return nil
  end
  # ペイロードからユーザーIDを取得する
  user_id = payload["data"]["user_id"]
  Rails.logger.debug "user_id: #{user_id}"
  # ユーザーIDからユーザーを取得する
  user = User.find_by(id: user_id)
  Rails.logger.debug "user: #{user.inspect}"
  user
end

end
```

あとはルーティングの設定をすればユーザー認証機能は実装完了となります。
rails APIモードではviewは作成されません。このrailsのバックエンドを実装しておけばフロントエンドのフレームワークからAPIを利用することが可能になります。
ちなみに今回APIの仕様は[RealWorld](https://realworld-docs.netlify.app/)の仕様の一部に準拠しています。

ユーザー認証ができているかどうかはPostman(APIを開発・テストするためのコラボレーションプラットフォーム)などを利用することで機能しているか確認することができます。
postmanについてはローカル環境で開発するのであればダウンロード版を利用してください。

エンジニアへ転向できるように一緒に頑張りましょう！

:::note warn
未経験エンジニアの私が学習した内容を記載しているためすべて鵜呑みにせずあっているかどうか自分でも確認してください。
:::

::: note
また、有識者の方で”ここ間違ているよ”とか”もっとこうした方がいいよ”ということがあれば教えてください！
:::