Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: authenticate not called when deploying in the cloud #16020

Open
supersilverlemonhaze opened this issue May 20, 2024 · 1 comment
Open

Bug: authenticate not called when deploying in the cloud #16020

supersilverlemonhaze opened this issue May 20, 2024 · 1 comment

Comments

@supersilverlemonhaze
Copy link

supersilverlemonhaze commented May 20, 2024

What are you trying to achieve?

This issue is regarding your PLUGINS. Note: I know you want to deprecate plugins. HOWEVER: You do not provide any means to customize things like authentication, be it even with APPS, that you try to push for. For my application I need to have Mobile Phone Auth. We are close to MVP and production, PLEASE even if you dont want to fix anything, just provide me an Info on why I have this behavior.

I wrote a Firebase Auth plugin, it overrides the authenticate_user method, that just takes the HTTP_AUTHORIZATION header, decodes it and gets or creates a user with available info from the JWT.

Constructor and authenticate method are both encapsulated by try, except and corresponding logging at beginning and end. So there is no way, in which authenticate is called, but I dont receive a single Log. However this is exactly what happens (more on this later).
Plugin Constructor:

def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.logger = logging.getLogger(__name__)
        [self.logger.info](http://self.logger.info/)("TRYING TO INITIALIZE FIREBASE")
        try:
            json_str = settings.FIREBASE_CONFIG
            cred_dict = json.loads(json_str)
            cred = credentials.Certificate(cred_dict)
            self.client = fa.get_app(__name__)
            print("ALREADY INITIALIZED")
        except:
            [self.logger.info](http://self.logger.info/)("BEFORE INITIALIZE APP")
            self.client = fa.initialize_app(credential=cred, name=__name__)
            [self.logger.info](http://self.logger.info/)("INITIALIZED APP SUCCESSFULLY")

Plugin authenticate_user Method:

def authenticate_user(self, request: WSGIRequest, previous_value) -> Optional[User]:
        # if True:
        try:
            [self.logger.info](http://self.logger.info/)("[+] FIREBASE HEADERS: " + str(request.META))
            token = request.META["HTTP_AUTHORIZATION"]
            [self.logger.info](http://self.logger.info/)("[+] FIREBASE TOKEN ENCODED: " + token)
            if token == "DEBUG_USER":
                return self.get_debug_user()
            decoded_jwt = auth.verify_id_token(token.split(" ")[1], app=self.client, clock_skew_seconds=60)
            [self.logger.info](http://self.logger.info/)("[+] FIREBASE TOKEN DECODED " + str(decoded_jwt))
            if self.is_valid(decoded_jwt):
                # get or create user from decoded_jwt
                user = self.get_or_create_user_from_payload(decoded_jwt)
                [self.logger.info](http://self.logger.info/)(f"FIREBASE USER AUTHENTICATED: {decoded_jwt['uid']}")
                [self.logger.info](http://self.logger.info/)(f"RETRIEVED USER: {str(user.private_metadata)}")
                return user
            raise Exception("INVALID TOKEN")
        except Exception as e:
            self.logger.warning(f"[!] FIREBASE AUTH: {e} RETURNING previous_value")
            self.logger.warning(str(e))
            self.logger.error(f"[!] FIREBASE AUTH: {e} RETURNING previous_value")
            self.logger.error(str(e))
            return previous_value
        return previous_value

When running locally my requests are correctly authenticated as you can see in the logs:
AT LEAST AUTHENTICATE METHOD IS BEING CALLED AT ALL.

2024-05-20 09:23:45,412 INFO saleor.plugins.firebase_auth.plugin [+] FIREBASE HEADERS: {'REQUEST_METHOD': 'POST', 'QUERY_STRING': '', 'SCRIPT_NAME': '', 'PATH_INFO': '/graphql/', 'wsgi.multithread': True, 'wsgi.multiprocess': True, 'REMOTE_ADDR': '172.24.0.1', 'REMOTE_HOST': '172.24.0.1', 'REMOTE_PORT': 35522, 'SERVER_NAME': '172.24.0.7', 'SERVER_PORT': '8000', 'HTTP_HOST': 'localhost:8000', 'HTTP_CONNECTION': 'keep-alive', 'CONTENT_LENGTH': '1121', 'HTTP_SEC_CH_UA': '"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"', 'HTTP_ACCEPT': '/', 'CONTENT_TYPE': 'application/json', 'HTTP_SEC_CH_UA_MOBILE': '?0', 'HTTP_AUTHORIZATION': 'Bearer REDACTED', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', 'HTTP_SEC_CH_UA_PLATFORM': '"macOS"', 'HTTP_ORIGIN': 'http://localhost:51598/', 'HTTP_SEC_FETCH_SITE': 'same-site', 'HTTP_SEC_FETCH_MODE': 'cors', 'HTTP_SEC_FETCH_DEST': 'empty', 'HTTP_REFERER': 'http://localhost:51598/', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br, zstd', 'HTTP_ACCEPT_LANGUAGE': 'en-GB,en-US;q=0.9,en;q=0.8'} [PID:2402:ThreadPoolExecutor-0_0]
2024-05-20 09:23:45,412 INFO saleor.plugins.firebase_auth.plugin [+] FIREBASE TOKEN ENCODED: Bearer REDACTED [PID:2402:ThreadPoolExecutor-0_0]
2024-05-20 09:23:45,415 INFO saleor.plugins.firebase_auth.plugin [+] FIREBASE TOKEN DECODED {'iss': 'https://securetoken.google.com/---', 'aud': 'xxxx', 'auth_time': 1716197002, 'user_id': 'REDACTED', 'sub': 'REDACTED', 'iat': 1716197025, 'exp': 1716200625, 'phone_number': '+REDACTED', 'firebase': {'identities': {'phone': ['+REDACTED']}, 'sign_in_provider': 'phone'}, 'uid': 'REDACTED'} [PID:2402:ThreadPoolExecutor-0_0]
2024-05-20 09:23:45,417 INFO saleor.plugins.firebase_auth.plugin FOUND USER: 45 [PID:2402:ThreadPoolExecutor-0_0]
2024-05-20 09:23:45,418 INFO saleor.plugins.firebase_auth.plugin FIREBASE USER AUTHENTICATED: REDACTED[PID:2402:ThreadPoolExecutor-0_0]
2024-05-20 09:23:45,418 INFO saleor.plugins.firebase_auth.plugin RETRIEVED USER: {'phone_number': '+REDACTED', 'uid-metadata': 'REDACTED'} [PID:2402:ThreadPoolExecutor-0_0]

When running in the cloud behind SSL the authenticate method isnt even called!
Other plugins work just fine. You can see in the logs, that it initializes the plugin multiple times without errors. only the authenticate method is simply not called. I tried to shuffle the order of plugins making my firebase auth plugin the first in the list, second, last and so on.

Please some of the Saleor Devs:
Do you have a clue why authentication would behave differently depending on where it is deployed, eg. different ENV vars such as DEBUG=False, PUBLIC_URL etc.??

Thanks in advance!

Steps to reproduce the problem

Read above

What did you expect to happen?

That it works more or less like locally

Logs

No response

Environment

Saleor version: 3.19
OS and version: built on top of your saleor:3.19 image

@korycins
Copy link
Member

Hey @supersilverlemonhaze
I don't think that there is any logic on Saleor side that could modify the behavior of your plugin 🤔

Here are some hints that I would try to do to investigate a problem:

  • Confirm that the settings.py that are used on your cloud have defined your plugin
  • Confirm that PluginsManager after initialization has info about your plugin (you can do that by adding simple logger to PluginsManager.init)
  • Confirm that your plugin is set to active on cloud - by default the plugins that are not active will be skipped when calling authenticate_user.
  • If you suspect that this can be related to SSL, I would try to reproduce it locally by using ngrok, and setting the ngrok's URL as Saleor's domain (something like /manage.py set_default_site --name test12 --domain 9830-79-191-57-66.ngrok-free.app)
  • Try to add some logger to: saleor.core.auth_backend.JSONWebTokenBackend.authenticate, and saleor.core.auth_backend.PluginBackend.authenticate to check what value is returned there.
  • If you have an active OIDCPlugin, I would try to turn it off temporarily.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants