【Golang】Goa v3でAPIキー認証(APIKyeAuth)を設定する

経緯

GoaのAPIキー認証(APIKeyAuth)の実装例はJWT認証などと比べると数が非常に少なく、さらにv2から仕様が大きく変わっておりv3での具体的な実装例を見つけられなかったため、今回実装してみた例を紹介します。

参考にしたサイト

①goadesign/goa/blob/v3/dsl/security.go

github.com

GoaのGithubリポジトリです。大まかな実装例が乗っており、参考になります。



②Goa v1 や Goa v2 から v3 にアップグレードする

goa.design

v1やv2での実装例をv3に適用する際に参考にしました。


実装

Goa公式のCalculator Serviceのdesign.goを題材にします。(別オリジンからのリクエストを想定しています。)

package design

import (
    . "goa.design/goa/v3/dsl"
)

var _ = API("calc", func() {
    Title("Calculator Service")
    Description("Service for adding numbers, a Goa teaser")
    Server("calc", func() {
        Host("localhost", func() {
            URI("http://localhost:8000")
        })
    })
})

var _ = Service("calc", func() {
    Description("The calc service performs operations on numbers.")
    cors.Origin("接続元のURL", func() {
        cors.Headers("Access-Control-Allow-Origin", "Authorization")
        cors.Methods("GET")
        cors.Credentials()
    })
    Method("add", func() {
        Security(APIKeyAuth)
        Payload(func() {
            APIKey("api_key", "key", String, "API key used to perform authorization")
            Field(1, "a", Int, "Left operand")
            Field(2, "b", Int, "Right operand")
            Required("key", "a", "b")
        })

        Result(Int)

        HTTP(func() {
            GET("/add/{a}/{b}")
            Header("key:Authorization")
        })
    })
})

var APIKeyAuth = APIKeySecurity("api_key", func() {
    Description("Secures endpoint by requiring an API key.")
})

順に説明していきます。

var APIKeyAuth = APIKeySecurity("api_key", func() {
    Description("Secures endpoint by requiring an API key.")
})

まず、APIKeyAuthを使用するため、ファイル最下部で以下の変数設定を行っています。


var _ = Service("calc", func() {
    Description("The calc service performs operations on numbers.")
    cors.Origin("接続元のURL", func() {
        cors.Headers("Access-Control-Allow-Origin", "Authorization")
        cors.Methods("GET")
        cors.Credentials()
    })

次に、CORSの設定を行います。ここで、後ほど設定するAPIキーを格納するヘッダーもcors.Headersに追加しておく必要があります(ここではAuthorizationヘッダー)。これを設定しないとCORSはクリアできてもリクエストヘッダーからAPIキーを取得できません。


    Method("add", func() {
        Security(APIKeyAuth)
        Payload(func() {
            APIKey("api_key", "key", String, "API key used to perform authorization")
            Field(1, "a", Int, "Left operand")
            Field(2, "b", Int, "Right operand")
            Required("key", "a", "b")
        })

        Result(Int)

次に、Methodへ記述していきます。まず、このメソッドでAPIキー認証を適用することを宣言するため、Security(APIKeyAuth)を追加します。次にPayload内でAPIKeyを記述し、APIキーの変数について定義します。(gRPCで利用する際は、APIKeyFieldの設定が必要になるようです。詳しい仕様は以下を参照してください。)

pkg.go.dev

またRequiredに、APIキー用の変数を追加します。


    HTTP(func() {
        GET("/add/{a}/{b}")
        Header("key:Authorization")
    })

最後にHTTP部で、HeaderにてAPIキーを格納するヘッダーを設定します。括弧内は、”キー:ヘッダー”の組み合わせです。


以上が、APIキー認証を実装する場合のdesignとなります。