Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking Oauth providers while testing

I have an app that I'm writing which authenticates against an Oauth 2.0 authorisation server. I'd like to test the parts that are accessible only after you've logged in but the Oauth server is an external dependency that complicates and make brittle my tests.

Any suggestions on how I should go about this? What the industry practices for something like this? My gut feel is to somehow mock out the server so that it allows access to the protected resources.

In case it matters, this is a Python webapp written using Flask.

I am using a custom oauth server which will run on my own domain and while it's possible to add some kind of sandboxing functionality as FoxMask has suggested, I'd much prefer being able to run the test without requiring an extra server running.

like image 305
Noufal Ibrahim Avatar asked Sep 16 '13 12:09

Noufal Ibrahim


1 Answers

From the consumer (i.e. your application) side, the OAuth2 process can be separated in two parts:

  1. the redirect from your application to the OAuth2 provider's "authorize" URL
  2. the exchange of the "code" returned by the OAuth2 provider for an access token

For #1 all you need to test is that when you invoke the route that starts the authentication process the response returned is a redirect to the OAuth2 provider. This is easily accomplished with Flask's test client. The response should have a status code of 302 and a "Location" header set to the authorize URL for your OAuth2 provider. Note that you do not need to provider to be up, you are just testing that the response is a redirect, but you do not need to actually redirect.

Testing for #2 is a little bit more involved. Your Flask app has a special URL that is designated as the "redirect URL" for the OAuth2 provider to send you back the authorization code. You can just invoke this URL with the Flask test client passing a mock code and that has no issue.

The problem is that in the view function that handles your redirect URL you need to invoke the OAuth2 provider to exchange the auth code for an access token, and this is done synchronously. To prevent this transaction to happen you have to check app.config['TESTING'] and in that case skip the actual request and replace it with a fake response that includes a mock access token.

From then on you will need to also fake any additional calls into the OAuth2 provider that send the access token to request data.

If you are using an OAuth2 client library in your Flask app it may be easier to create the mock provider without having to create testing exceptions in your application. In my case I'm using rauth, and for this I have created a subclass of the OAuth2Service class that overrides the proper methods and responds with mock data that I have captured from a real session. Then in my test setup I just create the mock service and the application is fooled into thinking it is talking to a real server.

I hope this helps.

like image 92
Miguel Avatar answered Oct 15 '22 01:10

Miguel