91508


GitHubでログインをしたあとに自分のアプリケーションサーバー（以下Appサーバー）とSPAのフロントエンド（以下SPA）でセッションを作りたいです。  
しかしGitHubでログイン後にAppサーバーに飛んでくるコールバックの中でセッションを作成して、その後のSPAからのリクエストに対してセッションを確認することができません。  
そもそもリダイレクトからだとセッションが作れなかったりするのでしょうか。  
よろしくおねがいします。

#### 処理の流れ

  1. SPA ユーザーがログインボタンをクリックする。
  2. APPサーバー Stateを作成しセッションに保存し、リクエストに付与しつつGitHubのログインにリダイレクト。
  3. GitHub ユーザーがログインや情報アクセスの許可をする。
  4. Appサーバー GitHubログイン後のコールバックを受け取りStateをセッション内のものと検証し、ログイン状態としアクセストークンなどが含まれるセッションを作成する。
  5. SPA ログイン状態のチェックや、情報のリクエストを行う。
  6. APPサーバー セッションからアクセストークンなどが読み込めない。

#### コード

Appサーバーはlocalhost:3000をngrokでアクセスする形にしたもの、SPAはlocalhost:8080を利用しています。  
Appサーバーはginを使いセッションにはgin-contrib/sessionsとgin-contrib/sessions/cookieを利用しています。

APPサーバーのセッション設定

[code]

    router := gin.Default()
    store := cookie.NewStore([]byte(os.Getenv("secret")))
    store.Options(sessions.Options{
        Path:   "/",
    })
    router.Use(sessions.Sessions("mysession", store))
    
[/code]

1

[code]

    <a href="2のコードをハンドラーとするAPPサーバーのURL">Login Github</a>
    
[/code]

2

[code]

    func (h *LoginHandler) LoginGithub(c *gin.Context) {
        session := sessions.Default(c)
        state := randomString(24)
        session.Set("state", state)
        session.Save()
        url := buildLoginUrl(state)
        c.Redirect(http.StatusMovedPermanently, url)
    }
    
[/code]

4

[code]

    func (h *LoginHandler) CallbackLoginGithub(c *gin.Context) {
        code := c.Query("code")
        state := c.Query("state")
        if code == "" || state == "" {
            log.Println(c.Query("error_description"))
            c.Status(http.StatusBadRequest)
            return
        }
        session := sessions.Default(c)
        if session.Get("state") != state {
            c.Status(http.StatusBadRequest)
            return
        }
        session.Clear()
        session.Set("token", "トークン")
        session.Save()
        c.Redirect(http.StatusMovedPermanently, "http://localhost:8080/")
    }
    
[/code]

6

[code]

    func (h *LoginHandler) GetLoginStatus(c *gin.Context) {
        session := sessions.Default(c)
        // 読み込めない
        token := session.Get("token")
        if token == nil {
            c.JSON(http.StatusOK, LoginStateResponse{
                LoggedIn: false,
            })
            return
        }
        c.JSON(http.StatusOK, LoginStateResponse{
            LoggedIn: true,
        })
    }
    
[/code]


CC BY-SA 4.0
2022-10-04T04:23:07.420
91441
2022-10-09T10:05:54.707
2022-10-04T05:22:12.427
3060
14222
question
go oauth cookie
OAuthでログイン後にセッションを作成したい


「処理の流れ」の5番にあたるSPAからAPIサーバーへのリクエストにfetchを使っていたのですが `credentials: 'include'`
のオプションが抜けていました。  
これによってAPIサーバーへCookieが送られていませんでした。

Cookieを送信するリクエストの例

[code]

    fetch(APIサーバーのアドレス, {
      method: 'GET',
      mode: 'cors',
      credentials: 'include', // ←これが大事
      headers: {
        'Accept': 'application/json',
        'X-Requested-With': 'Fetch',
      },
    })
    
[/code]


CC BY-SA 4.0
2022-10-09T10:05:54.707
91508
2022-10-09T10:05:54.707
14222
91441
answer