simplify kt
This commit is contained in:
+4
-22
@@ -22,7 +22,7 @@ class CryptoUtil {
|
|||||||
return random
|
return random
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateKeyPair(): Any {
|
fun generateKeyPair(): Map<String, String> {
|
||||||
val keyIdString = UUID.randomUUID().toString()
|
val keyIdString = UUID.randomUUID().toString()
|
||||||
|
|
||||||
val keyPairGen = KeyPairGenerator.getInstance("EC")
|
val keyPairGen = KeyPairGenerator.getInstance("EC")
|
||||||
@@ -44,27 +44,9 @@ class CryptoUtil {
|
|||||||
.algorithm(Algorithm.parse("ES256"))
|
.algorithm(Algorithm.parse("ES256"))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
return mapOf(
|
||||||
return JWKPair(
|
"privateKey" to privateJwk.toJSONString(),
|
||||||
JWK(
|
"publicKey" to publicJwk.toJSONString()
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -17,14 +17,14 @@ class ExpoBlueskyOAuthClientModule : Module() {
|
|||||||
return@Function CryptoUtil().getRandomValues(byteLength)
|
return@Function CryptoUtil().getRandomValues(byteLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncFunction("generateJwk") { algorithim: String ->
|
AsyncFunction("generateJwk") { algorithim: String? ->
|
||||||
if (algorithim != "ES256") {
|
if (algorithim != "ES256") {
|
||||||
throw Exception("Unsupported algorithm")
|
throw Exception("Unsupported algorithm")
|
||||||
}
|
}
|
||||||
return@AsyncFunction CryptoUtil().generateKeyPair()
|
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)
|
return@AsyncFunction JWTUtil().createJwt(header, payload, jwk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-29
@@ -3,32 +3,7 @@ package expo.modules.blueskyoauthclient
|
|||||||
import expo.modules.kotlin.records.Record
|
import expo.modules.kotlin.records.Record
|
||||||
import expo.modules.kotlin.records.Field
|
import expo.modules.kotlin.records.Field
|
||||||
|
|
||||||
class JWK(
|
class JWKPair(
|
||||||
@Field var alg: String = "",
|
@Field val privateKey: String,
|
||||||
@Field var kty: String = "",
|
@Field val publicKey: String
|
||||||
@Field var crv: String? = null,
|
) : Record
|
||||||
@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<String>()
|
|
||||||
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
|
|
||||||
+2
-168
@@ -3,173 +3,7 @@ package expo.modules.blueskyoauthclient
|
|||||||
import expo.modules.kotlin.records.Record
|
import expo.modules.kotlin.records.Record
|
||||||
import expo.modules.kotlin.records.Field
|
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<String>()
|
|
||||||
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<String>()
|
|
||||||
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<String>()
|
|
||||||
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<String>()
|
|
||||||
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<String>? = null,
|
|
||||||
@Field var actions: Array<String>? = null,
|
|
||||||
@Field var datatypes: Array<String>? = null,
|
|
||||||
@Field var identifier: String? = null,
|
|
||||||
@Field var privileges: Array<String>? = null
|
|
||||||
) : Record {
|
|
||||||
fun toJson(): String {
|
|
||||||
val parts = mutableListOf<String>()
|
|
||||||
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(
|
class JWTVerifyResponse(
|
||||||
@Field var protectedHeader: JWTHeader = JWTHeader(),
|
@Field var protectedHeader: String,
|
||||||
@Field var payload: String = "",
|
@Field var payload: String,
|
||||||
) : Record
|
) : Record
|
||||||
+9
-35
@@ -8,10 +8,10 @@ import com.nimbusds.jwt.JWTClaimsSet
|
|||||||
import com.nimbusds.jwt.SignedJWT
|
import com.nimbusds.jwt.SignedJWT
|
||||||
|
|
||||||
class JWTUtil {
|
class JWTUtil {
|
||||||
fun createJwt(header: JWTHeader, payload: JWTPayload, jwk: JWK): String {
|
fun createJwt(header: String, payload: String, jwk: String): String {
|
||||||
val parsedKey = ECKey.parse(jwk.toJson())
|
val parsedKey = ECKey.parse(jwk)
|
||||||
val parsedHeader = JWSHeader.parse(header.toJson())
|
val parsedHeader = JWSHeader.parse(header)
|
||||||
val parsedPayload = JWTClaimsSet.parse(payload.toJson())
|
val parsedPayload = JWTClaimsSet.parse(payload)
|
||||||
|
|
||||||
val signer = ECDSASigner(parsedKey)
|
val signer = ECDSASigner(parsedKey)
|
||||||
val jwt = SignedJWT(parsedHeader, parsedPayload)
|
val jwt = SignedJWT(parsedHeader, parsedPayload)
|
||||||
@@ -20,9 +20,9 @@ class JWTUtil {
|
|||||||
return jwt.serialize()
|
return jwt.serialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun verifyJwt(token: String, jwk: JWK): JWTVerifyResponse {
|
fun verifyJwt(token: String, jwk: String): Map<String, String> {
|
||||||
try {
|
try {
|
||||||
val parsedKey = ECKey.parse(jwk.toJson())
|
val parsedKey = ECKey.parse(jwk)
|
||||||
val jwt = SignedJWT.parse(token)
|
val jwt = SignedJWT.parse(token)
|
||||||
val verifier = ECDSAVerifier(parsedKey)
|
val verifier = ECDSAVerifier(parsedKey)
|
||||||
|
|
||||||
@@ -32,36 +32,10 @@ class JWTUtil {
|
|||||||
|
|
||||||
val header = jwt.header
|
val header = jwt.header
|
||||||
val payload = jwt.payload
|
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(
|
return mapOf(
|
||||||
alg = header.algorithm.toString(),
|
"payload" to payload.toString(),
|
||||||
jku = header.jwkurl?.toString(),
|
"protectedHeader" to header.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,
|
|
||||||
)
|
)
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
throw e
|
throw e
|
||||||
|
|||||||
Reference in New Issue
Block a user