Skip to content

Commit 1255b8e

Browse files
antspriggsclaudenat-ray
authored
Add Sonatype Maven Central publishing support (#9)
* Address pre-release security audit findings (all Critical + High) Fixes all 4 Critical and 5 High findings, plus 5 of 6 Medium and all 3 Low findings from the pre-release security audit. Critical: - [#1] State validation is now unconditional; missing state throws StateMismatch, closing the CSRF / authorization code injection vector - [#2] Public IDmeAuth constructor now requires Context and defaults to EncryptedCredentialStore; CredentialStore demoted to internal - [#3] JWKSClient cache fields are @volatile and all access is serialised through a Mutex, eliminating the race condition - [#4] policies() sends credentials via HTTP Basic Auth header instead of GET query parameter, keeping the client secret out of server logs High: - [#5] Demo network_security_config.xml removes user-cert trust and sets cleartextTrafficPermitted=false - [#6] iss and aud JWT claims are now mandatory; tokens that omit either throw JWTClaimInvalid instead of silently passing - [#7] JWTValidator validates nbf with 30-second clock skew tolerance and applies the same skew window to exp - [#8] IDmeAuthManager replaces the single CompletableDeferred with a ConcurrentHashMap keyed by state; IDmeAuth passes state as sessionId so callbacks cannot be routed to the wrong flow - [#9] extractJSON is now suspend and calls JWTValidator before decoding, ensuring userinfo JWT signatures are verified before claims are exposed Medium: - [#10] Log.isEnabled flag (default false) gates all SDK log output to prevent credential leakage in release builds - [#11] Redirect URI validation rejects http/https/javascript/file/data schemes in IDmeAuth, AuthorizationRequest, and GroupsRequest - [#12] clearSync() cancels the refresh deferred before nulling state, reducing the window for concurrent-write races - [#13] expiresIn is coerced to [0, 86400] seconds before multiplication, preventing integer-overflow-induced negative expiry timestamps - [#14] AuthViewModel extends AndroidViewModel (provides Context to IDmeAuth); clientSecret is only forwarded in OAUTH mode Low: - [#15] secure-pipeline-ast.yml pinned to immutable commit SHA instead of mutable @master ref - [#17] Demo release build enables minification - [#18] Base64URL.decode() throws IDmeAuthError.InvalidJWT on failure instead of returning null; JWTDecoder call sites cleaned up accordingly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add GitHub Packages Maven publishing workflow - Apply maven-publish plugin to :sdk with release publication (com.idme:idme-auth-sdk) - Configure GitHubPackages repository using GITHUB_TOKEN - Add GROUP and VERSION_NAME to gradle.properties - Add publish.yml workflow triggered on GitHub Release or workflow_dispatch Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Rename artifactId to android-auth-sample-code Aligns Maven coordinates with the repository name: me.id.auth:android-auth-sample-code:<version> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add Sonatype Maven Central publishing support - Add Dokka plugin for Javadoc JAR generation (required by Sonatype) - Add sources JAR task (required by Sonatype) - Apply signing plugin with in-memory PGP key support for CI - Complete POM metadata: url, licenses, developers, and SCM (required by Sonatype) - Wire Dokka + nexus-publish plugin into root buildscript classpath - Configure Sonatype OSSRH staging repository via nexus-publish plugin - Add Sonatype publish step to release workflow using five new secrets: SONATYPE_USERNAME, SONATYPE_PASSWORD, SIGNING_KEY_ID, SIGNING_KEY, SIGNING_PASSWORD Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Nat Ray <nathaniel.ray@id.me>
1 parent d3bbd6a commit 1255b8e

4 files changed

Lines changed: 101 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,18 @@ jobs:
176176
echo "Generated POM content:"
177177
cat ~/.m2/repository/me/id/auth/android-auth-sample-code/$RELEASE_VERSION/android-auth-sample-code-$RELEASE_VERSION.pom
178178
179+
- name: Publish to Maven Central (Sonatype OSSRH)
180+
env:
181+
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
182+
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
183+
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
184+
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
185+
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
186+
run: |
187+
./gradlew :sdk:publishReleasePublicationToSonatypeRepository \
188+
closeAndReleaseSonatypeStagingRepository \
189+
-PreleaseVersion=$RELEASE_VERSION
190+
179191
- name: Create Git tag
180192
run: |
181193
git config user.name "github-actions[bot]"
@@ -208,6 +220,10 @@ jobs:
208220
echo "### Maven Coordinates" >> $GITHUB_STEP_SUMMARY
209221
echo "\`me.id.auth:android-auth-sample-code:$RELEASE_VERSION\`" >> $GITHUB_STEP_SUMMARY
210222
echo "" >> $GITHUB_STEP_SUMMARY
223+
echo "### Published To" >> $GITHUB_STEP_SUMMARY
224+
echo "- GitHub Packages: https://github.com/IDme/android-auth-sample-code/packages" >> $GITHUB_STEP_SUMMARY
225+
echo "- Maven Central: https://central.sonatype.com/artifact/me.id.auth/android-auth-sample-code" >> $GITHUB_STEP_SUMMARY
226+
echo "" >> $GITHUB_STEP_SUMMARY
211227
echo "### Verification" >> $GITHUB_STEP_SUMMARY
212228
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
213229
echo "gh attestation verify android-auth-sample-code-$RELEASE_VERSION.aar --repo IDme/android-auth-sample-code" >> $GITHUB_STEP_SUMMARY
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Secure Pipeline | AST
2+
3+
on:
4+
push:
5+
pull_request:
6+
types:
7+
- opened
8+
- reopened
9+
- synchronize
10+
- ready_for_review
11+
- converted_to_draft
12+
schedule:
13+
- cron: '0 8 * * *' # 3am EST (UTC-5)
14+
15+
jobs:
16+
execute:
17+
uses: IDme/workflow-library/.github/workflows/secure-pipeline-ast.yml@7a259bb101fd4f20d7cd0137c1f99e8d60af0859
18+
secrets: inherit

build.gradle.kts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import io.github.gradlenexus.publishplugin.NexusPublishExtension
2+
13
buildscript {
24
repositories {
35
google()
@@ -8,5 +10,20 @@ buildscript {
810
classpath("com.android.tools.build:gradle:8.2.2")
911
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22")
1012
classpath("org.jetbrains.kotlin:kotlin-serialization:1.9.22")
13+
classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.9.20")
14+
classpath("io.github.gradle-nexus:publish-plugin:2.0.0")
15+
}
16+
}
17+
18+
apply(plugin = "io.github.gradle-nexus.publish-plugin")
19+
20+
configure<NexusPublishExtension> {
21+
repositories {
22+
sonatype {
23+
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
24+
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
25+
username.set(findProperty("sonatypeUsername")?.toString() ?: System.getenv("SONATYPE_USERNAME"))
26+
password.set(findProperty("sonatypePassword")?.toString() ?: System.getenv("SONATYPE_PASSWORD"))
27+
}
1128
}
1229
}

sdk/build.gradle.kts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import com.android.build.gradle.LibraryExtension
22
import org.gradle.api.publish.PublishingExtension
33
import org.gradle.api.publish.maven.MavenPublication
4+
import org.gradle.plugins.signing.SigningExtension
45

56
apply(plugin = "com.android.library")
67
apply(plugin = "kotlin-android")
78
apply(plugin = "kotlinx-serialization")
89
apply(plugin = "maven-publish")
10+
apply(plugin = "signing")
11+
apply(plugin = "org.jetbrains.dokka")
912

1013
version = findProperty("releaseVersion")?.toString() ?: "1.0.0"
1114

@@ -48,6 +51,17 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
4851
}
4952
}
5053

54+
val sourcesJar by tasks.registering(Jar::class) {
55+
archiveClassifier.set("sources")
56+
from("src/main/java", "src/main/kotlin")
57+
}
58+
59+
val javadocJar by tasks.registering(Jar::class) {
60+
archiveClassifier.set("javadoc")
61+
dependsOn(tasks.named("dokkaJavadoc"))
62+
from(tasks.named("dokkaJavadoc").map { it.outputs.files })
63+
}
64+
5165
dependencies {
5266
"implementation"("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
5367
"implementation"("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
@@ -68,11 +82,36 @@ afterEvaluate {
6882
version = project.version.toString()
6983

7084
from(components["release"])
85+
artifact(sourcesJar)
86+
artifact(javadocJar)
7187

7288
pom {
7389
name.set("ID.me Auth Sample Code")
7490
description.set("ID.me Android Auth Sample Code SDK")
91+
url.set("https://github.com/IDme/android-auth-sample-code")
7592
packaging = "aar"
93+
94+
licenses {
95+
license {
96+
name.set("MIT License")
97+
url.set("https://opensource.org/licenses/MIT")
98+
distribution.set("repo")
99+
}
100+
}
101+
102+
developers {
103+
developer {
104+
id.set("idme")
105+
name.set("ID.me")
106+
email.set("engineering@id.me")
107+
}
108+
}
109+
110+
scm {
111+
connection.set("scm:git:git://github.com/IDme/android-auth-sample-code.git")
112+
developerConnection.set("scm:git:ssh://github.com/IDme/android-auth-sample-code.git")
113+
url.set("https://github.com/IDme/android-auth-sample-code")
114+
}
76115
}
77116
}
78117
}
@@ -81,4 +120,15 @@ afterEvaluate {
81120
mavenLocal()
82121
}
83122
}
123+
124+
configure<SigningExtension> {
125+
val signingKeyId = findProperty("signingKeyId")?.toString() ?: System.getenv("SIGNING_KEY_ID")
126+
val signingKey = findProperty("signingKey")?.toString() ?: System.getenv("SIGNING_KEY")
127+
val signingPassword = findProperty("signingPassword")?.toString() ?: System.getenv("SIGNING_PASSWORD")
128+
129+
if (!signingKey.isNullOrBlank() && !signingPassword.isNullOrBlank()) {
130+
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
131+
sign(extensions.getByType<PublishingExtension>().publications["release"])
132+
}
133+
}
84134
}

0 commit comments

Comments
 (0)