A simple Java OAuth 2.0 library for Korean OAuth providers (Kakao, Naver)
Official releases are published to Maven Central.
Add the following to your build.gradle file:
dependencies {
implementation 'kr.higu:k-oauth:0.1.2'
}<dependency>
<groupId>kr.higu</groupId>
<artifactId>k-oauth</artifactId>
<version>0.1.2</version>
</dependency>JitPack remains available as a secondary channel for GitHub-based snapshot or branch builds.
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.higukang:k-oauth:main-SNAPSHOT'
}If you cannot see the library's source code or Javadoc in your IDE:
- IntelliJ: Click "Download Sources" in the notification bar or use the Gradle tab to refresh with sources enabled.
- VS Code: Ensure the "Java Language Support" extension is installed; it typically handles sources automatically.
Javadoc is included in the published Maven Central artifacts through the javadoc classifier.
K-OAuth uses a singleton HttpClient by default to avoid creating a new HTTP client for every OAuth request.
Reusing a single client reduces unnecessary overhead, allows the JDK to reuse underlying connections internally,
and keeps the library lightweight for common Spring Boot and side-project use cases.
This design favors simplicity and predictable behavior over heavy configuration.
If you need more control over the transport layer, you can provide your own IHttpManager
through KakaoClient.create(IHttpManager) or NaverClient.create(IHttpManager).
1. Exchange Code for Access Token
KakaoClient kakaoClient = KakaoClient.create();
try {
KakaoTokenResponse response = kakaoClient.getToken()
.clientId("YOUR_REST_API_KEY")
.redirectUri("YOUR_REDIRECT_URI")
.code("AUTHORIZATION_CODE")
.clientSecret("YOUR_CLIENT_SECRET") // Optional (null is ignored)
.build()
.execute();
System.out.println("Access Token: " + response.accessToken());
} catch (OAuthException e) {
e.printStackTrace();
}2. Refresh Tokens with a Refresh Token
KakaoClient kakaoClient = KakaoClient.create();
try {
KakaoRefreshTokenResponse response = kakaoClient.refreshToken()
.clientId("YOUR_REST_API_KEY")
.refreshToken("USER_REFRESH_TOKEN")
.clientSecret("YOUR_CLIENT_SECRET") // Optional unless Client Secret is enabled
.build()
.execute();
System.out.println("Refreshed Access Token: " + response.accessToken());
} catch (OAuthException e) {
e.printStackTrace();
}Kakao refresh token notes:
- If Client Secret is enabled in the Kakao console,
client_secretmust be included in the refresh request. id_tokenis only returned when the refresh token was originally issued with OpenID Connect.refresh_tokenandrefresh_token_expires_inare only returned when the current refresh token has less than one month remaining.- If Kakao returns an error such as
KOE237, the library exposes it throughOAuthResponseException#getErrorCode().
3. Get User Profile
KakaoClient kakaoClient = KakaoClient.create();
try {
KakaoUserResponse user = kakaoClient.getUserInfo()
.accessToken("ACCESS_TOKEN")
.secureResource(false)
.propertyKeys(KakaoPropertyKey.EMAIL)
.build()
.execute();
System.out.println("Nickname: " + user.kakaoAccount().profile().nickname());
} catch (OAuthException e) {
e.printStackTrace();
}1. Exchange Code for Access Token
NaverClient naverClient = NaverClient.create();
try {
NaverTokenResponse response = naverClient.getToken()
.clientId("CLIENT_ID")
.clientSecret("SECRET")
.code("CODE")
.state("STATE")
.build()
.execute();
System.out.println("Access Token: " + response.accessToken());
} catch (OAuthException e) {
e.printStackTrace();
}2. Refresh Access Token with a Refresh Token
NaverClient naverClient = NaverClient.create();
try {
NaverRefreshTokenResponse response = naverClient.refreshToken()
.clientId("YOUR_CLIENT_ID")
.clientSecret("YOUR_CLIENT_SECRET")
.refreshToken("USER_REFRESH_TOKEN")
.build()
.execute();
System.out.println("Refreshed Access Token: " + response.accessToken());
} catch (OAuthException e) {
e.printStackTrace();
}Naver refresh token notes:
- Naver uses the same token endpoint for token issuance and token refresh, but the required parameters differ by
grant_type. - The refresh token response follows the official refresh output fields and does not include
refresh_token. - Naver may return HTTP
200 OKwitherroranderror_descriptionin the response body. - The library converts those responses into
OAuthResponseException.
3. Get User Profile
NaverClient naverClient = NaverClient.create();
try {
NaverUserResponse response = naverClient.getUserInfo()
.accessToken("ACCESS_TOKEN")
.build()
.execute();
System.out.println("Nickname: " + response.response().nickname());
} catch (OAuthException e) {
e.printStackTrace();
}Selective Property Retrieval (Kakao Only)
You can request specific user properties to optimize the response size.
KakaoUserResponse user = kakaoClient.getUserInfo()
.accessToken("ACCESS_TOKEN")
.propertyKeys(KakaoPropertyKey.EMAIL, KakaoPropertyKey.PROFILE)
.secureResource(true) // Return HTTPS URLs
.build()
.execute();K-OAuth provides a detailed exception hierarchy to help you handle various failure scenarios.
-
OAuthValidationException: Thrown when mandatory parameters are missing before the request.
-
OAuthResponseException: Thrown when the OAuth provider returns a non-2xx response or a logical error (Naver's 200 OK error).
-
OAuthNetworkException: Thrown when network issues occur (timeouts, DNS failures).
-
OAuthParsingException: Thrown when a provider response cannot be parsed as expected JSON.
Validation and optional parameter notes:
- Required values are validated at
build()time and throwOAuthValidationException. - Optional parameters with
nullvalues are safely ignored.
try {
// execute request...
} catch (OAuthResponseException e) {
System.out.println("Status Code: " + e.getStatusCode());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Message: " + e.getMessage());
} catch (OAuthException e) {
// Handle other exceptions
}| Inspiration |
|---|
| Inspired by spotify-web-api-java. |
- Issues and Pull Requests are always welcome.
- Feel free to contribute, from small typo fixes to feature suggestions.
This project is licensed under the MIT License - see the LICENSE file for details.
