Skip to content

KtorサーバーでのDigest認証

必要な依存関係: io.ktor:ktor-server-auth

コード例: auth-digest

ネイティブサーバー
KtorはKotlin/Nativeをサポートしており、追加のランタイムや仮想マシンなしでサーバーを実行できます。
のサポート: ✖️

Digest認証スキームは、アクセス制御と認証に使用されるHTTPフレームワークの一部です。このスキームでは、ユーザー名とパスワードをネットワーク経由で送信する前に、ハッシュ関数が適用されます。

Ktorでは、ユーザーのログインと特定のルートの保護にDigest認証を使用できます。Ktorでの認証に関する一般情報は、Ktorサーバーでの認証と認可セクションで確認できます。

依存関係の追加

digest認証を有効にするには、ビルドスクリプトにktor-server-authアーティファクトを含める必要があります。

Kotlin
Groovy
XML

Digest認証フロー

Digest認証フローは次のようになります。

  1. クライアントは、Authorizationヘッダーなしで、サーバーアプリケーション内の特定のルートにリクエストを行います。

  2. サーバーは、クライアントに401(Unauthorized)応答ステータスで応答し、WWW-Authenticate応答ヘッダーを使用して、そのルートを保護するためにDigest認証スキームが使用されているという情報を提供します。一般的なWWW-Authenticateヘッダーは次のようになります。

    WWW-Authenticate: Digest
            realm="Access to the '/' path",
            nonce="e4549c0548886bc2",
            algorithm="MD5"

    Ktorでは、digest認証プロバイダーを設定する際に、レルムとノンス値の生成方法を指定できます。

  3. 通常、クライアントはユーザーが資格情報を入力できるログインダイアログを表示します。その後、クライアントは次のAuthorizationヘッダーを含むリクエストを行います。

    Authorization: Digest username="jetbrains",
            realm="Access to the '/' path",
            nonce="e4549c0548886bc2",
            uri="/",
            algorithm=MD5,
            response="6299988bb4f05c0d8ad44295873858cf"

    response値は次のように生成されます。

    a. HA1 = MD5(username:realm:password)

    この部分はサーバーに保存され、Ktorがユーザーの資格情報を検証するために使用できます。

    b. HA2 = MD5(method:digestURI)

    c. response = MD5(HA1:nonce:HA2)

  4. サーバーはクライアントから送信された資格情報を検証し、要求されたコンテンツで応答します。

Digest認証のインストール

digest認証プロバイダーをインストールするには、installブロック内でdigest関数を呼び出します。

kotlin
import io.ktor.server.application.*
import io.ktor.server.auth.*
// ...
install(Authentication) {
    digest {
        // Digest認証を設定します
    }
}

オプションで、指定されたルートを認証するために使用できるプロバイダー名を指定できます。

Digest認証の設定

Ktorで異なる認証プロバイダーを設定する方法の概要については、認証の設定を参照してください。このセクションでは、digest認証プロバイダーの設定の詳細について説明します。

ステップ1: ダイジェストを含むユーザーテーブルの提供

digest認証プロバイダーは、ダイジェストメッセージのHA1部分を使用してユーザーの資格情報を検証します。したがって、ユーザー名とそれに対応するHA1ハッシュを含むユーザーテーブルを提供できます。以下の例では、getMd5Digest関数を使用してHA1ハッシュを生成しています。

kotlin
fun getMd5Digest(str: String): ByteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray(UTF_8))

val myRealm = "Access to the '/' path"
val userTable: Map<String, ByteArray> = mapOf(
    "jetbrains" to getMd5Digest("jetbrains:$myRealm:foobar"),
    "admin" to getMd5Digest("admin:$myRealm:password")
)

ステップ2: Digestプロバイダーの設定

digest認証プロバイダーは、DigestAuthenticationProvider.Configクラスを介して設定を公開します。以下の例では、次の設定が指定されています。

  • realmプロパティは、WWW-Authenticateヘッダーで渡されるレルムを設定します。
  • digestProvider関数は、指定されたユーザー名のダイジェストのHA1部分を取得します。
  • (オプション) validate関数を使用すると、資格情報をカスタムプリンシパルにマッピングできます。
kotlin
fun Application.main() {
    install(Authentication) {
        digest("auth-digest") {
            realm = myRealm
            digestProvider { userName, realm ->
                userTable[userName]
            }
            validate { credentials ->
                if (credentials.userName.isNotEmpty()) {
                    CustomPrincipal(credentials.userName, credentials.realm)
                } else {
                    null
                }
            }
        }
    }
}

data class CustomPrincipal(val userName: String, val realm: String)

nonceManagerプロパティを使用して、ノンス値の生成方法を指定することもできます。

ステップ3: 特定のリソースを保護する

digestプロバイダーを設定した後、**authenticate**関数を使用してアプリケーション内の特定のリソースを保護できます。認証が成功した場合、call.principal関数を使用してルートハンドラー内で認証されたPrincipalを取得し、認証されたユーザーの名前を取得できます。

kotlin
routing {
    authenticate("auth-digest") {
        get("/") {
            call.respondText("Hello, ${call.principal<CustomPrincipal>()?.userName}!")
        }
    }
}