0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KongでOAuth2.0認証(Client Credentialsフロー)を試す

Last updated at Posted at 2024-12-30

はじめに

KongのGet Started with Kongを読むと、Kongには認証方式が色々できると書かれていて、Key認証が紹介されている。
で、OAuth認証のやり方はどうするんだろう、と調べていたら、KongのBlogにOAuth認証の手順や、実際に動かした56さんの記事があった。
これらを参考にOAuth認証のやり方を自分なりに整理。なお、KongのインストールやOAuth認証の仕組みの説明は割愛。
基本Blogの設定に従っているが、リソースサーバであるAPIサーバとの接続は56さんの記事の中でGitHubにあげていたサンプルを参考にして、httpsでなくhttpに変更した。

前提条件

  • Kong Gatewayはdocker-composeでコンテナとして構築
  • APIサーバもコンテナで作成したが、KongからAPIサーバを呼び出せなかった。コンテナ同士で通信する場合、仕掛けが必要?よく分からなかったのでAPIサーバはコンテナを諦め、VagrantでVMを作成した
  • OAuth認証は4フローあるが、今回はClient Credentialsフローをターゲットにした。Client Credentialフローの詳細はRFCの和訳の「4.4. Client Credentials Grant」を参照。

APIサーバの設定

最初にProxy先となるAPIサーバを作成

基本はBlogの記事のとおり。

wb01のホスト名でVM作成後、以下を実施。コマンドのみ記載。

~$ mkdir project
~$ cd project
~/project$ yarn init
# 質問には全部デフォルト(リターン)で

https通信しないので、Blogと違って必要最小限のパッケージだけ

~/project$ yarn add express

Blogのとおり、APIサーバ用のJSONデータ用意。
GET /stepcountsで呼び出す。

project/data.json
{
  "alice": [
    { "date": "2021-01-01", "count": 14500 },
    { "date": "2021-01-02", "count": 6500 },
    { "date": "2021-01-03", "count": 28000 }
  ],
  "bob": [
    { "date": "2021-01-01", "count": 900 },
    { "date": "2021-01-02", "count": 1400 },
    { "date": "2021-01-03", "count": 1100 }
  ],
  "clark": [
    { "date": "2021-01-01", "count": 2500 },
    { "date": "2021-01-02", "count": 12000 },
    { "date": "2021-01-03", "count": 9500 }
  ]
}

56さんの記事を参考にhttpで/stepcountsのエンドポイント作成

project/index.js
// PATH: project/index.js

const port = 3000

const express = require('express')
const app = express()
const data = require('./data.json')

const getCurrentUser = ({ headers }) => {
  return headers['mock-logged-in-as'] ||
    headers['x-authenticated-userid']
}

app.get('/stepcounts', (req, res, next) => {
  console.log(req.headers)
  const user = getCurrentUser(req)
  if (!user) {
    res.status(401).send('Not authorized')
    return
  }
  res.send(data[user] || [])
})

app.listen(port, () => {
  console.log(`Server is listening on http://wb01:${port}`
  )
})

サーバ起動

~/project$ node index.js
Server is listening on http://wb01:3000

APIサーバの疎通確認

疎通確認用のクライアントとしてInsomniaでWebアクセスを試す。Postmanでもいいのだが、Header情報の書き換えができなかったりしたため、不便だったので使わず。

index.jsではmock-logged-in-asでユーザチェックをしているので、Header情報が不足しているとエラーになる。

http://wb01:3000/stepcountsmock-logged-in-asない場合
image.png

mock-logged-in-asを付与した場合、clarkの値が返ってくる。
image.png

Kong GatewayとAPIサーバの配置

ServiceとRouteを登録

最初にServiceを登録
image.png

サービス名「step-on-api-service」とURL入れる。
image.png

続いてRouteの登録
image.png

特に難しい部分はない。登録済みのServiceがプルダウンから選択可能。
RouteのエンドポイントはBlogだとhttpとhttps両方の設定にしているが、今回はhttpのみで/steponをPathとしている。

image.png

Kong GatewayとAPIサーバの通信確認

InsomniaからKongのRouteにアクセス。
アクセス先はhttp://localhost:8000/stepon/stepcounts。Headerにmock-logged-in-asも必要。

image.png

OAuth2プラグインの導入

Service「step-on-api-service」からOAuth2.0プラグインを追加。Serviceの中でPluginを追加するとGlobal設定されず、Serviceに閉じた範囲で有効になる。

image.png

oauthで検索し、OAuth 2.0 Authentificationを選択する。OSS版では使えないプラグインも表示される。
image.png

今回はOAuth認証フローのクライアント認証を試すので、Enable Client Credentialsにチェックを入れる。その他必要な情報を設定する。

image.png

すでにOAuth認証が有効になっているので、Access Tokenなしでアクセスしようとするとエラーになる。
image.png

OAuth認証を無効にしたい場合、Enabledのボタン押下で無効化できる。
無効化となると、先ほどAccess Tokenなしでエラーになったリクエストが再び成功する。

image.png

Client Application(API Consumer)を追加

誰がアクセスできるか設定する。
Client Applicationとしてshoeflyshoeの名前で利用者を登録する
image.png

最初にshoeflyshoeさんを登録

image.png

次にshowflyshoeさんに認証情報を登録する。クライアントがToken取得する際に必要な情報となる。
Consumersのshoeflyshoeを選択してCredentials情報を登録する。

image.png

image.png

client_id, client_secretを入力、Client Typeconfidentialが良さそう。
OAuth2.0のRFCの「2.1. Client Types」に記載あり。

image.png

以上の設定でOAuth2.0認証の設定は完了。
今回はClient Credentialsフローのみを有効にし、クライアント認証

OAuth2.0認証によるAPIアクセス

Client Credentialsフローをやってみる。

アクセスToken取得

以下の2通りのやり方がある。詳細は@TakahikoKawasakiさんのページで説明されている。

  • BODY部にclient_id,client_secretを設定
  • Head部にBASE64エンコードした情報を設定

Token取得のURLは/oauth2/tokenらしい。
grant_typeはclient_credentialsにする(RFC参照)

その1:BODY部にclient_id,client_secretを設定

Body部に値を埋め込む。
image.png

なお、RFCによれば、Content-Type=application/x-www-form-urlencodedとあるが、間違って指定してもTokenは取得できた。
image.png

その2:Head部にBASE64エンコードした情報を設定

client_idとclient_secretの値を":"でつなぎ、BASE64でエンコードしてToken取得リクエスト。
今回の例で言えばsome_client_id:some_client_secretをエンコードし、生成されたc29tZV9jbGllbnRfaWQ6c29tZV9jbGllbnRfc2VjcmV0をHeaderに入れる。先頭にBasic を入れ忘れないこと。

Body部はgrant_typeのみ
image.png

Header部にBASE64エンコード情報を入れる。
image.png

取得したAccessTokenを使ってAPIサーバにアクセス

AccessTokenが取得できたら、そのTokenを使ってAPIサーバにアクセス。
Tokenの先頭にbearer が必要。
image.png

もしTokenが誤っていたり、有効時間切れの場合はエラーになる、。
image.png

まとめ

Kongの各種設定がGUIから可能になって操作性が向上したので、GUIベースの設定方法の紹介です。
他のフローも同様の手順で試すことができるはずなので、そのうち試してみる。とはいえ、OAuth認証難しい。。。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?