GoでGoogleのOauth2をたたくときにはまったことメモ
November 25, 2020
golangでOauth2を使おうと思った時は、oauth2が有名なのでこれは押さえとけばOK. 基本的にはexampleに載ってるけど、嵌ったポイントがあったので次に調べずに済むようにメモしてます.
import (
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
func newConf() *oauth2.Config {
return &oauth2.Config{
ClientID: os.Getenv("OAUTH_CLIENT_ID"),
ClientSecret: os.Getenv("OAUTH_CLIENT_SECRET"),
RedirectURL: os.Getenv("OAUTH_REDIRECT_URL"),
Scopes: []string{
"https://www.googleapis.com/auth/userinfo.email",
},
Endpoint: google.Endpoint,
}
}
conf := s.newConf()
// ここでリクエスト先のURLを作成する.
// 注意ポイントとしてはAccessTypeOfflineを設定しておかないと、refresh_tokenは発行されない.
// デフォルトではAccessTypeOnlineになっているらしい
url := conf.AuthCodeURL(os.Getenv("OAUTH_STATE"), oauth2.AccessTypeOffline)
// いったんここでアクセスするとリダイレクトURLに飛ばされる.
// リダイレクトURLで渡される"code"と"state"は必要なので押さえておく
// "scope"も一緒に渡されるけど、必要かは要調査
// 普通にサーバとして開発するなら、ここから下は別のメソッドになるはず
// stateが自分で用意したstateと同じかのチェック
// csrf攻撃対策に必要らしい.stateはランダムな値で用意する.
if req.State != os.Getenv("OAUTH_STATE") {
return fmt.Errorf("request is something wrong")
}
// "code"からaccess_tokenを発行する.
// refresh_tokenが来ている場合もtokの中に入る
conf := s.newConf()
tok, err := conf.Exchange(ctx, req.Code)
if err != nil {
return err
}
// tokからclientを作って、このクライアントを使ってリクエストを送る.
// 後は普通のhttp.Clientと同じような使いかたになりそう.
client := conf.Client(ctx, tok)
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
if err != nil {
return err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
fmt.Println(string(body))
return
}
ここからは普通にメモ
refresh_token
って何?
refresh_token
はaccess_token
よりも有効時間が長いトークン.
refresh_token
によって、access_token
を発行する.
実際にリクエストを送るときはaccess_token
を用いて送る.
上の例に出てきた client
を使うと勝手に access_token
を更新してくれるみたい.
注意点
refresh_token
は最初のログインの時しか返してくれない.(refresh_token
は有効時間が長いので発行しすぎは注意しなければならないから)
もし、開発時にrefresh_token
を発行しなおさないといけないってなったら、以下のリンクにアクセスして、permissionを消すとまた発行しなおされる.
https://myaccount.google.com/u/0/permissions?pli=1
id_token
とは何か
上の例で言うと conf.Exchange
したときに、id_token
が一緒に返ってきているみたい.
id_token
はOpenIDのtoken.
OpenIDはユーザーの認証とかに使われるもので、ユーザーの本人認証とかを出来るらしいけど、正直よく分かってない.
Goで使う場合は、go-oidcというライブラリを別途使う必要がある.