Closed iChemy closed 1 month ago
原因は
var traqAPIConfig = traq.NewConfiguration()
の HTTPClient
フィールドが NewOauth2APIClient
を通して不正なトークンを利用したものに書き換えられてしまうこと.
func (repo *TraQRepository) GetUser(userID uuid.UUID) (*traq.User, error)
は
traqAPIConfig
を元に traQ の API を叩くが func (repo *TraQRepository) GetUser(userID uuid.UUID) (*traq.User, error)
内で HTTPClient
を書き換えることはないため先述のことが起こった後だと 不正な HTTPClient
フィールドの traqAPIConfig
でtraQ の API を叩きエラーが返ってしまう.
これは (当然) HTTPClient
が有効なものに書き換えられない限り続く
誰かがログインし直すと,その過程で func (repo *TraQRepository) GetUserMe(token *oauth2.Token) (*traq.User, error)
が呼ばれ,これは func NewOauth2APIClient(ctx context.Context, token *oauth2.Token) *traq.APIClient
で traqAPIConfig
の HTTPClient
フィールドを書き換え,適切なトークンを利用してこれが行われれば有効な traqAPIConfig
は有効な HTTPClient
フィールドを保持するためエラーがなくなる.
再現方法例
必要なもの: 2つの異なるブラウザ (ブラウザA, ブラウザBと呼称),bot の traQ へのアクセストークン
func (repo *Repository) LoginUser(query, state, codeVerifier string) (*domain.User, error)
を下のように書き換える (1例)
var once = 0
func (repo Repository) LoginUser(query, state, codeVerifier string) (domain.User, error) { // 省略 t, err := repo.TraQRepo.GetOAuthToken(query, state, codeVerifier) // 省略 if once == 0 { // たまたま不正なトークンに書き換える fmt.Println("GetOAuthToken unexpectedly return invalid token") t = &oauth2.Token{ AccessToken: "123456789123456789123456789123456789", // invalid token } once++ } traQUser, err := repo.TraQRepo.GetUserMe(t) // 省略 }
4. 書き換えた後に docker で開発環境を立ち上げる.このとき,各ブラウザは session を保持したままである必要がある.
5. ブラウザA, B ともに session があるため,ログインせずに localhost:3000 にアクセスしてknoQ が利用できることを確認する. (このとき,ブラウザAのユーザーがちゃんとbotになっていることを確認すること)
6. ブラウザB の session を削除しログインを試みる.このとき上述の `LoginUser` が走り `traqAPIConfig` の `HTTPClient` フィールドが不正なトークンで書き換えられるのでログインはできないはずである.
7. ここで無関係なブラウザAで knoQ を利用しようとするとできなくなっていることを確認する.(<- knoQを開いてみたらなんか利用できなくなってる現象を再現できた)
8. ブラウザBで再びログインを試みる.一回しか不正なトークンに書き換えないため今度は成功するはずである.
9. ブラウザAでknoQが利用できることを確認する.(<-誰かがログインし直すことでなぜか利用できるようになる現象を再現できた)
client := oauth2Config.Client(ctx, oauth2Token)
によって作成された *http.Client
で
req.Header.Set("Authorization", "Bearer ANOTHER_TOKEN")
なる *http.Request
,req
で リクエストを送った場合, Authorization
ヘッダーには oauth2Token
の方が設定されていることが確認できたので
HTTPClient
フィールドを書き換えてるのが悪いという考えであってそう.
closed by #565
不定期でタイトルの現象が発生し,
TraQUserMiddleware
などでエラーが返ってしまうためその間全ユーザーがknoQを利用できなくなる.誰かがsessionを消しログインに成功すれば解消する.