adrien2p / medusa-plugins

A collection of awesome plugins for medusa :rocket:
https://medusa-plugins.vercel.app
MIT License
157 stars 46 forks source link

TypeError: Cannot read properties of undefined (reading 'id') when integrating Keycloak #157

Closed vholik closed 6 months ago

vholik commented 6 months ago

Im using the latest version of the auth plugin to integrate with Keycloak.

::1 - - [29/Mar/2024:16:57:18 +0000] "GET /admin/auth/oauth2?returnAccessToken HTTP/1.1" 302 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
TypeError: Cannot read properties of undefined (reading 'id')
    at /Users/viktorholik/Desktop/market-api/node_modules/medusa-plugin-auth/core/auth-callback-middleware.js:35:44
    at /Users/viktorholik/Desktop/market-api/node_modules/medusa-plugin-auth/core/passport/utils/auth-routes-builder.js:89:9
    at /Users/viktorholik/Desktop/market-api/node_modules/medusa-plugin-auth/core/passport/utils/auth-routes-builder.js:46:98
    at /Users/viktorholik/Desktop/market-api/node_modules/medusa-plugin-auth/core/auth-callback-middleware.js:15:9
    at /Users/viktorholik/Desktop/market-api/node_modules/medusa-plugin-auth/core/passport/utils/auth-routes-builder.js:70:20
    at strategy.error (/Users/viktorholik/Desktop/market-api/node_modules/passport/lib/middleware/authenticate.js:361:18)
    at /Users/viktorholik/Desktop/market-api/node_modules/passport-oauth2/lib/strategy.js:178:43
    at /Users/viktorholik/Desktop/market-api/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:214:7
    at passBackControl (/Users/viktorholik/Desktop/market-api/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:134:9)
    at IncomingMessage.<anonymous> (/Users/viktorholik/Desktop/market-api/node_modules/passport-oauth2/node_modules/oauth/lib/oauth2.js:157:7)

Here my options in medusa config

{
        resolve: 'medusa-plugin-auth',
        /** @type {import('medusa-plugin-auth').AuthOptions} */
        options: [
            {
                type: 'oauth2',
                strict: 'none',
                identifier: 'oauth2',
                authorizationURL: 'https://.../realms/master/protocol/openid-connect/auth',
                tokenURL: 'http://.../auth/realms/master/protocol/openid-connect/token',
                clientID: OAuth2ClientId,
                clientSecret: OAuth2ClientSecret,
                scope: OAuth2Scope.split(','),
                admin: {
                    callbackUrl: `${BACKEND_URL}/admin/auth/oauth2/cb`,
                    failureRedirect: `${ADMIN_URL}/login`,
                    successRedirect: `${ADMIN_URL}/`,
                },
                store: {
                    callbackUrl: `${BACKEND_URL}/store/auth/oauth2/cb`,
                    failureRedirect: `${STORE_URL}/login`,
                    successRedirect: `${STORE_URL}/`,
                },
                parseProfile: (json) => {
                    const profile = {
                        provider: 'keycloak',
                        id: json.sub,
                        username: json.preferred_username,
                        displayName: json.name,
                        email: json.email,
                        name: {
                            familyName: json.family_name,
                            givenName: json.given_name,
                        },
                        emails: json.email
                            ? [
                                    {
                                        value: json.email,
                                    },
                              ]
                            : [],
                        _json: json,
                        phoneNumbers: json.phone_number
                            ? [
                                    {
                                        value: json.phone_number ?? '',
                                    },
                              ]
                            : [],
                    };

                    return profile;
                },
            },
        ],
    },

This function causes the problem because req.user is undefined. Adding ?returnAccessToken doesn't change error message.

adrien2p commented 6 months ago

@sl1mpshady could you maybe have a look please?

sl1mpshady commented 6 months ago

Was able to reproduce the issue. I found out this error if

Kindly check your client secret from the keycloak client settings to verify if it's correct

image
sl1mpshady commented 6 months ago

@sl1mpshady could you maybe have a look please?

The package is expecting to always have the user after login but on this case when the client secret is wrong it was not able to get the profile. might be best to add an error handler on this part and redirect back the user to login page with error. WDYT @adrien2p

adrien2p commented 6 months ago

If the secret is wrong, what is its content when we receive it? I would have thought that the parsing would have failed from there no?

sl1mpshady commented 6 months ago

I tried using the old version and the default oauth2 is returning the same issue so it was not handled maybe

vholik commented 6 months ago

Thanks for help. Actually the client secret was correct. Incorrect was a tokenURL.

Incorrect: http://.../auth/realms/master/protocol/openid-connect/token. Correct: https://.../realms/master/protocol/openid-connect/token

sl1mpshady commented 6 months ago

I will add an error handling for this @adrien2p. instead of not showing anything, we redirect the user back to the login with the error message thrown by passport