qin-team-recipe / 03-recipe-app-backend

0 stars 0 forks source link

認証回りの実装&説明 #35

Closed aopontann closed 1 year ago

aopontann commented 1 year ago

closes #35

概要

動作確認

既にユーザ登録を済ませている状態

  1. http://localhost:8080/auth/google/login へアクセス
  2. http://localhost:3000 へリダイレクトされる
  3. クッキーを取得
  4. postmanにセット
  5. postmanで GET http://localhost:8080/api/user/id へリクエストを送信
  6. ユーザIDとメールアドレスを取得できるか確認
aopontann commented 1 year ago

これから新しくハンドラ関数を作成するときは、user_handler.goGetUserId が参考になると思います。

func (s *Server) GetUserId(c *gin.Context) {
    // Authentication()でセットしたメールアドレスを取得
    email := c.MustGet("email").(string)
    uid, err := s.q.GetUserId(context.Background(), email)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }
    c.JSON(http.StatusOK, gin.H{"id": uid, "email": email})
}
aopontann commented 1 year ago

server.go/api/user/* 以下にアクセスしたとき、ハンドラ関数を実行する前にミドルウェアを実行するようにしました。

    //// 仮で作成 セッションの説明用 ////
    // グループを作成
    usr := api.Group("/user")
    // /api/user/* リンクにアクセスしたとき、登録したハンドラ関数(ここではGetUserId)を実行する前に Authentication() を実行するようにする処理
    usr.Use(s.Authentication())
    // ユーザIDのみ返すAPI
    usr.GET("/id", s.GetUserId)
aopontann commented 1 year ago

oauth_google.goAuthentication() を作成しました。

func (s *Server) Authentication() gin.HandlerFunc {
    return func(c *gin.Context) {
        // CookieにセットされたセッションIDを使い、redisからユーザのメールアドレスを取得する
        sid, _ := c.Cookie("session_id")
        email, err := s.rbd.Get(context.Background(), sid).Result()
        if err != nil {
            c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
            c.Abort()
        }
        // 次に実行されるハンドラ関数で取得したメールアドレスを使うための処理
        c.Set("email", email)
    }
}

c.Set("email", email) で次に実行されるハンドラ関数でメールアドレスを使えるようにします。 次に実行されたハンドラ関数でemail := c.MustGet("email").(string) とすることでメールアドレスを取得することができます。

aopontann commented 1 year ago

認証の流れ

  1. google ログインが成功すると、セッションストレージの redis に、ログインしたユーザのメールアドレスとセッションIDが保存されます。
  2. ブラウザのクッキーにはセッションIDが付与されます。
  3. 認証が必要なAPIにリクエストを送るとハンドラ関数を実行する前にミドルウェアの Authentication が実行されます。
  4. ミドルウェアの Authentication で redis からセッションIDを使って ログインユーザのメールアドレスを取得します。
  5. ハンドラ関数を内部で、ミドルウェアから取得したメールアドレスをSQLのWHERE 句などで使ってユーザ情報を取得します。
  6. 取得したユーザ情報を使って、ユーザのレシピを取得したり、いいねをしたりするSQLを実行します。
  7. SQLの結果をフロント側に返します

このような流れになるかと思います。 何か不明点などあれば教えてください!

aopontann commented 1 year ago

一旦マージします

takutok28 commented 1 year ago

ありがとうございます!LGTM!