Sphereon-Opensource / SIOP-OID4VP

Self Issued OpenID Provider v2 (SIOP) with optional OpenID for Verifiable Presentations (OpenID4VP)
Apache License 2.0
77 stars 25 forks source link

authorizationRequestPayload.client_id.startsWith is not a function #54

Closed mmatteo23 closed 1 year ago

mmatteo23 commented 1 year ago

Hi all, I was trying your library following your tutorial but I'm stuck at "OP Auth Request verification" point.

I'm using your "@sphereon/did-auth-siop": "^0.3.0" library version.

I was able to create an AuthorizationRequest correctly, obtain the encodedURI and return it.

This is an example:

openid-vc://?request=eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa2poYXJTOXpWRVJmdnQ0Q29Lb1FmUERyd1Q4aGZRRVRQYnhxWThvcVl1SjY0IiwidHlwIjoiSldUIn0.eyJpYXQiOjE2ODQzMTkwMjAsImV4cCI6MTY4NDMxOTE0MCwicmVzcG9uc2VfdHlwZSI6ImlkX3Rva2VuIiwic2NvcGUiOiJvcGVuaWQiLCJjbGllbnRfaWQiOnsiaWRfdG9rZW5fc2lnbmluZ19hbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFZERTQSJdLCJyZXF1ZXN0X29iamVjdF9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkVkRFNBIiwiRVMyNTYiXSwicmVzcG9uc2VfdHlwZXNfc3VwcG9ydGVkIjpbImlkX3Rva2VuIl0sInNjb3Blc19zdXBwb3J0ZWQiOlsib3BlbmlkIGRpZF9hdXRobiIsIm9wZW5pZCJdLCJzdWJqZWN0X3R5cGVzX3N1cHBvcnRlZCI6WyJwYWlyd2lzZSJdLCJzdWJqZWN0X3N5bnRheF90eXBlc19zdXBwb3J0ZWQiOlsiZGlkOmV0aHI6IiwiZGlkOmtleToiLCJkaWQiLCJkaWQ6ZXRociIsImRpZDprZXkiXSwidnBfZm9ybWF0cyI6eyJqd3RfdmMiOnsiYWxnIjpbIkVkRFNBIl19fX0sInJlZGlyZWN0X3VyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODc4Ny9hcGkvb3BlbmlkL0F1dGhSZXF1ZXN0Q2FsbGJhY2siLCJyZXNwb25zZV9tb2RlIjoicG9zdCIsIm5vbmNlIjoiMTExMSIsInN0YXRlIjoiQ3JlYXRlZCIsInJlZ2lzdHJhdGlvbiI6eyJpZF90b2tlbl9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkVkRFNBIl0sInJlcXVlc3Rfb2JqZWN0X3NpZ25pbmdfYWxnX3ZhbHVlc19zdXBwb3J0ZWQiOlsiRWREU0EiLCJFUzI1NiJdLCJyZXNwb25zZV90eXBlc19zdXBwb3J0ZWQiOlsiaWRfdG9rZW4iXSwic2NvcGVzX3N1cHBvcnRlZCI6WyJvcGVuaWQgZGlkX2F1dGhuIiwib3BlbmlkIl0sInN1YmplY3RfdHlwZXNfc3VwcG9ydGVkIjpbInBhaXJ3aXNlIl0sInN1YmplY3Rfc3ludGF4X3R5cGVzX3N1cHBvcnRlZCI6WyJkaWQ6ZXRocjoiLCJkaWQ6a2V5OiIsImRpZCIsImRpZDpldGhyIiwiZGlkOmtleSJdLCJ2cF9mb3JtYXRzIjp7Imp3dF92YyI6eyJhbGciOlsiRWREU0EiXX19fSwiY2xhaW1zIjp7InZwX3Rva2VuIjp7InByZXNlbnRhdGlvbl9kZWZpbml0aW9uIjp7ImlkIjoiMTIzNC0xMjM0LTEyMzQtMTIzNCIsImlucHV0X2Rlc2NyaXB0b3JzIjpbeyJpZCI6IkV4YW1wbGVJbnB1dERlc2NyaXB0b3IiLCJzY2hlbWEiOlt7InVyaSI6Imh0dHBzOi8vZGlkLml0c291cndlYi5vcmc6MzAwMC9zbWFydGNyZWRlbnRpYWwvT250YXJpby1IZWFsdGgtSW5zdXJhbmNlLVBsYW4ifV19XX19fSwibmJmIjoxNjg0MzE5MDIwLCJqdGkiOiJhMjdiOGUzMi04NmRiLTQyY2UtYTg1Yi1kY2ExMWFhZDdhOTQiLCJpc3MiOiJkaWQ6a2V5Ono2TWtqaGFyUzl6VkVSZnZ0NENvS29RZlBEcndUOGhmUUVUUGJ4cVk4b3FZdUo2NCIsInN1YiI6ImRpZDprZXk6ejZNa2poYXJTOXpWRVJmdnQ0Q29Lb1FmUERyd1Q4aGZRRVRQYnhxWThvcVl1SjY0In0.dL7uJfXK-AO_-TYEPxNvK-pcC4UU_Zyqv32p0xUah-VlqOIfrETzZ3h5LqaUJ6dHyNoqgbQgNdB1HKpDKRgEDg

Then when I try to verify it using the method OP.verifyAuthorizationRequest() passing the URI above it gives me this error:

TypeError: authorizationRequestPayload.client_id.startsWith is not a function
    at /node_modules/@sphereon/did-auth-siop/src/authorization-request/Payload.ts:107:45
    at AuthorizationRequest.<anonymous> (/node_modules/@sphereon/did-auth-siop/src/authorization-request/AuthorizationRequest.ts:156:39)

It's a function from Typescript String library, so I don't know what the problem could be. Any ideas?

nklomp commented 1 year ago

Let me setup a test later today. I am assuming that the object is not a string somehow

nklomp commented 1 year ago

Wow, something for sure is wrong with that request: image

Indeed it is an object instead of a string.

Could you happen to provide the input params you used or the builder code you used?

mmatteo23 commented 1 year ago

Thank you @nklomp.

Sure! Here you are.

This is my OP object setup:

OP.builder()
            .withExpiresIn(6000)
            .addDidMethod("ethr")
            .addDidMethod("key")
            .withIssuer(ResponseIss.SELF_ISSUED_V2)
            .withInternalSignature(this._keys.hexPrivateKey, this._keys.did, this._keys.didKey, this._keys.alg)
            .build();

And this is the other one for RP:

RP.builder()
            .withRedirectUri(AuthRequestCallback)
            .withRequestByValue()
            .withRevocationVerification(RevocationVerification.NEVER)
            .withInternalSignature(
                this._keys.hexPrivateKey, 
                this._keys.did,
                this._keys.didKey,
                this._keys.alg
            )
            .addDidMethod("ethr")
            .addDidMethod("key")
            .withSupportedVersions([
                SupportedVersion.JWT_VC_PRESENTATION_PROFILE_v1
            ])
            .withClientMetadata({
                idTokenSigningAlgValuesSupported: [SigningAlgo.EDDSA],
                passBy: PassBy.VALUE,
                requestObjectSigningAlgValuesSupported: [SigningAlgo.EDDSA, SigningAlgo.ES256],
                responseTypesSupported: [ResponseType.ID_TOKEN],
                vpFormatsSupported: { jwt_vc: { alg: [SigningAlgo.EDDSA] } },
                scopesSupported: [Scope.OPENID_DIDAUTHN, Scope.OPENID],
                subjectTypesSupported: [SubjectType.PAIRWISE],
                subject_syntax_types_supported: ["did:ethr:", "did:key:", "did"]
            })
            .withPresentationDefinition({
                definition: {
                    "id": "1234-1234-1234-1234",
                    "input_descriptors": [
                        {
                            "id": "ExampleInputDescriptor",
                            "schema": [
                                {
                                    "uri": "https://did.itsourweb.org:3000/smartcredential/Ontario-Health-Insurance-Plan"
                                }
                            ]
                        }
                    ]
                }
            })
            .build();

Let me know if you need more information

nklomp commented 1 year ago

Thanks that will do. Will have a look at it later today though

nklomp commented 1 year ago

Okay the issue is that it defaults to take the DID supplied as clientId if no clientId is specifically set. It does this after checking the registration metadata. This means in most cases you do not have to set a client_id, as it will pick it up automatically.

However when checking for the registration metadata, it takes the whole registration object instead if the the client_id from the registration object. Given that object will always be filled, even if it does not contain a client_id the DID fallback will never be triggered. Then the JWT generation process simply kicks in and that is happy to encode and sign the whole object. Only on the other side when decoding everything you run into issues, as the client_id is not a string as it should be.

Working on a fix and test. A new version will be released shortly

nklomp commented 1 year ago

0.3.1 has been released fixing the issue. https://github.com/Sphereon-Opensource/SIOP-OID4VP/releases/tag/v0.3.1

Thanks for reporting

mmatteo23 commented 1 year ago

No problem. Thanks to you for the quick fix 💪