Colin-b / requests_auth

Authentication classes to be used with requests
MIT License
35 stars 13 forks source link

How can I mock the authentication flow in tests? #69

Closed CeeBeeCee closed 8 months ago

CeeBeeCee commented 2 years ago

Hi @Colin-b ,

First of all, thank you for creating this library that makes it so easy to incorporate the PKCE flow! I'm using this library for a Python Windows desktop app that authenticates with Okta via the PKCE flow. I'm now trying to write integration tests but the issue is that I need to pass in test user credentials instead of using the browser for IWA. Is there a way to achieve this? I am able to call /api/v1/authn with the credentials and get a session token and am at a loss on how to use it to get the auth code bypassing browser auth.

Let me know if there is a way to do that.

Thanks

Colin-b commented 2 years ago

Hello @CeeBeeCee ,

Thanks for the kind word. Yes there is a way to provide your custom token for test purpose.

You can use the token_cache_mock pytest fixture.

As said in documentation, by default, an access token with value 2YotnFZFEjr1zCsicMWpAA is generated.

You can however return your custom token by providing your own token_mock fixture as in the following sample:

import pytest

from requests_auth.testing import token_cache_mock

@pytest.fixture
def token_mock() -> str:
    return "MyCustomTokenValue"

def test_something(token_cache_mock):
    # perform code using authentication
    pass

I hope this is what you were looking for? Feel free to close the issue if this solves it.

Best Regards

CeeBeeCee commented 2 years ago

@Colin-b : I was looking to run integration tests, not mock/unit tests. So I need to hit the actual API endpoints and to do that I need to generate actual tokens from Okta and send them in my requests.get and request.put calls. Since my tests run on a Linux docker image, this part of the code doesnt work since there is no web browser. So my question is, "Is there a way to bypass browser auth and get the tokens by alternate means like requests.get/post?

    browser = (
        webbrowser.get(webbrowser.iexplore)
        if hasattr(webbrowser, "iexplore")
        else webbrowser.get()
    )
Colin-b commented 2 years ago

Ah I see, so this is not related at all to testing per se.

What you want is to be able to use Authorization code with PKCE flow, but without a webbrowser.

As you can see in this module code, there is already a best effort fallback behavior trying out a HTTP GET request.

But as user interaction is expected to be part of the flow, I don't think your use case would work anyway as the flow is not a simple client-server response. Instead it is:

Client (your app, this module) opens a browser on https://the_auth_server (whatever authority you are using) and specify a parameter named redirect_uri. Usually a bunch of redirects are performed before the actual token (or code) is returned to the redirect_uri.

If you don't use a browser, there will be no interpretation of the javascript contained in the initial response, so you will not have any redirection, meaning nothing will be received on the redirect_uri.

However your provider might work a bit differently, and maybe there is some parameter you could work with? If you add logging configuration, you will be able to track what is actually performed by this module. Could you tell me what is the result of the HTTP GET requests that are issued?

Colin-b commented 8 months ago

No response received. Closing. Feel free to reopen with more details if you need it.