Automated API testing of OAuth2/OpenID Connect protected API
Asked Answered
V

1

24

I'm looking into a new project that we are planning on doing API first, so that we can then implement web- and native- apps on top of, plus allow for third party integration. All fairly standard so far.

We also want to have a full suite of automated tests for the API, both to ensure that it works without regressions, and to ensure it meets the requirements. Again, fairly standard, but because we are testing the API we will be using an in-code HTTP client and not a web browser.

We have been looking at oauth2/OpenID Connect to facilitate authentication and authorisation for the API - basically so clients can authenticate, get an access token and then use that to access all of the API resources.

What I'm struggling to work out is a good way of getting the automated tests to work with the oauth2 part to be able to actually call the API. The first thought was to use the "client_credentials" or the "password" grant types, which both seem like they would work for what we want, but they're not covered in the OpenID Connect spec at all, and of course the"password" one at least it's generally not considered a good idea anyway.

Is this the best way to achieve this or are there other best practices for this kind of situation that can be used with the other flows, but without a web browser?

Edit: after (much) more reading, I have a new plan. Running tests entirely offline, using a separate deployment against a separate database and seeding data directly into the database before the tests run, and then using the standard OpenID Connect flows, but with:

  • A client that is marked in the database as for testing purposes. This is an important bit, and is only possible if the client can be registered direct into the database without going through business logic.
  • prompt=none
  • login_hint=the user name to get an access token for
  • scope containing "testing"

The system can then detect this combination of facts, and auto authenticate the provided username without needing to go through a browser.

Does this seem reasonable? Or is there a better way?

Viscountcy answered 27/8, 2016 at 10:19 Comment(5)
Have you tried the OpenID Connect certification tool provided by the OpenID Foundation?Clemenceau
My understanding is that this is for testing the OpenID Connect services themselves, whereas I'm more interested in testing the other API services that are to be produced and protected behind the OAuth2 / OpenID Connect Access Tokens, which means that in order to call them I need some way of obtaining valid Access Tokens programatically.Viscountcy
I don't understand how creating a special testing user is secure? What if someone gets access to your test environment, or figures out how to create a test user on production? It doesn't seem like the right solution to me.Precess
I should clarify (I just did in my post). My E2E Tests are running against a version of the webapp running in-process, which itself runs against a database that is running in-process, and the test process seeds data directly into the database before tests run and can verify it afterwards if necessary. I'm using Java and Maven, so I'm running the webapp with the maven-cargo-plugin and starting a database using the embedmongo-maven-plugin for the webapp to talk to. There needs never be a way for anyone to create users with this special flag through any normal means, so that's less of a risk.Viscountcy
Ok, that makes sense. In our case, we have a production-like UAT environment on which we'd like to run our end-to-end tests. Up until last week we were using a work around that allowed us to obtain a Google OAuth token which unfortunately has stopped working. It would be good to know what the right solution is for us.Precess
C
13

Since you're looking to test the API, it should not matter how you got the access_token, through the browser or through some other way. So there are (at least) two solutions:

  1. That other way could be the client_credentials grant. You will have to make the Authorization Server return an access_token that resembles an access_token that would be returned for a user in an OpenID Connect flow through the browser but depending on your AS implementation that should be doable.

  2. Bootstrap your client using a regular OpenID Connect browser flow to generate a refresh_token alongside of an access_token and store both tokens with your test client together with the client_id and client_secret at configuration time. Your test client can then access the APIs until the access token expires and subsequently get a new access_token through the refresh_token grant type (leveraging the client_id and client_secret).

OpenID Connect itself, the user authentication and the id_token are irrelevant to your APIs that should care about the access_token only.

Classical answered 1/9, 2016 at 15:38 Comment(1)
To elaborate on solution 1: create a test client and add all the claims required to pass authorization requirements for the endpoint. If this checks for a 'sub' claim, add a claim to the test client named 'sub', which is often required as only user authentication using oidc would generate the sub.Chrysarobin

© 2022 - 2024 — McMap. All rights reserved.