diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 21a90a3..0dff7a6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,9 +1,15 @@ version: 2 +registries: + maven-central: + type: maven-repository + url: "https://repo.maven.apache.org/maven2/" updates: - package-ecosystem: "gradle" directory: "/" schedule: interval: "daily" + registries: + - maven-central - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5fcd6ee..ffaa149 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,11 +3,13 @@ on: [push, pull_request, workflow_dispatch] jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} steps: - name: Checkout Repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Validate Gradle Wrapper uses: gradle/actions/wrapper-validation@v4 - name: Set up JDK 21 diff --git a/.github/workflows/update-gradle-wrapper.yml b/.github/workflows/update-gradle-wrapper.yml deleted file mode 100644 index 0da284f..0000000 --- a/.github/workflows/update-gradle-wrapper.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: update-gradle-wrapper -on: - workflow_dispatch: - schedule: - - cron: "0 0 * * 0" - -jobs: - update-gradle-wrapper: - runs-on: ubuntu-latest - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - name: Update Gradle Wrapper - uses: gradle-update/update-gradle-wrapper-action@v1 diff --git a/.gitignore b/.gitignore index 9d0620d..26560b9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,7 @@ hs_err_pid* /.idea/* !/.idea/copyright/ /.gradle/ -/build/ -/out/ +/buildSrc/.gradle/ +build/ +out/ +/run/ diff --git a/build.gradle b/build.gradle index f5537e0..45f70a7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,97 +1,25 @@ plugins { id "java-library" - id "maven-publish" - id "signing" - id "net.raphimc.class-token-replacer" version "1.1.3" + id "base.base-conventions" + id "base.fill-build-constants" + id "minecraftauth.publishing-conventions" + id "net.raphimc.class-token-replacer" version "1.1.6" } -base { - java.toolchain.languageVersion = JavaLanguageVersion.of(8) - compileJava.options.encoding = compileTestJava.options.encoding = javadoc.options.encoding = "UTF-8" - - group = project.maven_group ?: rootProject.maven_group - archivesName = project.maven_name ?: rootProject.maven_name - version = project.maven_version ?: rootProject.maven_version -} - -repositories { - mavenCentral() +sourceSets { + javaFxStub // Java 11+ does not include JavaFX anymore, so the JavaFX stubs are needed for the compiler } dependencies { - compileOnly(annotationProcessor("org.projectlombok:lombok:1.18.34")) - compileOnly "org.jetbrains:annotations:24.1.0" + compileOnly(annotationProcessor("org.projectlombok:lombok:1.18.38")) + compileOnly "org.jetbrains:annotations:26.0.2" + compileOnly sourceSets.javaFxStub.output - api "com.google.code.gson:gson:2.11.0" + api "net.lenni0451.commons:httpclient:1.7.1" + api "com.google.code.gson:gson:2.13.1" api "io.jsonwebtoken:jjwt-impl:0.12.6" api("io.jsonwebtoken:jjwt-gson:0.12.6") { exclude group: "com.google.code.gson", module: "gson" } -} - -sourceSets { - main { - classTokenReplacer { - property("\${version}", project.version) - property("\${impl_version}", "git-${project.name}-${project.version}:${project.latestCommitHash()}") - } - } -} - -java { - withSourcesJar() - withJavadocJar() -} - -jar { - from("LICENSE") { - rename { "${it}_${project.name ?: rootProject.name}" } - } -} - -artifacts { - archives javadocJar, sourcesJar -} - -publishing { - publications { - maven(MavenPublication) { - groupId = project.maven_group - artifactId = project.maven_name - version = project.maven_version - - from components.java - - pom { - name = "MinecraftAuth" - description = "Simple and easy to use Minecraft microsoft authentication library (Java and Bedrock)" - url = "https://github.com/RaphiMC/MinecraftAuth" - licenses { - license { - name = "LGPL-3.0 License" - url = "https://github.com/RaphiMC/MinecraftAuth/blob/main/LICENSE" - } - } - developers { - developer { - id = "RK_01" - } - } - scm { - connection = "scm:git:git://github.com/RaphiMC/MinecraftAuth.git" - developerConnection = "scm:git:ssh://github.com/RaphiMC/MinecraftAuth.git" - url = "https://github.com/RaphiMC/MinecraftAuth.git" - } - } - } - } -} - -String latestCommitHash() { - def stdout = new ByteArrayOutputStream() - exec { - commandLine "git", "rev-parse", "--short", "HEAD" - standardOutput = stdout - } - return stdout.toString().trim() + api "org.slf4j:slf4j-api:2.0.17" } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 0000000..e1c034f --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,7 @@ +plugins { + id "groovy-gradle-plugin" +} + +repositories { + gradlePluginPortal() +} diff --git a/buildSrc/src/main/groovy/base.base-conventions.gradle b/buildSrc/src/main/groovy/base.base-conventions.gradle new file mode 100644 index 0000000..7b0fc7b --- /dev/null +++ b/buildSrc/src/main/groovy/base.base-conventions.gradle @@ -0,0 +1,34 @@ +base { + java.toolchain.languageVersion = JavaLanguageVersion.of(project.java_version) + + group = project.maven_group + archivesName = project.name + version = project.maven_version +} + +repositories { + mavenCentral() +} + +jar { + if (layout.projectDirectory.file("LICENSE").asFile.exists()) { + def projectName = project.name + from(layout.projectDirectory.file("LICENSE")) { + rename { "${it}_${projectName}" } + } + } else if (rootProject.layout.projectDirectory.file("LICENSE").asFile.exists()) { + def projectName = rootProject.name + from(rootProject.layout.projectDirectory.file("LICENSE")) { + rename { "${it}_${projectName}" } + } + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" +} + +tasks.withType(Javadoc).configureEach { + it.options.encoding = "UTF-8" + it.options.addStringOption("Xdoclint:none", "-quiet") +} diff --git a/buildSrc/src/main/groovy/base.fill-build-constants.gradle b/buildSrc/src/main/groovy/base.fill-build-constants.gradle new file mode 100644 index 0000000..60e6c75 --- /dev/null +++ b/buildSrc/src/main/groovy/base.fill-build-constants.gradle @@ -0,0 +1,16 @@ +plugins { + id "net.raphimc.class-token-replacer" +} + +sourceSets.configureEach { + it.classTokenReplacer { + property("\${version}", project.version) + property("\${commit_hash}", latestCommitHash().get()) + } +} + +Provider latestCommitHash() { + return providers.exec { + commandLine = ["git", "rev-parse", "--short", "HEAD"] + }.standardOutput.getAsText().map(String::trim) +} diff --git a/buildSrc/src/main/groovy/base.lenni0451-maven-publishing.gradle b/buildSrc/src/main/groovy/base.lenni0451-maven-publishing.gradle new file mode 100644 index 0000000..7dcd899 --- /dev/null +++ b/buildSrc/src/main/groovy/base.lenni0451-maven-publishing.gradle @@ -0,0 +1,13 @@ +publishing { + repositories { + maven { + name = "reposilite" + url = "https://maven.lenni0451.net/" + (project.maven_version.endsWith("SNAPSHOT") ? "snapshots" : "releases") + + credentials(PasswordCredentials) + authentication { + basic(BasicAuthentication) + } + } + } +} diff --git a/buildSrc/src/main/groovy/base.maven-central-publishing.gradle b/buildSrc/src/main/groovy/base.maven-central-publishing.gradle new file mode 100644 index 0000000..f92d87e --- /dev/null +++ b/buildSrc/src/main/groovy/base.maven-central-publishing.gradle @@ -0,0 +1,13 @@ +publishing { + repositories { + maven { + name = "ossrh" + url = "https://s01.oss.sonatype.org/" + (project.maven_version.endsWith("SNAPSHOT") ? "content/repositories/snapshots/" : "service/local/staging/deploy/maven2/") + + credentials(PasswordCredentials) + authentication { + basic(BasicAuthentication) + } + } + } +} diff --git a/buildSrc/src/main/groovy/base.publishing-conventions.gradle b/buildSrc/src/main/groovy/base.publishing-conventions.gradle new file mode 100644 index 0000000..4c87128 --- /dev/null +++ b/buildSrc/src/main/groovy/base.publishing-conventions.gradle @@ -0,0 +1,30 @@ +plugins { + id "maven-publish" + id "signing" +} + +java { + withSourcesJar() + withJavadocJar() +} + +publishing { + publications { + mavenJava(MavenPublication) { + from(components.java) + + groupId = project.maven_group + artifactId = project.maven_name + version = project.maven_version + } + } +} + +signing { + setRequired(false) + sign(publishing.publications.mavenJava) +} + +tasks.withType(PublishToMavenRepository).configureEach { + it.dependsOn(tasks.withType(Sign)) +} diff --git a/buildSrc/src/main/groovy/minecraftauth.publishing-conventions.gradle b/buildSrc/src/main/groovy/minecraftauth.publishing-conventions.gradle new file mode 100644 index 0000000..c1f309e --- /dev/null +++ b/buildSrc/src/main/groovy/minecraftauth.publishing-conventions.gradle @@ -0,0 +1,33 @@ +plugins { + id "base.publishing-conventions" + id "base.maven-central-publishing" + id "base.lenni0451-maven-publishing" +} + +publishing { + publications { + mavenJava { + pom { + name = "MinecraftAuthHeadless" + description = "Simple and easy to use Minecraft microsoft authentication library (Java and Bedrock)" + url = "https://github.com/mcio-dev/MinecraftAuthHeadless" + licenses { + license { + name = "LGPL-3.0 License" + url = "https://github.com/mcio-dev/MinecraftAuthHeadless/blob/main/LICENSE" + } + } + developers { + developer { + id = "RK_01" + } + } + scm { + connection = "scm:git:git://github.com/mcio-dev/MinecraftAuthHeadless.git" + developerConnection = "scm:git:ssh://github.com/mcio-dev/MinecraftAuthHeadless.git" + url = "https://github.com/mcio-dev/MinecraftAuthHeadless.git" + } + } + } + } +} diff --git a/gradle.properties b/gradle.properties index 6b536bc..69dc35a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,8 @@ org.gradle.daemon=true org.gradle.parallel=true -org.gradle.configureondemand=true +org.gradle.configuration-cache=true +java_version=8 maven_group=net.raphimc maven_name=MinecraftAuthHeadless -maven_version=4.1.1-SNAPSHOT +maven_version=4.1.2-SNAPSHOT diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e644113..1b33c55 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09523c0..1af9e09 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf1..23d15a9 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -112,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -203,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -211,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 25da30d..db3a6ac 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -68,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle index 0fe37c2..8aa5653 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,7 +6,7 @@ pluginManagement { } plugins { - id "org.gradle.toolchains.foojay-resolver-convention" version "0.8.0" + id "org.gradle.toolchains.foojay-resolver-convention" version "1.0.0" } rootProject.name = "MinecraftAuthHeadless" diff --git a/src/main/java/net/raphimc/minecraftauth/MinecraftAuth.java b/src/main/java/net/raphimc/minecraftauth/MinecraftAuth.java index 2e08f5a..5061e70 100644 --- a/src/main/java/net/raphimc/minecraftauth/MinecraftAuth.java +++ b/src/main/java/net/raphimc/minecraftauth/MinecraftAuth.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,7 @@ import net.lenni0451.commons.httpclient.HttpClient; import net.lenni0451.commons.httpclient.RetryHandler; import net.lenni0451.commons.httpclient.constants.ContentTypes; -import net.lenni0451.commons.httpclient.constants.Headers; +import net.lenni0451.commons.httpclient.constants.HttpHeaders; import net.raphimc.minecraftauth.step.AbstractStep; import net.raphimc.minecraftauth.step.BiMergeStep; import net.raphimc.minecraftauth.step.bedrock.StepMCChain; @@ -48,7 +48,7 @@ public class MinecraftAuth { public static final String VERSION = "${version}"; - public static final String IMPL_VERSION = "${impl_version}"; + public static final String IMPL_VERSION = "${version}+${commit_hash}"; public static ILogger LOGGER = new LazyLogger(JavaConsoleLogger::new); public static String USER_AGENT = "MinecraftAuth/" + VERSION; @@ -128,9 +128,9 @@ public static HttpClient createHttpClient(int timeout) { .setCookieManager(null) .setFollowRedirects(false) .setRetryHandler(new RetryHandler(0, 50)) - .setHeader(Headers.ACCEPT, ContentTypes.APPLICATION_JSON.toString()) - .setHeader(Headers.ACCEPT_LANGUAGE, "en-US,en") - .setHeader(Headers.USER_AGENT, USER_AGENT); + .setHeader(HttpHeaders.ACCEPT, ContentTypes.APPLICATION_JSON.toString()) + .setHeader(HttpHeaders.ACCEPT_LANGUAGE, "en-US,en") + .setHeader(HttpHeaders.USER_AGENT, USER_AGENT); } public static class MsaTokenBuilder { diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/JsonHttpResponseHandler.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/JsonHttpResponseHandler.java index 5732448..b3e7415 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/JsonHttpResponseHandler.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/JsonHttpResponseHandler.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftEduServicesResponseHandler.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftEduServicesResponseHandler.java index 0db5adb..918eaec 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftEduServicesResponseHandler.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftEduServicesResponseHandler.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftResponseHandler.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftResponseHandler.java index 5345f4a..a4a642f 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftResponseHandler.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/MinecraftResponseHandler.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/MsaResponseHandler.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/MsaResponseHandler.java index 790a099..1e1185d 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/MsaResponseHandler.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/MsaResponseHandler.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/PlayFabResponseHandler.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/PlayFabResponseHandler.java index 8098742..d514c6e 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/PlayFabResponseHandler.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/PlayFabResponseHandler.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/RealmsResponseHandler.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/RealmsResponseHandler.java index f53dac4..0f9b58b 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/RealmsResponseHandler.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/RealmsResponseHandler.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/XblResponseHandler.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/XblResponseHandler.java index e187851..c9ff930 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/XblResponseHandler.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/XblResponseHandler.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/ApiHttpRequestException.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/ApiHttpRequestException.java index 4079927..bf92a60 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/ApiHttpRequestException.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/ApiHttpRequestException.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,13 +17,21 @@ */ package net.raphimc.minecraftauth.responsehandler.exception; +import lombok.Getter; import net.lenni0451.commons.httpclient.HttpResponse; import net.lenni0451.commons.httpclient.exceptions.HttpRequestException; +@Getter public class ApiHttpRequestException extends HttpRequestException { + private final String error; + private final String errorMessage; + public ApiHttpRequestException(final HttpResponse response, final String error, final String errorMessage) { super(response, "status: " + response.getStatusCode() + " " + response.getStatusMessage() + ", error: " + error + ", error message: " + errorMessage); + + this.error = error; + this.errorMessage = errorMessage; } } diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/InformativeHttpRequestException.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/InformativeHttpRequestException.java index b63bcfc..c69cdeb 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/InformativeHttpRequestException.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/InformativeHttpRequestException.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MinecraftRequestException.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MinecraftRequestException.java index ca11d2c..a98040d 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MinecraftRequestException.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MinecraftRequestException.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,18 +17,12 @@ */ package net.raphimc.minecraftauth.responsehandler.exception; -import lombok.Getter; import net.lenni0451.commons.httpclient.HttpResponse; -@Getter public class MinecraftRequestException extends ApiHttpRequestException { - private final String error; - public MinecraftRequestException(final HttpResponse response, final String error, final String errorMessage) { super(response, error, errorMessage); - - this.error = error; } } diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MsaRequestException.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MsaRequestException.java index 3645e8f..a81cf54 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MsaRequestException.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/MsaRequestException.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,18 +17,12 @@ */ package net.raphimc.minecraftauth.responsehandler.exception; -import lombok.Getter; import net.lenni0451.commons.httpclient.HttpResponse; -@Getter public class MsaRequestException extends ApiHttpRequestException { - private final String error; - public MsaRequestException(final HttpResponse response, final String error, final String errorMessage) { super(response, error, errorMessage); - - this.error = error; } } diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/PlayFabRequestException.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/PlayFabRequestException.java index 39d707c..b3905c2 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/PlayFabRequestException.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/PlayFabRequestException.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,18 +17,12 @@ */ package net.raphimc.minecraftauth.responsehandler.exception; -import lombok.Getter; import net.lenni0451.commons.httpclient.HttpResponse; -@Getter public class PlayFabRequestException extends ApiHttpRequestException { - private final String error; - public PlayFabRequestException(final HttpResponse response, final String error, final String errorMessage) { super(response, error, errorMessage); - - this.error = error; } } diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/RealmsRequestException.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/RealmsRequestException.java index afea3b9..6fcd470 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/RealmsRequestException.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/RealmsRequestException.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/XblRequestException.java b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/XblRequestException.java index b15ffef..3795d94 100644 --- a/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/XblRequestException.java +++ b/src/main/java/net/raphimc/minecraftauth/responsehandler/exception/XblRequestException.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/service/realms/AbstractRealmsService.java b/src/main/java/net/raphimc/minecraftauth/service/realms/AbstractRealmsService.java index 26b95a5..80a90c4 100644 --- a/src/main/java/net/raphimc/minecraftauth/service/realms/AbstractRealmsService.java +++ b/src/main/java/net/raphimc/minecraftauth/service/realms/AbstractRealmsService.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ import lombok.SneakyThrows; import net.lenni0451.commons.httpclient.HttpClient; import net.lenni0451.commons.httpclient.constants.ContentTypes; -import net.lenni0451.commons.httpclient.constants.Headers; +import net.lenni0451.commons.httpclient.constants.HttpHeaders; import net.lenni0451.commons.httpclient.handler.ThrowingResponseHandler; import net.lenni0451.commons.httpclient.requests.HttpRequest; import net.lenni0451.commons.httpclient.requests.impl.GetRequest; @@ -57,7 +57,7 @@ public CompletableFuture isAvailable() { public Boolean get() { final GetRequest getRequest = new GetRequest(CLIENT_COMPATIBLE_URL.replace("$HOST", AbstractRealmsService.this.host)); getRequest.setCookieManager(AbstractRealmsService.this.cookieManager); - getRequest.setHeader(Headers.ACCEPT, ContentTypes.TEXT_PLAIN.getMimeType()); + getRequest.setHeader(HttpHeaders.ACCEPT, ContentTypes.TEXT_PLAIN.getMimeType()); AbstractRealmsService.this.addRequestHeaders(getRequest); final String response = AbstractRealmsService.this.httpClient.execute(getRequest, new ThrowingResponseHandler()).getContentAsString(); return response.equals("COMPATIBLE"); diff --git a/src/main/java/net/raphimc/minecraftauth/service/realms/BedrockRealmsService.java b/src/main/java/net/raphimc/minecraftauth/service/realms/BedrockRealmsService.java index ba3f039..6b5dfa9 100644 --- a/src/main/java/net/raphimc/minecraftauth/service/realms/BedrockRealmsService.java +++ b/src/main/java/net/raphimc/minecraftauth/service/realms/BedrockRealmsService.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,7 @@ import com.google.gson.JsonObject; import lombok.SneakyThrows; import net.lenni0451.commons.httpclient.HttpClient; -import net.lenni0451.commons.httpclient.constants.Headers; +import net.lenni0451.commons.httpclient.constants.HttpHeaders; import net.lenni0451.commons.httpclient.requests.HttpRequest; import net.lenni0451.commons.httpclient.requests.impl.DeleteRequest; import net.lenni0451.commons.httpclient.requests.impl.GetRequest; @@ -91,7 +91,7 @@ public void run() { @Override protected void addRequestHeaders(final HttpRequest httpRequest) { - httpRequest.setHeader(Headers.AUTHORIZATION, "XBL3.0 x=" + this.realmsXsts.getServiceToken()); + httpRequest.setHeader(HttpHeaders.AUTHORIZATION, "XBL3.0 x=" + this.realmsXsts.getServiceToken()); httpRequest.setHeader("Client-Version", this.clientVersion); } diff --git a/src/main/java/net/raphimc/minecraftauth/service/realms/JavaRealmsService.java b/src/main/java/net/raphimc/minecraftauth/service/realms/JavaRealmsService.java index cff54cf..10c0755 100644 --- a/src/main/java/net/raphimc/minecraftauth/service/realms/JavaRealmsService.java +++ b/src/main/java/net/raphimc/minecraftauth/service/realms/JavaRealmsService.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/service/realms/model/RealmsWorld.java b/src/main/java/net/raphimc/minecraftauth/service/realms/model/RealmsWorld.java index f980dea..2ad4551 100644 --- a/src/main/java/net/raphimc/minecraftauth/service/realms/model/RealmsWorld.java +++ b/src/main/java/net/raphimc/minecraftauth/service/realms/model/RealmsWorld.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/AbstractStep.java b/src/main/java/net/raphimc/minecraftauth/step/AbstractStep.java index 552464c..e6b799c 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/AbstractStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/AbstractStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -86,21 +86,21 @@ public abstract static class StepResult

> { protected abstract P prevResult(); /** - * Checks if this result is expired.
+ * Checks if this or any previous result is expired.
* Results that have no expire time returned by their API are never considered expired.
* If you want to minimize the amount of HTTP requests, you should only call {@link AbstractStep#refresh} if this method returns true.
* For certain use cases, like joining a Minecraft server, you want to make sure that the data is up-to-date, even if it is not expired yet. See {@link StepResult#isExpiredOrOutdated}. * - * @return true if this result is expired + * @return true if this or any previous result is expired */ public abstract boolean isExpired(); /** - * Checks if this result is expired or potentially outdated.
+ * Checks if this or any previous result is expired or potentially outdated.
* Results that have no expire time returned by their API are always considered outdated.
* If you want the data in the result to be up-to-date, you should call {@link AbstractStep#refresh} if this method returns true.
* - * @return true if this result is potentially outdated or expired + * @return true if this or any previous result is potentially outdated or expired */ public boolean isExpiredOrOutdated() { return this.isExpired(); diff --git a/src/main/java/net/raphimc/minecraftauth/step/BiMergeStep.java b/src/main/java/net/raphimc/minecraftauth/step/BiMergeStep.java index 177c05f..69eac8f 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/BiMergeStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/BiMergeStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/SameInputBiMergeStep.java b/src/main/java/net/raphimc/minecraftauth/step/SameInputBiMergeStep.java index 35f1892..20a6e6a 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/SameInputBiMergeStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/SameInputBiMergeStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/SameInputStep.java b/src/main/java/net/raphimc/minecraftauth/step/SameInputStep.java index 69816eb..2800960 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/SameInputStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/SameInputStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/SameInputTriMergeStep.java b/src/main/java/net/raphimc/minecraftauth/step/SameInputTriMergeStep.java index cf6fd3b..ad63347 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/SameInputTriMergeStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/SameInputTriMergeStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/TriMergeStep.java b/src/main/java/net/raphimc/minecraftauth/step/TriMergeStep.java index aa74beb..d081077 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/TriMergeStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/TriMergeStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepMCChain.java b/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepMCChain.java index 3839079..cec9ebf 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepMCChain.java +++ b/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepMCChain.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,20 +19,18 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; import lombok.*; import lombok.experimental.NonFinal; import lombok.experimental.PackagePrivate; import net.lenni0451.commons.httpclient.HttpClient; -import net.lenni0451.commons.httpclient.constants.Headers; +import net.lenni0451.commons.httpclient.constants.HttpHeaders; import net.lenni0451.commons.httpclient.requests.impl.PostRequest; import net.raphimc.minecraftauth.responsehandler.MinecraftResponseHandler; import net.raphimc.minecraftauth.step.AbstractStep; import net.raphimc.minecraftauth.step.xbl.StepXblXstsToken; import net.raphimc.minecraftauth.util.CryptUtil; import net.raphimc.minecraftauth.util.JsonContent; +import net.raphimc.minecraftauth.util.JwtUtil; import net.raphimc.minecraftauth.util.logging.ILogger; import org.jetbrains.annotations.ApiStatus; @@ -45,8 +43,6 @@ import java.util.Map; import java.util.UUID; -import static net.raphimc.minecraftauth.util.TimeUtil.MAX_JWT_CLOCK_SKEW; - public class StepMCChain extends AbstractStep, StepMCChain.MCChain> { public static final String MINECRAFT_LOGIN_URL = "https://multiplayer.minecraft.net/authentication"; @@ -73,18 +69,18 @@ protected MCChain execute(final ILogger logger, final HttpClient httpClient, fin final PostRequest postRequest = new PostRequest(MINECRAFT_LOGIN_URL); postRequest.setContent(new JsonContent(postData)); - postRequest.setHeader(Headers.AUTHORIZATION, "XBL3.0 x=" + xblXsts.getServiceToken()); + postRequest.setHeader(HttpHeaders.AUTHORIZATION, "XBL3.0 x=" + xblXsts.getServiceToken()); final JsonObject obj = httpClient.execute(postRequest, new MinecraftResponseHandler()); final JsonArray chain = obj.getAsJsonArray("chain"); if (chain.size() != 2) { throw new IllegalStateException("Invalid chain size"); } - final Jws mojangJwt = Jwts.parser().clockSkewSeconds(MAX_JWT_CLOCK_SKEW).verifyWith(MOJANG_PUBLIC_KEY).build().parseSignedClaims(chain.get(0).getAsString()); - final ECPublicKey mojangJwtPublicKey = CryptUtil.publicKeyEcFromBase64(mojangJwt.getPayload().get("identityPublicKey", String.class)); - final Jws identityJwt = Jwts.parser().clockSkewSeconds(MAX_JWT_CLOCK_SKEW).verifyWith(mojangJwtPublicKey).build().parseSignedClaims(chain.get(1).getAsString()); + final JwtUtil.Jwt mojangJwt = JwtUtil.parseSignedJwt(chain.get(0).getAsString(), MOJANG_PUBLIC_KEY); + final ECPublicKey mojangJwtPublicKey = CryptUtil.publicKeyEcFromBase64(mojangJwt.getClaim("identityPublicKey", String.class)); + final JwtUtil.Jwt identityJwt = JwtUtil.parseSignedJwt(chain.get(1).getAsString(), mojangJwtPublicKey); - final Map extraData = identityJwt.getPayload().get("extraData", Map.class); + final Map extraData = identityJwt.getClaim("extraData", Map.class); final String xuid = (String) extraData.get("XUID"); final UUID id = UUID.fromString((String) extraData.get("identity")); final String displayName = (String) extraData.get("displayName"); @@ -175,6 +171,10 @@ protected StepXblXstsToken.XblXsts prevResult() { @Override public boolean isExpired() { + if (this.prevResult().isExpired()) { + return true; + } + // Cache the result for 1 second because it's expensive to check if (System.currentTimeMillis() - this.lastExpireCheckTimeMs < 1000) { return this.lastExpireCheckResult; @@ -182,9 +182,9 @@ public boolean isExpired() { this.lastExpireCheckTimeMs = System.currentTimeMillis(); try { - final Jws mojangJwt = Jwts.parser().clockSkewSeconds(MAX_JWT_CLOCK_SKEW).verifyWith(MOJANG_PUBLIC_KEY).build().parseSignedClaims(this.mojangJwt); - final ECPublicKey mojangJwtPublicKey = CryptUtil.publicKeyEcFromBase64(mojangJwt.getPayload().get("identityPublicKey", String.class)); - Jwts.parser().clockSkewSeconds(MAX_JWT_CLOCK_SKEW).verifyWith(mojangJwtPublicKey).build().parseSignedClaims(this.identityJwt); + final JwtUtil.Jwt mojangJwt = JwtUtil.parseSignedJwt(this.mojangJwt, MOJANG_PUBLIC_KEY); + final ECPublicKey mojangJwtPublicKey = CryptUtil.publicKeyEcFromBase64(mojangJwt.getClaim("identityPublicKey", String.class)); + JwtUtil.parseSignedJwt(this.identityJwt, mojangJwtPublicKey); this.lastExpireCheckResult = false; } catch (Throwable e) { // Any error -> The jwts are expired or invalid this.lastExpireCheckResult = true; diff --git a/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepPlayFabToken.java b/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepPlayFabToken.java index b229254..07f14a8 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepPlayFabToken.java +++ b/src/main/java/net/raphimc/minecraftauth/step/bedrock/StepPlayFabToken.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -129,7 +129,7 @@ protected StepXblXstsToken.XblXsts prevResult() { @Override public boolean isExpired() { - return this.expireTimeMs <= System.currentTimeMillis(); + return this.expireTimeMs <= System.currentTimeMillis() || this.prevResult().isExpired(); } } diff --git a/src/main/java/net/raphimc/minecraftauth/step/bedrock/session/StepFullBedrockSession.java b/src/main/java/net/raphimc/minecraftauth/step/bedrock/session/StepFullBedrockSession.java index 5518699..56e3cef 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/bedrock/session/StepFullBedrockSession.java +++ b/src/main/java/net/raphimc/minecraftauth/step/bedrock/session/StepFullBedrockSession.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/edu/StepEduJWT.java b/src/main/java/net/raphimc/minecraftauth/step/edu/StepEduJWT.java index 54f9d41..3d6fe34 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/edu/StepEduJWT.java +++ b/src/main/java/net/raphimc/minecraftauth/step/edu/StepEduJWT.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/java/StepMCProfile.java b/src/main/java/net/raphimc/minecraftauth/step/java/StepMCProfile.java index 8665c46..498c3a0 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/java/StepMCProfile.java +++ b/src/main/java/net/raphimc/minecraftauth/step/java/StepMCProfile.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,13 +21,16 @@ import lombok.EqualsAndHashCode; import lombok.Value; import net.lenni0451.commons.httpclient.HttpClient; -import net.lenni0451.commons.httpclient.constants.Headers; +import net.lenni0451.commons.httpclient.HttpResponse; +import net.lenni0451.commons.httpclient.constants.HttpHeaders; import net.lenni0451.commons.httpclient.requests.impl.GetRequest; import net.raphimc.minecraftauth.responsehandler.MinecraftResponseHandler; +import net.raphimc.minecraftauth.responsehandler.exception.MinecraftRequestException; import net.raphimc.minecraftauth.step.AbstractStep; import net.raphimc.minecraftauth.util.UuidUtil; import net.raphimc.minecraftauth.util.logging.ILogger; +import java.io.IOException; import java.util.UUID; public class StepMCProfile extends AbstractStep { @@ -43,8 +46,21 @@ protected MCProfile execute(final ILogger logger, final HttpClient httpClient, f logger.info(this, "Getting profile..."); final GetRequest getRequest = new GetRequest(MINECRAFT_PROFILE_URL); - getRequest.setHeader(Headers.AUTHORIZATION, mcToken.getTokenType() + " " + mcToken.getAccessToken()); - final JsonObject obj = httpClient.execute(getRequest, new MinecraftResponseHandler()); + getRequest.setHeader(HttpHeaders.AUTHORIZATION, mcToken.getTokenType() + " " + mcToken.getAccessToken()); + final JsonObject obj = httpClient.execute(getRequest, new MinecraftResponseHandler() { + @Override + protected void handleJsonError(final HttpResponse response, final JsonObject obj) throws IOException { + try { + super.handleJsonError(response, obj); + } catch (MinecraftRequestException e) { + if (e.getResponse().getStatusCode() == 404) { + throw new ProfileNotFoundException(e); + } else { + throw e; + } + } + } + }); final MCProfile mcProfile = new MCProfile( UuidUtil.fromLenientString(obj.get("id").getAsString()), @@ -103,4 +119,12 @@ public boolean isExpiredOrOutdated() { } + public static class ProfileNotFoundException extends MinecraftRequestException { + + public ProfileNotFoundException(final MinecraftRequestException exception) { + super(exception.getResponse(), exception.getError(), "Your account doesn't have a Minecraft profile. Please login to Minecraft and set up your profile."); + } + + } + } diff --git a/src/main/java/net/raphimc/minecraftauth/step/java/StepMCToken.java b/src/main/java/net/raphimc/minecraftauth/step/java/StepMCToken.java index 76cdac7..9d6aa75 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/java/StepMCToken.java +++ b/src/main/java/net/raphimc/minecraftauth/step/java/StepMCToken.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -98,7 +98,7 @@ protected StepXblXstsToken.XblXsts prevResult() { @Override public boolean isExpired() { - return this.expireTimeMs <= System.currentTimeMillis(); + return this.expireTimeMs <= System.currentTimeMillis() || this.prevResult().isExpired(); } } diff --git a/src/main/java/net/raphimc/minecraftauth/step/java/StepPlayerCertificates.java b/src/main/java/net/raphimc/minecraftauth/step/java/StepPlayerCertificates.java index 0e21c85..e4e4ef8 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/java/StepPlayerCertificates.java +++ b/src/main/java/net/raphimc/minecraftauth/step/java/StepPlayerCertificates.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ import lombok.Value; import net.lenni0451.commons.httpclient.HttpClient; import net.lenni0451.commons.httpclient.constants.ContentTypes; -import net.lenni0451.commons.httpclient.constants.Headers; +import net.lenni0451.commons.httpclient.constants.HttpHeaders; import net.lenni0451.commons.httpclient.content.impl.StringContent; import net.lenni0451.commons.httpclient.requests.impl.PostRequest; import net.raphimc.minecraftauth.responsehandler.MinecraftResponseHandler; @@ -52,7 +52,7 @@ protected PlayerCertificates execute(final ILogger logger, final HttpClient http final PostRequest postRequest = new PostRequest(PLAYER_CERTIFICATES_URL); postRequest.setContent(new StringContent(ContentTypes.APPLICATION_JSON, "")); - postRequest.setHeader(Headers.AUTHORIZATION, mcToken.getTokenType() + " " + mcToken.getAccessToken()); + postRequest.setHeader(HttpHeaders.AUTHORIZATION, mcToken.getTokenType() + " " + mcToken.getAccessToken()); final JsonObject obj = httpClient.execute(postRequest, new MinecraftResponseHandler()); final JsonObject keyPair = obj.getAsJsonObject("keyPair"); @@ -123,7 +123,7 @@ protected StepMCToken.MCToken prevResult() { @Override public boolean isExpired() { - return this.expireTimeMs <= System.currentTimeMillis(); + return this.expireTimeMs <= System.currentTimeMillis() || this.prevResult().isExpired(); } } diff --git a/src/main/java/net/raphimc/minecraftauth/step/java/session/StepFullJavaSession.java b/src/main/java/net/raphimc/minecraftauth/step/java/session/StepFullJavaSession.java index 16b6ca7..dd6e385 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/java/session/StepFullJavaSession.java +++ b/src/main/java/net/raphimc/minecraftauth/step/java/session/StepFullJavaSession.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/InitialPreparationStep.java b/src/main/java/net/raphimc/minecraftauth/step/msa/InitialPreparationStep.java index ea52131..74dcb08 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/InitialPreparationStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/InitialPreparationStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/MsaCodeStep.java b/src/main/java/net/raphimc/minecraftauth/step/msa/MsaCodeStep.java index 8bfcacf..c933ee5 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/MsaCodeStep.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/MsaCodeStep.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -72,6 +72,15 @@ public static class MsaCode extends AbstractStep.FirstStepResult { @EqualsAndHashCode.Exclude StepMsaToken.MsaToken msaToken; // Used in device code flow + @ApiStatus.Internal + @Getter(AccessLevel.NONE) + @Setter(AccessLevel.NONE) + @PackagePrivate + @NonFinal + @ToString.Exclude + @EqualsAndHashCode.Exclude + String customRedirectUri; // Used in local webserver flow + @Override public boolean isExpired() { return true; // MsaCode can only be used one time and can't be refreshed diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/StepCredentialsMsaCode.java b/src/main/java/net/raphimc/minecraftauth/step/msa/StepCredentialsMsaCode.java index 4691498..9067753 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/StepCredentialsMsaCode.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/StepCredentialsMsaCode.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,11 +22,13 @@ import lombok.EqualsAndHashCode; import lombok.Value; import net.lenni0451.commons.httpclient.HttpClient; +import net.lenni0451.commons.httpclient.HttpResponse; import net.lenni0451.commons.httpclient.constants.ContentTypes; -import net.lenni0451.commons.httpclient.constants.Headers; +import net.lenni0451.commons.httpclient.constants.HttpHeaders; import net.lenni0451.commons.httpclient.constants.StatusCodes; import net.lenni0451.commons.httpclient.content.impl.URLEncodedFormContent; import net.lenni0451.commons.httpclient.exceptions.HttpRequestException; +import net.lenni0451.commons.httpclient.requests.HttpRequest; import net.lenni0451.commons.httpclient.requests.impl.GetRequest; import net.lenni0451.commons.httpclient.requests.impl.PostRequest; import net.lenni0451.commons.httpclient.utils.URLWrapper; @@ -36,9 +38,11 @@ import net.raphimc.minecraftauth.util.JsonUtil; import net.raphimc.minecraftauth.util.logging.ILogger; +import java.io.IOException; import java.io.StringReader; import java.net.CookieManager; import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -59,14 +63,33 @@ protected MsaCode execute(final ILogger logger, final HttpClient httpClient, fin } final CookieManager cookieManager = new CookieManager(); + final PostRequest loginPostRequest = this.prepareLoginPostRequest(httpClient, msaCredentials, cookieManager); + final HttpResponse loginResponse = this.sendLoginRequest(httpClient, loginPostRequest); + + final Optional locationHeader = loginResponse.getFirstHeader(HttpHeaders.LOCATION); + if (!locationHeader.isPresent()) { + throw new IllegalStateException("Could not get redirect url"); + } + + final Map parameters = new URLWrapper(locationHeader.get()).wrapQuery().getQueries(); + if (!parameters.containsKey("code")) { + throw new IllegalStateException("Could not extract MSA Code from redirect url"); + } + + final MsaCode msaCode = new MsaCode(parameters.get("code")); + logger.info(this, "Got MSA Code"); + return msaCode; + } + + private PostRequest prepareLoginPostRequest(final HttpClient httpClient, final MsaCredentials msaCredentials, final CookieManager cookieManager) throws IOException, URISyntaxException { final URL authenticationUrl = new URLWrapper(this.applicationDetails.getOAuthEnvironment().getAuthorizeUrl()).wrapQuery().addQueries(this.applicationDetails.getOAuthParameters()).apply().toURL(); final GetRequest getRequest = new GetRequest(authenticationUrl); getRequest.setCookieManager(cookieManager); - getRequest.setHeader(Headers.ACCEPT, ContentTypes.TEXT_HTML.getMimeType()); + getRequest.setHeader(HttpHeaders.ACCEPT, ContentTypes.TEXT_HTML.getMimeType()); final JsonObject config = httpClient.execute(getRequest, response -> { if (response.getStatusCode() >= 300) { - final Optional locationHeader = response.getFirstHeader(Headers.LOCATION); + final Optional locationHeader = response.getFirstHeader(HttpHeaders.LOCATION); if (locationHeader.isPresent()) { final Map parameters = new URLWrapper(locationHeader.get()).wrapQuery().getQueries(); if (parameters.containsKey("error") && parameters.containsKey("error_description")) { @@ -118,64 +141,76 @@ protected MsaCode execute(final ILogger logger, final HttpClient httpClient, fin final PostRequest postRequest = new PostRequest(urlPost); postRequest.setCookieManager(cookieManager); - postRequest.setHeader(Headers.ACCEPT, ContentTypes.TEXT_HTML.getMimeType()); + postRequest.setHeader(HttpHeaders.ACCEPT, ContentTypes.TEXT_HTML.getMimeType()); postRequest.setContent(new URLEncodedFormContent(postData)); - final String code = httpClient.execute(postRequest, response -> { - if (response.getStatusCode() != StatusCodes.MOVED_TEMPORARILY) { - if (!response.getContentType().orElse(ContentTypes.TEXT_PLAIN).getMimeType().equals(ContentTypes.TEXT_HTML.getMimeType())) { - throw new InformativeHttpRequestException(response, "Wrong content type"); - } + return postRequest; + } + + private HttpResponse sendLoginRequest(final HttpClient httpClient, final HttpRequest request) throws IOException { + final HttpResponse loginResponse = httpClient.execute(request); - final JsonObject errorConfig = StepCredentialsMsaCode.this.extractConfig(response.getContentAsString()); - switch (StepCredentialsMsaCode.this.applicationDetails.getOAuthEnvironment()) { + if (loginResponse.getStatusCode() != StatusCodes.MOVED_TEMPORARILY) { + if (!loginResponse.getContentType().orElse(ContentTypes.TEXT_PLAIN).getMimeType().equals(ContentTypes.TEXT_HTML.getMimeType())) { + throw new InformativeHttpRequestException(loginResponse, "Wrong content type"); + } + + final String responseString = loginResponse.getContentAsString(); + if (responseString.contains("")) { // Dialog informing the user about something. Can be skipped by getting the return url. + String actionUrl = responseString.substring(responseString.indexOf("action=\"") + 8); + actionUrl = actionUrl.substring(0, actionUrl.indexOf("\"")); + final String returnUrl = new URLWrapper(actionUrl).wrapQuery().getQuery("ru").get(); + + final GetRequest getRequest = new GetRequest(returnUrl); + getRequest.setCookieManager(request.getCookieManager()); + getRequest.setHeader(HttpHeaders.ACCEPT, ContentTypes.TEXT_HTML.getMimeType()); + return this.sendLoginRequest(httpClient, getRequest); + } else { + final JsonObject errorConfig = this.extractConfig(loginResponse.getContentAsString()); + switch (this.applicationDetails.getOAuthEnvironment()) { case LIVE: { if (errorConfig.has("sErrorCode") && errorConfig.has("sErrTxt")) { - throw new MsaRequestException(response, errorConfig.get("sErrorCode").getAsString(), errorConfig.get("sErrTxt").getAsString()); + throw new MsaRequestException(loginResponse, errorConfig.get("sErrorCode").getAsString(), errorConfig.get("sErrTxt").getAsString()); } break; } case MICROSOFT_ONLINE_COMMON: case MICROSOFT_ONLINE_CONSUMERS: { if (errorConfig.has("iErrorCode") && errorConfig.has("strServiceExceptionMessage")) { - throw new MsaRequestException(response, errorConfig.get("iErrorCode").getAsString(), errorConfig.get("strServiceExceptionMessage").getAsString()); + throw new MsaRequestException(loginResponse, errorConfig.get("iErrorCode").getAsString(), errorConfig.get("strServiceExceptionMessage").getAsString()); } break; } default: - throw new IllegalStateException("Unsupported OAuthEnvironment: " + StepCredentialsMsaCode.this.applicationDetails.getOAuthEnvironment()); + throw new IllegalStateException("Unsupported OAuthEnvironment: " + this.applicationDetails.getOAuthEnvironment()); } - } - final Optional locationHeader = response.getFirstHeader(Headers.LOCATION); - if (!locationHeader.isPresent()) { - throw new IllegalStateException("Could not get redirect url"); + throw new IllegalStateException("Could not extract config from html. This most likely indicates that the account does not exist"); } + } - final Map parameters = new URLWrapper(locationHeader.get()).wrapQuery().getQueries(); - if (!parameters.containsKey("code")) { - throw new IllegalStateException("Could not extract MSA Code from redirect url"); - } - - return parameters.get("code"); - }); - - final MsaCode msaCode = new MsaCode(code); - logger.info(this, "Got MSA Code"); - return msaCode; + return loginResponse; } private JsonObject extractConfig(final String html) { switch (this.applicationDetails.getOAuthEnvironment()) { case LIVE: { - final JsonReader jsonReader = new JsonReader(new StringReader(html.substring(html.indexOf("var ServerData = ") + 17))); - jsonReader.setLenient(true); - return JsonUtil.GSON.fromJson(jsonReader, JsonObject.class); + try { + final JsonReader jsonReader = new JsonReader(new StringReader(html.substring(html.indexOf("var ServerData = ") + 17))); + jsonReader.setLenient(true); + return JsonUtil.GSON.fromJson(jsonReader, JsonObject.class); + } catch (Throwable e) { + throw new IllegalStateException("Could not extract config from html. This most likely indicates that the login was not successful", e); + } } case MICROSOFT_ONLINE_COMMON: case MICROSOFT_ONLINE_CONSUMERS: { - final JsonReader jsonReader = new JsonReader(new StringReader(html.substring(html.indexOf("$Config=") + 8))); - jsonReader.setLenient(true); - return JsonUtil.GSON.fromJson(jsonReader, JsonObject.class); + try { + final JsonReader jsonReader = new JsonReader(new StringReader(html.substring(html.indexOf("$Config=") + 8))); + jsonReader.setLenient(true); + return JsonUtil.GSON.fromJson(jsonReader, JsonObject.class); + } catch (Throwable e) { + throw new IllegalStateException("Could not extract config from html. This most likely indicates that the login was not successful", e); + } } default: throw new IllegalStateException("Unsupported OAuthEnvironment: " + this.applicationDetails.getOAuthEnvironment()); diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServer.java b/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServer.java index 78359b6..34ed918 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServer.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServer.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -48,16 +48,18 @@ protected LocalWebServer execute(final ILogger logger, final HttpClient httpClie try (final ServerSocket localServer = new ServerSocket(0)) { final int localPort = localServer.getLocalPort(); + final String customRedirectUri = this.applicationDetails.getRedirectUri() + ":" + localPort; final URL authenticationUrl = new URLWrapper(this.applicationDetails.getOAuthEnvironment().getAuthorizeUrl()).wrapQuery() .addQueries(this.applicationDetails.getOAuthParameters()) - .setQuery("redirect_uri", this.applicationDetails.getRedirectUri() + ":" + localPort) + .setQuery("redirect_uri", customRedirectUri) .setQuery("prompt", "select_account") .apply().toURL(); final LocalWebServer localWebServer = new LocalWebServer( authenticationUrl.toString(), - localPort + localPort, + customRedirectUri ); logger.info(this, "Created local webserver MSA authentication URL: " + localWebServer.getAuthenticationUrl()); localWebServerCallback.callback.accept(localWebServer); @@ -71,6 +73,7 @@ public static class LocalWebServer extends AbstractStep.InitialInput { String authenticationUrl; int port; + String customRedirectUri; } diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServerMsaCode.java b/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServerMsaCode.java index 0321f54..7935923 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServerMsaCode.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/StepLocalWebServerMsaCode.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -83,6 +83,7 @@ protected MsaCode execute(final ILogger logger, final HttpClient httpClient, fin try { final MsaCode msaCode = msaCodeFuture.get(this.timeout, TimeUnit.MILLISECONDS); + msaCode.customRedirectUri = localWebServer.getCustomRedirectUri(); httpServer.stop(0); logger.info(this, "Got MSA Code"); return msaCode; diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCode.java b/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCode.java index 4a5cb25..3561ecd 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCode.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCode.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCodeMsaCode.java b/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCodeMsaCode.java index 579f429..860ead1 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCodeMsaCode.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaDeviceCodeMsaCode.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaToken.java b/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaToken.java index 2a8c29d..e60b81f 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaToken.java +++ b/src/main/java/net/raphimc/minecraftauth/step/msa/StepMsaToken.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -104,7 +104,11 @@ private MsaToken execute(final ILogger logger, final HttpClient httpClient, fina postData.put("refresh_token", codeOrRefreshToken); } else if (type.equals("authorization_code")) { postData.put("code", codeOrRefreshToken); - postData.put("redirect_uri", this.applicationDetails.getRedirectUri()); + if (msaCode.customRedirectUri != null) { + postData.put("redirect_uri", msaCode.customRedirectUri); + } else { + postData.put("redirect_uri", this.applicationDetails.getRedirectUri()); + } } else { throw new IllegalArgumentException("Invalid type: " + type); } diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblDeviceToken.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblDeviceToken.java index 20edba4..9f312dd 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblDeviceToken.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblDeviceToken.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblSisuAuthentication.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblSisuAuthentication.java index 8d4cb58..6039089 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblSisuAuthentication.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblSisuAuthentication.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -152,12 +152,12 @@ protected StepInitialXblSession.InitialXblSession prevResult() { @Override public boolean isExpired() { - return this.userToken.isExpired() || this.titleToken.isExpired() || this.xstsToken.isExpired(); + return this.userToken.isExpired() || this.titleToken.isExpired() || this.xstsToken.isExpired() || this.prevResult().isExpired(); } @Override public boolean isExpiredOrOutdated() { - return this.userToken.isExpiredOrOutdated() || this.titleToken.isExpiredOrOutdated() || this.xstsToken.isExpiredOrOutdated(); + return this.userToken.isExpiredOrOutdated() || this.titleToken.isExpiredOrOutdated() || this.xstsToken.isExpiredOrOutdated() || this.prevResult().isExpiredOrOutdated(); } } diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblTitleToken.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblTitleToken.java index fcfaec0..f67a72d 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblTitleToken.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblTitleToken.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -132,7 +132,7 @@ protected StepInitialXblSession.InitialXblSession prevResult() { @Override public boolean isExpired() { - return this.expireTimeMs <= System.currentTimeMillis(); + return this.expireTimeMs <= System.currentTimeMillis() || this.prevResult().isExpired(); } } diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblUserToken.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblUserToken.java index b1187d7..0c12bc4 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblUserToken.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblUserToken.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -128,7 +128,7 @@ protected StepInitialXblSession.InitialXblSession prevResult() { @Override public boolean isExpired() { - return this.expireTimeMs <= System.currentTimeMillis(); + return this.expireTimeMs <= System.currentTimeMillis() || this.prevResult().isExpired(); } } diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblXstsToken.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblXstsToken.java index bb85977..046e825 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblXstsToken.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/StepXblXstsToken.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -152,7 +152,7 @@ protected StepFullXblSession.FullXblSession prevResult() { @Override public boolean isExpired() { - return this.expireTimeMs <= System.currentTimeMillis(); + return this.expireTimeMs <= System.currentTimeMillis() || this.prevResult().isExpired(); } } diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/adapter/StepXblXstsToFullXblSession.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/adapter/StepXblXstsToFullXblSession.java index ad7996f..dc52a17 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/adapter/StepXblXstsToFullXblSession.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/adapter/StepXblXstsToFullXblSession.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepFullXblSession.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepFullXblSession.java index 20a90d5..1c7500b 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepFullXblSession.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepFullXblSession.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepInitialXblSession.java b/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepInitialXblSession.java index 834a64b..274f46c 100644 --- a/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepInitialXblSession.java +++ b/src/main/java/net/raphimc/minecraftauth/step/xbl/session/StepInitialXblSession.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/CryptUtil.java b/src/main/java/net/raphimc/minecraftauth/util/CryptUtil.java index f0a1748..2061b29 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/CryptUtil.java +++ b/src/main/java/net/raphimc/minecraftauth/util/CryptUtil.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,23 +18,17 @@ package net.raphimc.minecraftauth.util; import com.google.gson.JsonObject; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.impl.security.DefaultSecureRequest; import net.lenni0451.commons.httpclient.content.HttpContent; import net.lenni0451.commons.httpclient.model.HttpHeader; import net.lenni0451.commons.httpclient.requests.HttpContentRequest; import net.lenni0451.commons.httpclient.requests.HttpRequest; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.math.BigInteger; import java.nio.charset.StandardCharsets; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; +import java.security.*; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.InvalidKeySpecException; @@ -124,7 +118,21 @@ public static HttpHeader getSignatureHeader(final HttpRequest httpRequest, final data = new DataOutputStream(header); data.writeInt(1); // Policy Version data.writeLong(windowsTimestamp); // Timestamp - data.write(Jwts.SIG.ES256.digest(new DefaultSecureRequest<>(new ByteArrayInputStream(signatureContent.toByteArray()), null, null, privateKey))); // Signature + + try { + byte[] signature; + try { // Java 9+ only + final Signature ecdsaSignature = Signature.getInstance("SHA256withECDSAinP1363Format"); + ecdsaSignature.initSign(privateKey); + ecdsaSignature.update(signatureContent.toByteArray()); + signature = ecdsaSignature.sign(); + } catch (NoSuchAlgorithmException e) { // Fallback for Java 8 + signature = JwtUtil.signES256(privateKey, signatureContent.toByteArray()); + } + data.write(signature); // Signature + } catch (Throwable e) { + throw new RuntimeException("Could not sign request", e); + } return new HttpHeader("Signature", Base64.getEncoder().encodeToString(header.toByteArray())); } diff --git a/src/main/java/net/raphimc/minecraftauth/util/JsonContent.java b/src/main/java/net/raphimc/minecraftauth/util/JsonContent.java index 3e631af..05c1068 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/JsonContent.java +++ b/src/main/java/net/raphimc/minecraftauth/util/JsonContent.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/JsonUtil.java b/src/main/java/net/raphimc/minecraftauth/util/JsonUtil.java index 236d4b5..c8c755e 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/JsonUtil.java +++ b/src/main/java/net/raphimc/minecraftauth/util/JsonUtil.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/JwtUtil.java b/src/main/java/net/raphimc/minecraftauth/util/JwtUtil.java new file mode 100644 index 0000000..547b210 --- /dev/null +++ b/src/main/java/net/raphimc/minecraftauth/util/JwtUtil.java @@ -0,0 +1,60 @@ +/* + * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.raphimc.minecraftauth.util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.impl.security.DefaultSecureRequest; +import org.jetbrains.annotations.ApiStatus; + +import java.io.ByteArrayInputStream; +import java.security.PrivateKey; +import java.security.PublicKey; + +import static net.raphimc.minecraftauth.util.TimeUtil.MAX_JWT_CLOCK_SKEW; + +/** + * Utility class for handling JWTs. Code is intentionally kept separate from the rest of the project to allow for the exclusion of the JWT library. + */ +@ApiStatus.Internal +public class JwtUtil { + + public static Jwt parseSignedJwt(final String jwt, final PublicKey publicKey) { + final Jws parsedJwt = Jwts.parser().clockSkewSeconds(MAX_JWT_CLOCK_SKEW).verifyWith(publicKey).build().parseSignedClaims(jwt); + return new Jwt() { + + @Override + public T getClaim(final String claimName, final Class requiredType) { + return parsedJwt.getPayload().get(claimName, requiredType); + } + + }; + } + + public static byte[] signES256(final PrivateKey privateKey, final byte[] data) { + return Jwts.SIG.ES256.digest(new DefaultSecureRequest<>(new ByteArrayInputStream(data), null, null, privateKey)); + } + + public interface Jwt { + + T getClaim(final String claimName, final Class requiredType); + + } + +} diff --git a/src/main/java/net/raphimc/minecraftauth/util/MicrosoftConstants.java b/src/main/java/net/raphimc/minecraftauth/util/MicrosoftConstants.java index 6c655f8..e7a4f06 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/MicrosoftConstants.java +++ b/src/main/java/net/raphimc/minecraftauth/util/MicrosoftConstants.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/OAuthEnvironment.java b/src/main/java/net/raphimc/minecraftauth/util/OAuthEnvironment.java index 7f27756..7b9410a 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/OAuthEnvironment.java +++ b/src/main/java/net/raphimc/minecraftauth/util/OAuthEnvironment.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/TimeUtil.java b/src/main/java/net/raphimc/minecraftauth/util/TimeUtil.java index 26737d8..e812eab 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/TimeUtil.java +++ b/src/main/java/net/raphimc/minecraftauth/util/TimeUtil.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/UuidUtil.java b/src/main/java/net/raphimc/minecraftauth/util/UuidUtil.java index 3d82194..6a3271d 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/UuidUtil.java +++ b/src/main/java/net/raphimc/minecraftauth/util/UuidUtil.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/logging/ILogger.java b/src/main/java/net/raphimc/minecraftauth/util/logging/ILogger.java index 17d06d1..456b99a 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/logging/ILogger.java +++ b/src/main/java/net/raphimc/minecraftauth/util/logging/ILogger.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/logging/JavaConsoleLogger.java b/src/main/java/net/raphimc/minecraftauth/util/logging/JavaConsoleLogger.java index 20797c6..2e37371 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/logging/JavaConsoleLogger.java +++ b/src/main/java/net/raphimc/minecraftauth/util/logging/JavaConsoleLogger.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/logging/LazyLogger.java b/src/main/java/net/raphimc/minecraftauth/util/logging/LazyLogger.java index f675f91..03e172e 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/logging/LazyLogger.java +++ b/src/main/java/net/raphimc/minecraftauth/util/logging/LazyLogger.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/logging/NOPLogger.java b/src/main/java/net/raphimc/minecraftauth/util/logging/NOPLogger.java index eab158e..f70a7d0 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/logging/NOPLogger.java +++ b/src/main/java/net/raphimc/minecraftauth/util/logging/NOPLogger.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/logging/NoOpLogger.java b/src/main/java/net/raphimc/minecraftauth/util/logging/NoOpLogger.java new file mode 100644 index 0000000..697f3cd --- /dev/null +++ b/src/main/java/net/raphimc/minecraftauth/util/logging/NoOpLogger.java @@ -0,0 +1,34 @@ +/* + * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.raphimc.minecraftauth.util.logging; + +public class NoOpLogger implements ILogger { + + @Override + public void info(String message) { + } + + @Override + public void warn(String message) { + } + + @Override + public void error(String message) { + } + +} diff --git a/src/main/java/net/raphimc/minecraftauth/util/logging/PlainConsoleLogger.java b/src/main/java/net/raphimc/minecraftauth/util/logging/PlainConsoleLogger.java index 07c8de3..14df296 100644 --- a/src/main/java/net/raphimc/minecraftauth/util/logging/PlainConsoleLogger.java +++ b/src/main/java/net/raphimc/minecraftauth/util/logging/PlainConsoleLogger.java @@ -1,6 +1,6 @@ /* * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth - * Copyright (C) 2022-2024 RK_01/RaphiMC and contributors + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/main/java/net/raphimc/minecraftauth/util/logging/Slf4jConsoleLogger.java b/src/main/java/net/raphimc/minecraftauth/util/logging/Slf4jConsoleLogger.java new file mode 100644 index 0000000..50742e5 --- /dev/null +++ b/src/main/java/net/raphimc/minecraftauth/util/logging/Slf4jConsoleLogger.java @@ -0,0 +1,50 @@ +/* + * This file is part of MinecraftAuth - https://github.com/RaphiMC/MinecraftAuth + * Copyright (C) 2022-2025 RK_01/RaphiMC and contributors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package net.raphimc.minecraftauth.util.logging; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Slf4jConsoleLogger implements ILogger { + + private final Logger logger; + + public Slf4jConsoleLogger() { + this(LoggerFactory.getLogger("MinecraftAuth")); + } + + public Slf4jConsoleLogger(final Logger logger) { + this.logger = logger; + } + + @Override + public void info(final String message) { + this.logger.info(message); + } + + @Override + public void warn(final String message) { + this.logger.warn(message); + } + + @Override + public void error(final String message) { + this.logger.error(message); + } + +}