Maven Central Repository 公開時の認証をユーザートークンに変更する手順


はじめに

2024年6月に Sonatype における認証システムが変更され、ユーザートークンでの認証が必要になったようです。

従来のユーザ名とパスワードで Publish しようとした場合、以下のような認証エラーとなります。

Execution failed for task ':lib:publishMavenJavaPublicationToMavenCentralRepository'.
> Failed to publish publication 'mavenJava' to repository 'MavenCentral'
   > Could not PUT 'https://oss.sonatype.org/service/local/staging/deploy/maven2/xxx/xxx.jar'. Received status code 401 from server: Content access is protected by token

ユーザートークンへの切り替え手順についてまとめておきます。


ユーザートークンの発行

https://oss.sonatype.org/ にログインして Profile に移動

User Token を選択して Access User Token ボタンを押下

以下のようにユーザートークンが発行される(トークン : トークンパスワード)


ユーザートークンの設定

以下に従った、Gradle プロジェクトを前提とします。

blog1.mammb.com

ユーザホームの ~/.gradle/gradle.properties ユーザートークンを設定します。

signing.keyId=812DXXXX
signing.password=鍵作成時のパスフレーズ
signing.secretKeyRingFile=/Users/XXXXX/.gnupg/secring.gpg

ossrhToken=トークン
ossrhTokenPassword=トークンパスワード

build.gradle.kts を以下のように構成します。

val ossrhToken: String? by project
val ossrhTokenPassword: String? by project

publishing {
    ...
    repositories {
        maven {
            name = "MavenCentral"
            val releasesRepoUrl = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
            val snapshotsRepoUrl = uri("https://oss.sonatype.org/content/repositories/snapshots")
            url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
            credentials {
                username = ossrhToken
                password = ossrhTokenPassword
            }
        }
    }
}


publishing プラグインと signing プラグイン含めた全体像は以下のようになります。

plugins {
    // ...
    `maven-publish`
    signing
}

// ...

group = "Your Group Id"
version = "X.X.X"


val ossrhToken: String? by project
val ossrhTokenPassword: String? by project

java {
    withJavadocJar()
    withSourcesJar()
}

publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            artifactId = "プロジェクト名"
            from(components["java"])
            versionMapping {
                usage("java-api") {
                    fromResolutionOf("runtimeClasspath")
                }
                usage("java-runtime") {
                    fromResolutionResult()
                }
            }
            pom {
                name.set("プロジェクト名")
                description.set("プロジェクトの説明")
                url.set("プロジェクトURL(GithubのURL)")
                licenses {
                    license {
                        name.set("The Apache License, Version 2.0")
                        url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
                    }
                }
                developers {
                    developer {
                        id.set("Your ID")
                        name.set("Your name")
                        email.set("Your email address")
                    }
                }
                scm {
                    connection.set("git@github.com:XXXXX.git")
                    developerConnection.set("git@github.com:XXXXX.git")
                    url.set("https://github.com/XXXXX")
                }
            }
        }
    }
    repositories {
        maven {
            val releasesRepoUrl = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
            val snapshotsRepoUrl = uri("https://oss.sonatype.org/content/repositories/snapshots")
            url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
            credentials {
                username = ossrhToken
                password = ossrhTokenPassword
            }
        }
    }
}

signing {
    sign(publishing.publications["mavenJava"])
}


publish 実行

以上で、ユーザートークンの設定は完了です。

以下のようにして発行できるようになります。

./gradlew publish

BUILD SUCCESSFUL in 36s
9 actionable tasks: 3 executed, 6 up-to-date