Skip to content

Commit c72dba6

Browse files
committed
introduce JWT class for easier parsing of idToken
1 parent ded1970 commit c72dba6

File tree

5 files changed

+18
-7
lines changed

5 files changed

+18
-7
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 1.6.5
2+
* oauth: AppleOAuthClient updated and tested
3+
* oauth: JWT helper class introduced
4+
15
# 1.6.4
26
* core: added common value types for Email, Phone, and Password, also StringValue base class
37
* jdbc: introduced db.insertBatch()

oauth/src/JWT.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package klite.oauth
2+
3+
import klite.base64Decode
4+
5+
data class JWT(val token: String) {
6+
private val parts = token.split(".").map { it.base64Decode().decodeToString() }
7+
val header get() = parts[0]
8+
val payload get() = parts[1]
9+
val signature get() = parts[2]
10+
}

oauth/src/OAuthClient.kt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,7 @@ class AppleOAuthClient(httpClient: HttpClient): OAuthClient(
112112
httpClient
113113
) {
114114
override suspend fun profile(token: OAuthTokenResponse, exchange: HttpExchange): UserProfile {
115-
val email = token.idToken!!.let {
116-
val payload = it.split(".")[1]
117-
http.json.parse<JsonNode>(payload.base64Decode().decodeToString()).getString("email")
118-
}
115+
val email = http.json.parse<JsonNode>(token.idToken!!.payload).getString("email")
119116
val user = exchange.bodyParams["user"]?.let { http.json.parse<AppleUserProfile>(it.toString()) }
120117
return UserProfile(provider, email, Email(email), user?.name?.firstName ?: email.substringBefore("@").capitalize(), user?.name?.lastName ?: "")
121118
}
@@ -124,5 +121,5 @@ class AppleOAuthClient(httpClient: HttpClient): OAuthClient(
124121
data class AppleUserName(val firstName: String, val lastName: String)
125122
}
126123

127-
data class OAuthTokenResponse(val accessToken: String, val expiresIn: Int, val scope: String? = null, val tokenType: String? = null, val idToken: String? = null, val refreshToken: String? = null)
124+
data class OAuthTokenResponse(val accessToken: String, val expiresIn: Int, val scope: String? = null, val tokenType: String? = null, val idToken: JWT? = null, val refreshToken: String? = null)
128125
data class UserProfile(val provider: String, override val id: String, override val email: Email, override val firstName: String, override val lastName: String, val avatarUrl: URI? = null, val locale: Locale? = null): OAuthUser

oauth/src/OAuthRoutes.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ open class OAuthRoutes(private val userProvider: OAuthUserProvider, registry: Re
3030

3131
val client = client(provider)
3232
val token = client.authenticate(code, e.fullUrl(e.path))
33-
var profile = client.profile(token)
33+
var profile = client.profile(token, e)
3434
if (profile.locale == null) profile = profile.copy(locale = Locale.forLanguageTag(e.lang))
3535

3636
val user = userProvider.provide(profile, token, e)

oauth/test/OAuthRoutesTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class OAuthRoutesTest {
2424
val oauthClient = mockk<OAuthClient> {
2525
every { provider } returns user.provider
2626
coEvery { authenticate("code", any()) } returns token
27-
coEvery { profile(token) } returns user
27+
coEvery { profile(token, exchange) } returns user
2828
}
2929
val userProvder = mockk<OAuthUserProvider>()
3030
val registry = mockk<Registry> {

0 commit comments

Comments
 (0)