From f464875db0fc9ef3e8e06d2e3379687f29b04db5 Mon Sep 17 00:00:00 2001 From: Hailey Date: Mon, 15 Apr 2024 09:25:43 -0700 Subject: [PATCH] simplify kt --- .../modules/blueskyoauthclient/CryptoUtil.kt | 26 +-- .../ExpoBlueskyOAuthClientModule.kt | 4 +- .../expo/modules/blueskyoauthclient/JWK.kt | 33 +--- .../expo/modules/blueskyoauthclient/JWT.kt | 170 +----------------- .../modules/blueskyoauthclient/JWTUtil.kt | 44 +---- 5 files changed, 21 insertions(+), 256 deletions(-) diff --git a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/CryptoUtil.kt b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/CryptoUtil.kt index eab729a8b8..e47060aa95 100644 --- a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/CryptoUtil.kt +++ b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/CryptoUtil.kt @@ -22,7 +22,7 @@ class CryptoUtil { return random } - fun generateKeyPair(): Any { + fun generateKeyPair(): Map { val keyIdString = UUID.randomUUID().toString() val keyPairGen = KeyPairGenerator.getInstance("EC") @@ -44,27 +44,9 @@ class CryptoUtil { .algorithm(Algorithm.parse("ES256")) .build() - - return JWKPair( - JWK( - alg = privateJwk.algorithm.toString(), - kty = privateJwk.keyType.toString(), - crv = privateJwk.curve.toString(), - x = privateJwk.x.toString(), - y = privateJwk.y.toString(), - d = privateJwk.d.toString(), - use = privateJwk.keyUse.toString(), - kid = privateJwk.keyID - ), - JWK( - alg = publicJwk.algorithm.toString(), - kty = publicJwk.keyType.toString(), - crv = publicJwk.curve.toString(), - x = publicJwk.x.toString(), - y = publicJwk.y.toString(), - use = publicJwk.keyUse.toString(), - kid = publicJwk.keyID - ) + return mapOf( + "privateKey" to privateJwk.toJSONString(), + "publicKey" to publicJwk.toJSONString() ) } } diff --git a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/ExpoBlueskyOAuthClientModule.kt b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/ExpoBlueskyOAuthClientModule.kt index 93e7f70364..8ebdf91e50 100644 --- a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/ExpoBlueskyOAuthClientModule.kt +++ b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/ExpoBlueskyOAuthClientModule.kt @@ -17,14 +17,14 @@ class ExpoBlueskyOAuthClientModule : Module() { return@Function CryptoUtil().getRandomValues(byteLength) } - AsyncFunction("generateJwk") { algorithim: String -> + AsyncFunction("generateJwk") { algorithim: String? -> if (algorithim != "ES256") { throw Exception("Unsupported algorithm") } return@AsyncFunction CryptoUtil().generateKeyPair() } - AsyncFunction("createJwt") { header: JWTHeader, payload: JWTPayload, jwk: JWK -> + AsyncFunction("createJwt") { header: String, payload: String, jwk: String -> return@AsyncFunction JWTUtil().createJwt(header, payload, jwk) } diff --git a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWK.kt b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWK.kt index 2ce71dd8fa..9f9f1dd629 100644 --- a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWK.kt +++ b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWK.kt @@ -3,32 +3,7 @@ package expo.modules.blueskyoauthclient import expo.modules.kotlin.records.Record import expo.modules.kotlin.records.Field -class JWK( - @Field var alg: String = "", - @Field var kty: String = "", - @Field var crv: String? = null, - @Field var x: String? = null, - @Field var y: String? = null, - @Field var e: String? = null, - @Field var n: String? = null, - @Field var d: String? = null, - @Field var use: String? = null, - @Field var kid: String? = null -) : Record { - fun toJson(): String { - val parts = mutableListOf() - if (alg.isNotEmpty()) parts.add("\"alg\": \"$alg\"") - if (kty.isNotEmpty()) parts.add("\"kty\": \"$kty\"") - if (crv != null) parts.add("\"crv\": \"$crv\"") - if (x != null) parts.add("\"x\": \"$x\"") - if (y != null) parts.add("\"y\": \"$y\"") - if (e != null) parts.add("\"e\": \"$e\"") - if (n != null) parts.add("\"n\": \"$n\"") - if (d != null) parts.add("\"d\": \"$d\"") - if (use != null) parts.add("\"use\": \"$use\"") - if (kid != null) parts.add("\"kid\": \"$kid\"") - return "{ ${parts.joinToString()} }" - } -} - -class JWKPair(@Field val privateKey: JWK, @Field val publicKey: JWK) : Record \ No newline at end of file +class JWKPair( + @Field val privateKey: String, + @Field val publicKey: String +) : Record \ No newline at end of file diff --git a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWT.kt b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWT.kt index 8b761615a0..4990fa66a2 100644 --- a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWT.kt +++ b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWT.kt @@ -3,173 +3,7 @@ package expo.modules.blueskyoauthclient import expo.modules.kotlin.records.Record import expo.modules.kotlin.records.Field -class JWTHeader( - @Field var alg: String = "", - @Field var jku: String? = null, - @Field var jwk: JWK? = null, - @Field var kid: String? = null, - @Field var typ: String? = null, - @Field var cty: String? = null, - @Field var crit: String? = null -) : Record { - fun toJson(): String { - val parts = mutableListOf() - if (alg.isNotEmpty()) parts.add("\"alg\": \"$alg\"") - if (jku != null) parts.add("\"jku\": \"$jku\"") - if (jwk != null) parts.add("\"jwk\": ${jwk?.toJson()}") - if (kid != null) parts.add("\"kid\": \"$kid\"") - if (typ != null) parts.add("\"typ\": \"$typ\"") - if (cty != null) parts.add("\"cty\": \"$cty\"") - if (crit != null) parts.add("\"crit\": \"$crit\"") - return "{ ${parts.joinToString()} }" - } -} - -class JWTPayload( - @Field var iss: String? = null, - @Field var aud: String? = null, - @Field var sub: String? = null, - @Field var exp: Int? = null, - @Field var nbr: Int? = null, - @Field var iat: Int? = null, - @Field var jti: String? = null, - @Field var htm: String? = null, - @Field var htu: String? = null, - @Field var ath: String? = null, - @Field var acr: String? = null, - @Field var azp: String? = null, - @Field var amr: String? = null, - @Field var cnf: JWTPayloadCNF? = null, - @Field var client_id: String? = null, - @Field var scope: String? = null, - @Field var nonce: String? = null, - @Field var at_hash: String? = null, - @Field var c_hash: String? = null, - @Field var s_hash: String? = null, - @Field var auth_time: Int? = null, - @Field var name: String? = null, - @Field var family_name: String? = null, - @Field var given_name: String? = null, - @Field var middle_name: String? = null, - @Field var nickname: String? = null, - @Field var preferred_username: String? = null, - @Field var gender: String? = null, - @Field var picture: String? = null, - @Field var profile: String? = null, - @Field var birthdate: String? = null, - @Field var zoneinfo: String? = null, - @Field var updated_at: Int? = null, - @Field var email: String? = null, - @Field var email_verified: Boolean? = null, - @Field var phone_number: String? = null, - @Field var phone_number_verified: Boolean? = null, - @Field var address: JWTPayloadAddress? = null, - @Field var authorization_details: JWTPayloadAuthorizationDetails? = null -) : Record { - fun toJson(): String { - val parts = mutableListOf() - if (iss != null) parts.add("\"iss\": \"$iss\"") - if (aud != null) parts.add("\"aud\": \"$aud\"") - if (sub != null) parts.add("\"sub\": \"$sub\"") - if (exp != null) parts.add("\"exp\": $exp") - if (nbr != null) parts.add("\"nbr\": $nbr") - if (iat != null) parts.add("\"iat\": $iat") - if (jti != null) parts.add("\"jti\": \"$jti\"") - if (htm != null) parts.add("\"htm\": \"$htm\"") - if (htu != null) parts.add("\"htu\": \"$htu\"") - if (ath != null) parts.add("\"ath\": \"$ath\"") - if (acr != null) parts.add("\"acr\": \"$acr\"") - if (azp != null) parts.add("\"azp\": \"$azp\"") - if (amr != null) parts.add("\"amr\": \"$amr\"") - if (cnf != null) parts.add("\"cnf\": ${cnf?.toJson()}") - if (client_id != null) parts.add("\"client_id\": \"$client_id\"") - if (scope != null) parts.add("\"scope\": \"$scope\"") - if (nonce != null) parts.add("\"nonce\": \"$nonce\"") - if (at_hash != null) parts.add("\"at_hash\": \"$at_hash\"") - if (c_hash != null) parts.add("\"c_hash\": \"$c_hash\"") - if (s_hash != null) parts.add("\"s_hash\": \"$s_hash\"") - if (auth_time != null) parts.add("\"auth_time\": $auth_time") - if (name != null) parts.add("\"name\": \"$name\"") - if (family_name != null) parts.add("\"family_name\": \"$family_name\"") - if (given_name != null) parts.add("\"given_name\": \"$given_name\"") - if (middle_name != null) parts.add("\"middle_name\": \"$middle_name\"") - if (nickname != null) parts.add("\"nickname\": \"$nickname\"") - if (preferred_username != null) parts.add("\"preferred_username\": \"$preferred_username\"") - if (gender != null) parts.add("\"gender\": \"$gender\"") - if (picture != null) parts.add("\"picture\": \"$picture\"") - if (profile != null) parts.add("\"profile\": \"$profile\"") - if (birthdate != null) parts.add("\"birthdate\": \"$birthdate\"") - if (zoneinfo != null) parts.add("\"zoneinfo\": \"$zoneinfo\"") - if (updated_at != null) parts.add("\"updated_at\": $updated_at") - if (email != null) parts.add("\"email\": \"$email\"") - if (email_verified != null) parts.add("\"email_verified\": $email_verified") - if (phone_number != null) parts.add("\"phone_number\": \"$phone_number\"") - if (phone_number_verified != null) parts.add("\"phone_number_verified\": $phone_number_verified") - if (address != null) parts.add("\"address\": ${address?.toJson()}") - if (authorization_details != null) parts.add("\"authorization_details\": ${authorization_details?.toJson()}") - return "{ ${parts.joinToString()} }" - } -} - -class JWTPayloadCNF( - @Field var jwk: JWK? = null, - @Field var jwe: String? = null, - @Field var jku: String? = null, - @Field var jkt: String? = null, - @Field var osc: String? = null -) : Record { - fun toJson(): String { - val parts = mutableListOf() - if (jwk != null) parts.add("\"jwk\": ${jwk?.toJson()}") - if (jwe != null) parts.add("\"jwe\": \"$jwe\"") - if (jku != null) parts.add("\"jku\": \"$jku\"") - if (jkt != null) parts.add("\"jkt\": \"$jkt\"") - if (osc != null) parts.add("\"osc\": \"$osc\"") - return "{ ${parts.joinToString()} }" - } -} - -class JWTPayloadAddress( - @Field var formatted: String? = null, - @Field var street_address: String? = null, - @Field var locality: String? = null, - @Field var region: String? = null, - @Field var postal_code: String? = null, - @Field var country: String? = null -) : Record { - fun toJson(): String { - val parts = mutableListOf() - if (formatted != null) parts.add("\"formatted\": \"$formatted\"") - if (street_address != null) parts.add("\"street_address\": \"$street_address\"") - if (locality != null) parts.add("\"locality\": \"$locality\"") - if (region != null) parts.add("\"region\": \"$region\"") - if (postal_code != null) parts.add("\"postal_code\": \"$postal_code\"") - if (country != null) parts.add("\"country\": \"$country\"") - return "{ ${parts.joinToString()} }" - } -} - -class JWTPayloadAuthorizationDetails( - @Field var type: String? = null, - @Field var locations: Array? = null, - @Field var actions: Array? = null, - @Field var datatypes: Array? = null, - @Field var identifier: String? = null, - @Field var privileges: Array? = null -) : Record { - fun toJson(): String { - val parts = mutableListOf() - if (type != null) parts.add("\"type\": \"$type\"") - if (locations != null) parts.add("\"locations\": [${locations?.joinToString()}]") - if (actions != null) parts.add("\"actions\": [${actions?.joinToString()}]") - if (datatypes != null) parts.add("\"datatypes\": [${datatypes?.joinToString()}]") - if (identifier != null) parts.add("\"identifier\": \"$identifier\"") - if (privileges != null) parts.add("\"privileges\": [${privileges?.joinToString()}]") - return "{ ${parts.joinToString()} }" - } -} - class JWTVerifyResponse( - @Field var protectedHeader: JWTHeader = JWTHeader(), - @Field var payload: String = "", + @Field var protectedHeader: String, + @Field var payload: String, ) : Record \ No newline at end of file diff --git a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWTUtil.kt b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWTUtil.kt index 1fb9276e5d..f01d4a79bc 100644 --- a/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWTUtil.kt +++ b/modules/expo-bluesky-oauth-client/android/src/main/java/expo/modules/blueskyoauthclient/JWTUtil.kt @@ -8,10 +8,10 @@ import com.nimbusds.jwt.JWTClaimsSet import com.nimbusds.jwt.SignedJWT class JWTUtil { - fun createJwt(header: JWTHeader, payload: JWTPayload, jwk: JWK): String { - val parsedKey = ECKey.parse(jwk.toJson()) - val parsedHeader = JWSHeader.parse(header.toJson()) - val parsedPayload = JWTClaimsSet.parse(payload.toJson()) + fun createJwt(header: String, payload: String, jwk: String): String { + val parsedKey = ECKey.parse(jwk) + val parsedHeader = JWSHeader.parse(header) + val parsedPayload = JWTClaimsSet.parse(payload) val signer = ECDSASigner(parsedKey) val jwt = SignedJWT(parsedHeader, parsedPayload) @@ -20,9 +20,9 @@ class JWTUtil { return jwt.serialize() } - fun verifyJwt(token: String, jwk: JWK): JWTVerifyResponse { + fun verifyJwt(token: String, jwk: String): Map { try { - val parsedKey = ECKey.parse(jwk.toJson()) + val parsedKey = ECKey.parse(jwk) val jwt = SignedJWT.parse(token) val verifier = ECDSAVerifier(parsedKey) @@ -32,36 +32,10 @@ class JWTUtil { val header = jwt.header val payload = jwt.payload - val ecKey = header.jwk?.toECKey() - val serializedJwk = if (ecKey != null) { - JWK( - alg = ecKey.algorithm.toString(), - kty = ecKey.keyType.toString(), - crv = ecKey.curve.toString(), - x = ecKey.x.toString(), - y = ecKey.y.toString(), - d = ecKey.d.toString(), - use = ecKey.keyUse.toString(), - kid = ecKey.keyID - ) - } else { - null - } - - val serializedHeader = JWTHeader( - alg = header.algorithm.toString(), - jku = header.jwkurl?.toString(), - jwk = serializedJwk, - kid = header.keyID, - typ = header.type?.toString(), - cty = header.contentType, - crit = header.criticalParams?.joinToString() - ) - val serializedPayload = payload.toString() - return JWTVerifyResponse( - protectedHeader = serializedHeader, - payload = serializedPayload, + return mapOf( + "payload" to payload.toString(), + "protectedHeader" to header.toString() ) } catch(e: Exception) { throw e