Skip to content

Commit

Permalink
Updates from decentralised-dataexchange/main
Browse files Browse the repository at this point in the history
Updates is SDK
  • Loading branch information
josmilan authored Jul 29, 2024
2 parents fa35bea + a4f403c commit 4b5a8d6
Show file tree
Hide file tree
Showing 31 changed files with 1,541 additions and 117 deletions.
18 changes: 9 additions & 9 deletions app/src/main/java/com/ewc/eudiwalletoidcandroid/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ class MainActivity : AppCompatActivity() {
}

private fun initClicks() {
binding.btnCreateDID.setOnClickListener {
viewModel?.subJwk = DIDService().createJWK()
viewModel?.did = DIDService().createDID(viewModel?.subJwk!!)

viewModel?.displayText?.value = "Sub JWK : \n ${Gson().toJson(viewModel?.subJwk)}\n\n"
viewModel?.displayText?.value =
"${viewModel?.displayText?.value}Did : ${viewModel?.did}\n\n"
}
// binding.btnCreateDID.setOnClickListener {
// viewModel?.subJwk = DIDService().createJWK()
// viewModel?.did = DIDService().createDID(viewModel?.subJwk!!)
//
// viewModel?.displayText?.value = "Sub JWK : \n ${Gson().toJson(viewModel?.subJwk)}\n\n"
// viewModel?.displayText?.value =
// "${viewModel?.displayText?.value}Did : ${viewModel?.did}\n\n"
// }

binding.addCredential.setOnClickListener {
if (ContextCompat.checkSelfPermission(
Expand Down Expand Up @@ -150,7 +150,7 @@ class MainActivity : AppCompatActivity() {
viewModel?.displayText?.value =
"${viewModel?.displayText?.value}Scanned data : $url\n\n"

viewModel?.issueCredential(url ?: "")
viewModel?.issueCredential(url ?: "",this)
}

REQUEST_CODE_SCAN_VERIFY -> {
Expand Down
53 changes: 37 additions & 16 deletions app/src/main/java/com/ewc/eudiwalletoidcandroid/MainViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.ewc.eudiwalletoidcandroid

import android.content.Context
import android.net.Uri
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.ewc.eudi_wallet_oidc_android.CryptographicAlgorithms
import com.ewc.eudi_wallet_oidc_android.models.AuthorisationServerWellKnownConfiguration
import com.ewc.eudi_wallet_oidc_android.models.CredentialOffer
import com.ewc.eudi_wallet_oidc_android.models.IssuerWellKnownConfiguration
Expand All @@ -17,15 +20,19 @@ import com.ewc.eudi_wallet_oidc_android.services.sdjwt.SDJWTService
import com.ewc.eudi_wallet_oidc_android.services.verification.VerificationService
import com.google.gson.Gson
import com.nimbusds.jose.jwk.ECKey
import com.nimbusds.jose.jwk.JWK
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.ArrayList
import java.util.Timer
import java.util.TimerTask

class MainViewModel : ViewModel() {

private var format: String? = null
private var types: ArrayList<String> = arrayListOf()
var isLoading = MutableLiveData<Boolean>(false)

var isPreAuthorised = MutableLiveData<Boolean>(false)
Expand All @@ -40,28 +47,38 @@ class MainViewModel : ViewModel() {
private var issuerConfig: IssuerWellKnownConfiguration? = null
private var offerCredential: CredentialOffer? = null
lateinit var did: String
lateinit var subJwk: ECKey
lateinit var subJwk: JWK

init {
isLoading.value = false
}

fun issueCredential(url: String) {
fun issueCredential(url: String,context:Context) {
isLoading.value = true
CoroutineScope(Dispatchers.Main).launch {
// Resolving credential offer
offerCredential = IssueService().resolveCredentialOffer(url)

// Discovery
issuerConfig =
DiscoveryService().getIssuerConfig("${offerCredential?.credentialIssuer}/.well-known/openid-credential-issuer")

authConfig =
DiscoveryService().getAuthConfig(
"${issuerConfig?.authorizationServer ?: issuerConfig?.issuer}/.well-known/openid-configuration"
)
val wrappedResponse = DiscoveryService().getIssuerConfig("${offerCredential?.credentialIssuer}/.well-known/openid-credential-issuer")
if (wrappedResponse.issuerConfig != null) {
// Handle successful response
issuerConfig = wrappedResponse.issuerConfig
} else {
displayErrorMessage(context, wrappedResponse.errorResponse?.errorDescription)
return@launch
}
val wrappedAuthResponse = DiscoveryService().getAuthConfig(
"${issuerConfig?.authorizationServer ?: issuerConfig?.issuer}/.well-known/openid-configuration"
)
if(wrappedAuthResponse.authConfig !=null){
// Handle successful response
authConfig = wrappedAuthResponse.authConfig
}
else{
displayErrorMessage(context, wrappedAuthResponse.errorResponse?.errorDescription)
return@launch
}

// Generating code verifier
codeVerifier = CodeVerifierService().generateCodeVerifier()

withContext(Dispatchers.Main) {
Expand Down Expand Up @@ -118,18 +135,22 @@ class MainViewModel : ViewModel() {
}
}

private fun displayErrorMessage(context: Context, errorMessage: String?) {
val messageToShow = errorMessage?.takeIf { it.isNotBlank() } ?: "Unknown error"
Toast.makeText(context, messageToShow, Toast.LENGTH_SHORT).show()
isLoading.value = false
}

private suspend fun getCredential() {
val types = IssueService().getTypesFromCredentialOffer(offerCredential)
val format = IssueService().getFormatFromIssuerConfig(issuerConfig, types.lastOrNull() ?:"")

val credential = IssueService().processCredentialRequest(
did,
subJwk,
issuerConfig?.credentialIssuer,
tokenResponse?.tokenResponse?.cNonce,
offerCredential,
issuerConfig?.credentialEndpoint,
issuerConfig,
tokenResponse?.tokenResponse?.accessToken,
format?:"jwt_vc"
format ?: "jwt_vc"
)

withContext(Dispatchers.Main) {
Expand Down
2 changes: 1 addition & 1 deletion eudi-wallet-oidc-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ publishing {
register<MavenPublication>("release") {
groupId = "com.github.decentraliseddataexchange"
artifactId = "eudi-wallet-oidc-android"
version = "2024.5.1"
version = "2024.6.1"

afterEvaluate {
from(components["release"])
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.ewc.eudi_wallet_oidc_android

object CryptographicAlgorithms {
final val ES256 = "ES256"
final val EdDSA = "EdDSA"
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ data class Jwt(

@SerializedName("alg") var alg: ArrayList<String> = arrayListOf()

)
data class WrappedAuthConfigResponse(
var authConfig: AuthorisationServerWellKnownConfiguration? = null,
var errorResponse: ErrorResponse? = null
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package com.ewc.eudi_wallet_oidc_android.models

import com.google.gson.annotations.SerializedName
data class CredentialTypeDefinition(
@SerializedName("type") var type: ArrayList<String>? = arrayListOf()
)

data class AuthorizationDetails(

@SerializedName("type") var type: String? = "openid_credential",
@SerializedName("format") var format: String? = "jwt_vc",
@SerializedName("format") var format: String? = null,
@SerializedName("types") var types: ArrayList<String>? = arrayListOf(),
@SerializedName("locations") var locations: ArrayList<String>? = arrayListOf()
@SerializedName("locations") var locations: ArrayList<String>? = arrayListOf(),
@SerializedName("credential_definition") var credentialDefinition: CredentialTypeDefinition? = CredentialTypeDefinition()

)
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ import com.google.gson.annotations.SerializedName
data class CredentialRequest(

@SerializedName("types") var types: ArrayList<String>? = null,
@SerializedName("credential_definition") var credentialDefinition: CredentialDefinition? = null,
@SerializedName("vct") var vct: String? = null,
@SerializedName("format") var format: String? = null,
@SerializedName("proof") var proof: ProofV3? = null

)

data class CredentialDefinition(
@SerializedName("vct") var vct: String? = null,
@SerializedName("type") var type: ArrayList<String>? = null
)
data class ProofV3(

@SerializedName("proof_type") var proofType: String? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.ewc.eudi_wallet_oidc_android.models

import com.google.gson.annotations.SerializedName

data class DIDDocument(
@SerializedName("@context")
val context: List<String>,

@SerializedName("id")
val id: String,

@SerializedName("controller")
val controller: List<String>,

@SerializedName("verificationMethod")
val verificationMethods: List<VerificationMethod>,

@SerializedName("authentication")
val authentication: List<String>,

@SerializedName("assertionMethod")
val assertionMethods: List<String>,

@SerializedName("capabilityInvocation")
val capabilityInvocations: List<String>
)

data class VerificationMethod(
@SerializedName("id")
val id: String,

@SerializedName("type")
val type: String,

@SerializedName("controller")
val controller: String,

@SerializedName("publicKeyJwk")
val publicKeyJwk: PublicKeyJwk
)

data class PublicKeyJwk(
@SerializedName("kty")
val kty: String,

@SerializedName("crv")
val crv: String,

@SerializedName("x")
val x: String,

@SerializedName("y")
val y: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ data class Filter(

data class Contains(

@SerializedName("const") var const: String? = null

@SerializedName("const") var const: String? = null,
@SerializedName("pattern") var pattern: String? = null,
@SerializedName("type") var type: String? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ data class CredentialsSupported(
@SerializedName("format") var format: String? = null,
@SerializedName("types") var types: ArrayList<String> = arrayListOf(),
@SerializedName("trust_framework") var trustFramework: TrustFramework? = TrustFramework(),
@SerializedName("display") var display: ArrayList<Display> = arrayListOf()
@SerializedName("display") var display: ArrayList<Display> = arrayListOf(),
@SerializedName("cryptographic_suites_supported") var cryptographicSuitesSupported: ArrayList<String> = arrayListOf()
)

data class Display(
Expand All @@ -33,4 +34,8 @@ data class Image(
@SerializedName("uri") var uri: String? = null,
@SerializedName("url") var url: String? = null,
@SerializedName("alt_text") var altText: String? = null
)
data class WrappedIssuerConfigResponse(
var issuerConfig: IssuerWellKnownConfiguration? = null,
var errorResponse: ErrorResponse? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.ewc.eudi_wallet_oidc_android.models

// Data class representing a JSON Web Key (JWK).
data class JwkKey(
val kty: String,
val kid: String,
val crv: String,
val x: String,
val y: String,
val use: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.ewc.eudi_wallet_oidc_android.models

// Data class representing a response containing a list of JSON Web Keys (JWKs).
data class JwksResponse(val keys: List<JwkKey>)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.google.gson.annotations.SerializedName
data class PresentationDefinition(

@SerializedName("id") var id: String? = null,
@SerializedName("name") var name: String? = null,
@SerializedName("format") var format: Map<String, Jwt>? = mapOf(),
@SerializedName("input_descriptors") var inputDescriptors: ArrayList<InputDescriptors>? = arrayListOf()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.ewc.eudi_wallet_oidc_android.models
import com.google.gson.annotations.SerializedName
data class VPTokenResponse(
@SerializedName("location") var location: String? = null,
)

data class WrappedVpTokenResponse(
var vpTokenResponse: VPTokenResponse? = null,
var errorResponse: ErrorResponse? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.ewc.eudi_wallet_oidc_android.services.credentialValidation

import com.ewc.eudi_wallet_oidc_android.services.exceptions.ExpiryException
import com.ewc.eudi_wallet_oidc_android.services.exceptions.SignatureException

class CredentialValidator:CredentialValidatorInterface {

/**
* Validates a JWT credential by checking its expiration and signature.
*
* @param jwt
* @param jwksUri
* @return
*
* Returns true if the JWT is valid; otherwise, throws IllegalArgumentException with appropriate messages.
*/
@Throws(IllegalArgumentException::class)
override suspend fun validateCredential(jwt: String?, jwksUri: String?): Boolean {
try {
// Check if the JWT has expired
ExpiryValidator().isJwtExpired(jwt = jwt)

// Validate the JWT signature using the provided JWKS URI
SignatureValidator().validateSignature(jwt = jwt, jwksUri = jwksUri)

// If both checks pass, return true indicating the credential is valid
return true
} catch (expiryException: ExpiryException) {
// Throw IllegalArgumentException if JWT is expired
throw IllegalArgumentException("JWT token expired")
} catch (signatureException: SignatureException) {
// Throw IllegalArgumentException if JWT signature is invalid
throw IllegalArgumentException("JWT signature invalid")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ewc.eudi_wallet_oidc_android.services.credentialValidation

interface CredentialValidatorInterface {
/**
* Validates a JWT credential by checking its expiration and signature.
*
* @param jwt
* @param jwksUri
* @return
*
* Returns true if the JWT is valid; otherwise, throws IllegalArgumentException with appropriate messages.
*/
@Throws(IllegalArgumentException::class)
suspend fun validateCredential(jwt: String?,jwksUri:String?):Boolean
}
Loading

0 comments on commit 4b5a8d6

Please sign in to comment.