Skip to content

Commit 47baa82

Browse files
committed
feat: SFA login
Signed-off-by: Gaurav Goel <[email protected]>
1 parent 8f31a45 commit 47baa82

File tree

5 files changed

+173
-13
lines changed

5 files changed

+173
-13
lines changed

app/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ dependencies {
6262

6363
// Web3Auth
6464
implementation project(":core")
65+
api 'io.jsonwebtoken:jjwt-api:0.11.5'
66+
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
67+
runtimeOnly('io.jsonwebtoken:jjwt-orgjson:0.11.5') {
68+
exclude group: 'org.json', module: 'json' //provided by Android natively
69+
}
6570

6671
// Test
6772
testImplementation 'junit:junit:4.13.2'
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package com.web3auth.app
2+
3+
import io.jsonwebtoken.Jwts
4+
import io.jsonwebtoken.SignatureAlgorithm
5+
import java.security.KeyFactory
6+
import java.security.PrivateKey
7+
import java.security.spec.PKCS8EncodedKeySpec
8+
import java.util.Date
9+
10+
object JwtUtils {
11+
fun generateIdToken(email: String): String {
12+
return Jwts.builder()
13+
.setSubject("email|" + email.split("@".toRegex()).toTypedArray()[0])
14+
.setAudience("torus-key-test")
15+
.setExpiration(Date(System.currentTimeMillis() + 3600 * 1000))
16+
.setIssuedAt(Date())
17+
.setIssuer("torus-key-test")
18+
.claim("email", email)
19+
.claim("nickname", email.split("@".toRegex()).toTypedArray()[0])
20+
.claim("name", email)
21+
.claim("picture", "")
22+
.claim("email_verified", true)
23+
.signWith(getPrivateKey(), SignatureAlgorithm.ES256).compact()
24+
}
25+
26+
private fun getPrivateKey(): PrivateKey? {
27+
val encoded: ByteArray = byteArrayOf(
28+
48,
29+
65,
30+
2,
31+
1,
32+
0,
33+
48,
34+
19,
35+
6,
36+
7,
37+
42,
38+
-122,
39+
72,
40+
-50,
41+
61,
42+
2,
43+
1,
44+
6,
45+
8,
46+
42,
47+
-122,
48+
72,
49+
-50,
50+
61,
51+
3,
52+
1,
53+
7,
54+
4,
55+
39,
56+
48,
57+
37,
58+
2,
59+
1,
60+
1,
61+
4,
62+
32,
63+
-125,
64+
-18,
65+
-126,
66+
-21,
67+
112,
68+
-90,
69+
-98,
70+
-6,
71+
53,
72+
89,
73+
60,
74+
108,
75+
121,
76+
-40,
77+
38,
78+
-1,
79+
-108,
80+
-88,
81+
93,
82+
43,
83+
26,
84+
87,
85+
-114,
86+
95,
87+
94,
88+
24,
89+
-42,
90+
-75,
91+
50,
92+
86,
93+
57,
94+
-20
95+
)
96+
val keyFactory: KeyFactory = KeyFactory.getInstance("EC")
97+
val keySpec = PKCS8EncodedKeySpec(encoded)
98+
return keyFactory.generatePrivate(keySpec)
99+
}
100+
}

app/src/main/java/com/web3auth/app/MainActivity.kt

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener {
6161
private val gson = Gson()
6262
private var TEST_VERIFIER = "torus-test-health"
6363
private var TORUS_TEST_EMAIL = "[email protected]"
64-
private var SFA_ClientId = "YOUR_CLIENT_ID"
6564

6665
private fun signIn() {
6766
val hintEmailEditText = findViewById<EditText>(R.id.etEmailHint)
@@ -90,7 +89,7 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener {
9089
//authConnectionId = "w3ads",
9190
//groupedAuthConnectionId = "aggregate-mobile",
9291
loginHint = loginHint,
93-
), ctx = this.applicationContext
92+
), ctx = this
9493
)
9594
loginCompletableFuture.whenComplete { _, error ->
9695
if (error == null) {
@@ -104,6 +103,35 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener {
104103
}
105104
}
106105

106+
private fun sfaSignIn() {
107+
val idToken = JwtUtils.generateIdToken(TORUS_TEST_EMAIL)
108+
val web3AuthOptions =
109+
Web3AuthOptions(
110+
clientId = "YOUR_CLIENT_ID",
111+
web3AuthNetwork = Web3AuthNetwork.SAPPHIRE_MAINNET,
112+
redirectUrl = "torusapp://org.torusresearch.web3authexample"
113+
)
114+
web3Auth = Web3Auth(
115+
web3AuthOptions, this
116+
)
117+
val loginCompletableFuture: CompletableFuture<Web3AuthResponse> = web3Auth.connectTo(
118+
LoginParams(
119+
authConnection = selectedLoginProvider,
120+
authConnectionId = TEST_VERIFIER,
121+
idToken = idToken
122+
), ctx = this
123+
)
124+
loginCompletableFuture.whenComplete { _, error ->
125+
if (error == null) {
126+
//reRender()
127+
println("PrivKey: " + web3Auth.getPrivateKey())
128+
println("Web3Auth UserInfo" + web3Auth.getUserInfo())
129+
} else {
130+
Log.d("MainActivity_Web3Auth", error.message ?: "Something went wrong")
131+
}
132+
}
133+
}
134+
107135
private fun signOut() {
108136
val logoutCompletableFuture = web3Auth.logout()
109137
logoutCompletableFuture.whenComplete { _, error ->
@@ -239,6 +267,9 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener {
239267
val signInButton = findViewById<Button>(R.id.signInButton)
240268
signInButton.setOnClickListener { signIn() }
241269

270+
val sfaSignInButton = findViewById<Button>(R.id.sfaSignInButton)
271+
sfaSignInButton.setOnClickListener { sfaSignIn() }
272+
242273
val signOutButton = findViewById<Button>(R.id.signOutButton)
243274
signOutButton.setOnClickListener { signOut() }
244275

app/src/main/res/layout/activity_main.xml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,20 @@
6666
app:layout_constraintEnd_toEndOf="parent"
6767
app:layout_constraintStart_toStartOf="parent"
6868
app:layout_constraintTop_toTopOf="parent"
69-
app:layout_constraintBottom_toBottomOf="parent"/>
69+
app:layout_constraintBottom_toBottomOf="parent" />
70+
71+
<Button
72+
android:id="@+id/sfaSignInButton"
73+
android:layout_width="match_parent"
74+
android:layout_height="wrap_content"
75+
android:layout_marginStart="40dp"
76+
android:layout_marginEnd="40dp"
77+
android:layout_marginBottom="8dp"
78+
android:text="SFA Sign In"
79+
android:textAllCaps="false"
80+
app:layout_constraintEnd_toEndOf="parent"
81+
app:layout_constraintStart_toStartOf="parent"
82+
app:layout_constraintTop_toBottomOf="@+id/signInButton" />
7083

7184
<Button
7285
android:id="@+id/signOutButton"

core/src/main/java/com/web3auth/core/Web3Auth.kt

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import org.json.JSONObject
4242
import org.torusresearch.fetchnodedetails.FetchNodeDetails
4343
import org.torusresearch.fetchnodedetails.types.NodeDetails
4444
import org.torusresearch.torusutils.TorusUtils
45+
import org.torusresearch.torusutils.types.VerifierParams
4546
import org.torusresearch.torusutils.types.common.SessionToken
4647
import org.torusresearch.torusutils.types.common.TorusKey
4748
import org.torusresearch.torusutils.types.common.TorusOptions
@@ -230,7 +231,7 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
230231
if (err == null) {
231232
//authorize session
232233
sessionManager.setSessionId(SessionManager.getSessionIdFromStorage())
233-
this.authorizeSession(web3AuthOption.redirectUrl.toString(), baseContext)
234+
this.authorizeSession(web3AuthOption.redirectUrl, baseContext)
234235
.whenComplete { resp, error ->
235236
runOnUIThread {
236237
if (error == null) {
@@ -398,10 +399,10 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
398399

399400
}
400401

401-
fun connect(
402+
private fun connect(
402403
loginParams: LoginParams,
403404
ctx: Context
404-
): Web3AuthResponse {
405+
) {
405406
val torusKey = getTorusKey(loginParams)
406407

407408
val publicAddress = torusKey.finalKeyData?.walletAddress
@@ -422,30 +423,31 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
422423
profileImage = it?.getClaim("picture")?.asString() ?: "",
423424
authConnectionId = loginParams.authConnectionId.toString(),
424425
authConnection = AuthConnection.CUSTOM.name.lowercase(Locale.ROOT),
425-
userId = it?.getClaim("userId")?.asString() ?: "",
426+
userId = it?.getClaim("email")?.asString() ?: "",
426427
)
427428
}
428429
} catch (e: Exception) {
429430
throw Exception(Web3AuthError.getError(ErrorCode.INVALID_LOGIN))
430431
}
431432

432-
val web3AuthResponse = Web3AuthResponse(
433+
val response = Web3AuthResponse(
433434
privateKey = privateKey.toString(),
434435
signatures = getSignatureData(torusKey.sessionData.sessionTokenData),
435436
userInfo = decodedUserInfo
436437
)
437438

438439
val sessionId = SessionManager.generateRandomSessionKey()
439440
sessionManager.setSessionId(sessionId)
440-
sessionManager.createSession(gson.toJson(web3AuthResponse), ctx)
441+
sessionManager.createSession(gson.toJson(response), ctx)
441442
.whenComplete { result, err ->
442443
if (err == null) {
444+
web3AuthResponse = response
443445
SessionManager.saveSessionIdToStorage(result)
444446
sessionManager.setSessionId(result)
447+
if (::loginCompletableFuture.isInitialized)
448+
loginCompletableFuture.complete(web3AuthResponse)
445449
}
446450
}
447-
448-
return web3AuthResponse
449451
}
450452

451453
private fun getTorusKey(
@@ -494,6 +496,15 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
494496
)
495497
}*/
496498

499+
val verifierParams = VerifierParams(userId.toString(), null, null, null)
500+
retrieveSharesResponse = torusUtils.retrieveShares(
501+
nodeDetails.torusNodeEndpoints,
502+
loginParams.authConnectionId.toString(),
503+
verifierParams,
504+
loginParams.idToken.toString(),
505+
null
506+
)
507+
497508
val isUpgraded = retrieveSharesResponse.metadata?.isUpgraded
498509

499510
if (isUpgraded == true) {
@@ -511,10 +522,10 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
511522
}
512523
}
513524

514-
fun getUserIdFromJWT(token: String): String? {
525+
private fun getUserIdFromJWT(token: String): String? {
515526
return try {
516527
val jwt = JWT(token)
517-
jwt.getClaim("userId").asString()
528+
jwt.getClaim("email").asString()
518529
} catch (e: Exception) {
519530
e.printStackTrace()
520531
null

0 commit comments

Comments
 (0)