背景
業務でoauth2パッケージを使っています。
このパッケージを使って自動でトークンを更新できるということを上司から伺ったので調べてみました。
oauth2パッケージとは
oauth2パッケージはOAuth 2.0仕様のクライアント実装に使用することができます。
OAuthのクライアントとは
外部アプリのリソース(例:Googleカレンダーの情報)を使いたいアプリのことです。
クライアントは認可サーバーにリソースへのアクセス権を要求します。
リソース所有者であるユーザーから許可されると、認可サーバーからアクセストークンがクライアントに返されます。
この時リフレッシュトークンも返すようにすることもできます。
リフレッシュトークンを使うことで有効期限切れのアクセストークンを再発行し、リソースへアクセスすることが可能になります。
こちらでOAuthについて記事を書いたので良ければご覧ください。
oauth2パッケージで自動でtoken更新をする
oauth2パッケージでは確かに自動でトークンを更新するようです。
func (*Config) Client
func (c *Config) Client(ctx context.Context, t *Token) *http.Client
Client returns an HTTP client using the provided token. The token will auto-refresh as necessary.
クライアントは提供されたトークンを使用してHTTPクライアントを返します。トークンは必要に応じて自動更新されます。
https://pkg.go.dev/golang.org/x/oauth2#Config.Client
GoogleCalendarAPIに関するOAuth2の例を以下に書きます。
これはリフレッシュトークンしかclientに渡していないので常にトークンがリフレッシュされるようになっています。
googleOAuth2Config := &oauth2.Config{
ClientID: GOOGLE_CLIENT_ID,
ClientSecret: GOOGLE_CLIENT_SECRET,
RedirectURL: GOOGLE_REDIRECT_URL,
Scopes: []string{
"https://www.googleapis.com/auth/calendar",
},
Endpoint: google.Endpoint,
}
hc := googleOAuth2Config.Client(ctx, &oauth2.Token{
RefreshToken: refreshToken,//リフレッシュトークンしか渡さない
// AccessToken: "" ← ゼロ値(空文字)
// Expiry: time.Time{} ← ゼロ値
}
//リクエスト構造体を作成
request, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
if err != nil {
return nil, errors.Newf("error creating request with url(%s) : %w", requestURL, err)
}
//リクエストをOAuth2クライアントから実行
resp, err := hc.Do(request)
リフレッシュトークンのみをDBに保存する理由
アクセストークンはそれだけでリソースにアクセスできるので流出のリスクを考えるとDBに保存しないのは納得です。
業務ではリフレッシュトークンのみをDBに保存していたのでなぜだろうと思い調べました。
リフレッシュトークンに加えてクライアントID、クライアントシークレットもアクセストークンの再発行に必要です。
これらは認可サーバーがクライアントを何者か特定するために必要なものです。
ですので、リフレッシュトークンが流出しても被害を抑えられるということでした。
またリフレッシュトークンは定期的に更新することで安全性を高められます。
以下を参考にしました。
まとめ
oauth2パッケージのclientを使うことでトークンを自動で更新し、リクエストを送ることができる。
参考
