[go: nahoru, domu]

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

feat(auth): Add auth emulator support via the FIREBASE_AUTH_EMULATOR_HOST environment variable. #531

Merged
merged 5 commits into from
Mar 23, 2021

Conversation

muru
Copy link
Contributor
@muru muru commented Feb 5, 2021

Discussion

Closes #503, by adding support for the authentication emulator via the FIREBASE_AUTH_EMULATOR_HOST environment variable.

Additionally, I added a change that shouldn't break anything, but does make the SDK work better with the emulator, fixing the equivalent of firebase/firebase-admin-node#1084. I ran into this while testing these changes in a project, and I feel it should be part of "supporting" the emulator, but I am open to putting it in a separate PR if it doesn't belong.

Testing

  • Existing tests pass
  • Modified the existing tests for user management, token generation and providers to run for both emulated and non-emulated cases.

API Changes

None, except insofar that the FIREBASE_AUTH_EMULATOR_HOST environment variable becomes part of the API.

Copy link
Member
@yuchenshi yuchenshi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach looks right to me, although we should also handle verifying ID tokens and session cookies.

@yuchenshi
Copy link
Member

cc @brianrodri who may be interested in this.

@muru
Copy link
Contributor Author
muru commented Feb 11, 2021

@yuchenshi At the time I started work on this I thought the Google people were going to rework how those are handled. Now that the firebase CLI is supposed to work OK with session cookies, I'll try to include it in integration tests (which I'd held off on) and see what else needs to be fixed here.

@yuchenshi
Copy link
Member

@yuchenshi At the time I started work on this I thought the Google people were going to rework how those are handled. Now that the firebase CLI is supposed to work OK with session cookies, I'll try to include it in integration tests (which I'd held off on) and see what else needs to be fixed here.

I really appreciate it. firebase/firebase-admin-node#1148 has some integration tests that you can draw inspiration from and it shows the desired behavior for verifying ID tokens.

Copy link
Contributor
@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @muru. Looks mostly good. I've pointed out a few things that can be improved.

firebase_admin/_auth_client.py Outdated Show resolved Hide resolved
firebase_admin/_auth_client.py Outdated Show resolved Hide resolved
firebase_admin/_auth_client.py Outdated Show resolved Hide resolved
firebase_admin/_token_gen.py Outdated Show resolved Hide resolved
tests/testutils.py Outdated Show resolved Hide resolved
@hiranya911 hiranya911 assigned muru and unassigned hiranya911 Feb 11, 2021
@hiranya911 hiranya911 changed the title Add auth emulator support via the FIREBASE_AUTH_EMULATOR_HOST environment variable. feat(auth): Add auth emulator support via the FIREBASE_AUTH_EMULATOR_HOST environment variable. Feb 11, 2021
@Keramblock
Copy link

@muru sorry for disturbance, but could you please take a look? I really wait for that MR =)

@muru muru force-pushed the add-auth-emulator-support branch 2 times, most recently from 26132bc to 0586230 Compare February 24, 2021 12:06
@muru
Copy link
Contributor Author
muru commented Feb 24, 2021

@Keramblock thanks for the nudge. I have fixed the issues noted by @hiranya911 , but haven't gotten the integration tests to work. I'll try those again over the weekend.

Copy link
Contributor
@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the way credentials are being used is still not quite correct. But overall looks pretty good.

firebase_admin/_auth_client.py Outdated Show resolved Hide resolved
firebase_admin/_auth_client.py Outdated Show resolved Hide resolved
firebase_admin/_token_gen.py Outdated Show resolved Hide resolved
firebase_admin/_auth_client.py Show resolved Hide resolved
@muru muru force-pushed the add-auth-emulator-support branch 8 times, most recently from d5020ef to 0720435 Compare February 28, 2021 14:19
@hiranya911
Copy link
Contributor

@muru the last set of commits have broken the CI. I'd recommend reverting the breaking commits, and doing the bare minimal necessary to address the earlier code review feedback. Any other new capabilities (e.g. emulator based testing), can be implemented in separate future PRs.

@muru
Copy link
Contributor Author
muru commented Mar 4, 2021

@hiranya911 porting the token verification code from firebase/firebase-admin-node#1148 breaks a few unit tests. Since that should probably be included with this PR, would it be fine if I marked those tests for skipping when tested with the emulator? And while I am it, I could do the same for integration tests too.

@hiranya911
Copy link
Contributor

Ideally we shouldn't have to skip any unit tests.

We can live without emulator-based integration tests for now (that work is on hold in Node.js at firebase/firebase-admin-node#1155 due to some problems).

@muru muru force-pushed the add-auth-emulator-support branch 3 times, most recently from 17e28e6 to 14d1c01 Compare March 5, 2021 04:47
Copy link
Contributor
@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not implement integration testing for emulator mode yet. Lets focus on getting the implementation and the unit tests absolutely correct.

firebase_admin/_token_gen.py Outdated Show resolved Hide resolved
firebase_admin/_token_gen.py Outdated Show resolved Hide resolved
integration/test_auth.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
.github/workflows/ci.yml Outdated Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
@muru
Copy link
Contributor Author
muru commented Mar 5, 2021

@hiranya911 what you say is correct, but shouldn't matter here, since emulation is set in the second/final iteration (https://github.com/firebase/firebase-admin-python/pull/531/files#diff-81622636c5d10b6ab40396c608887473086a43b94621195117193ab81a4b5cdaR166 - emulated is False first, then True).

These tests broke due to the changes made to token validation to fit the emulator (aacd27f) - they were supposed to raise an exception but didn't. Note that all tests ran perfectly fine before that.

@hiranya911
Copy link
Contributor
hiranya911 commented Mar 5, 2021

I'm debugging the tests in your branch and I can clearly see that tests that shouldn't be running in the emulator mode, picking up the emulator mode from another fixture. The test case test_noncert_credential[user_mgt_app0] should pass by raising the expected error, but it doesn't because it sees the env variable set in a different fixture (i.e. the auth_app fixture), and goes into the emulator mode. The order of events observed is something like:

auth_app fixture initialized with emulated = False
  all tests that depend on auth_app runs
auth_app fixture cleaned up
auth_app fixture initialized with emulated = True
  all tests that depend on auth_app runs
user_mgt_app fixture initialized with emulated = False
  all tests that depend on user_mgt_app runs (These tests see the env variable set by auth_app, since it's not cleaned up yet)
user_mgt_app fixture cleaned up
user_mgt_app fixture initialized with emulated = True
  all tests that depend on user_mgt_app runs
user_mgt_app fixture cleaned up
auth_app fixture cleaned up

Basically we can no longer reason about when a test case may or may not see the env variable, since other fixtures may be running in the background, waiting to be cleaned up at the end of the module.

@muru
Copy link
Contributor Author
muru commented Mar 5, 2021

Ah, I hadn't noticed that, thanks! I'll look into how that can be fixed - maybe have an existing value of the environment variable override the fixture parameters.

@hiranya911
Copy link
Contributor

I think the easiest solution would be to change the fixture scope to function (which is also pytest default). That will cause a new app and a monkeypatch instance to be created per test function, and they will get cleaned up immediately after. App initialization and clean up are pretty cheap operations, so it should be ok in terms of speed.

@hiranya911
Copy link
Contributor

With function-scoped fixtures (plus a few other minor modifications), these are all the remaining test failures:

FAILED tests/test_token_gen.py::TestCreateCustomToken::test_noncert_credential[user_mgt_app1] - Failed: DID NOT RAISE <class 'ValueError'>
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_revoked_token_check_revoked[user_mgt_app1-BinaryToken] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.Revoke...
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_revoked_token_check_revoked[user_mgt_app1-TextToken] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.RevokedI...
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_invalid_token[user_mgt_app1-NoKid] - Failed: DID NOT RAISE <class 'firebase_admin._auth_utils.InvalidIdTokenError'>
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_invalid_token[user_mgt_app1-WrongKid] - Failed: DID NOT RAISE <class 'firebase_admin._auth_utils.InvalidIdTokenError'>
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_invalid_token[user_mgt_app1-FutureToken] - Failed: DID NOT RAISE <class 'firebase_admin._auth_utils.InvalidIdTokenError'>
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_invalid_token[user_mgt_app1-ExpiredToken] - Failed: DID NOT RAISE <class 'firebase_admin._auth_utils.InvalidIdTokenError'>
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_expired_token[user_mgt_app1] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.ExpiredIdTokenError'>
FAILED tests/test_token_gen.py::TestVerifyIdToken::test_certificate_request_failure[user_mgt_app1] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.CertificateFetchEr...
FAILED tests/test_token_gen.py::TestVerifySessionCookie::test_invalid_cookie[user_mgt_app1-NoKid] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.InvalidSessionCooki...
FAILED tests/test_token_gen.py::TestVerifySessionCookie::test_invalid_cookie[user_mgt_app1-WrongKid] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.InvalidSessionCo...
FAILED tests/test_token_gen.py::TestVerifySessionCookie::test_invalid_cookie[user_mgt_app1-FutureCookie] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.InvalidSessi...
FAILED tests/test_token_gen.py::TestVerifySessionCookie::test_invalid_cookie[user_mgt_app1-ExpiredCookie] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.InvalidSess...
FAILED tests/test_token_gen.py::TestVerifySessionCookie::test_expired_cookie[user_mgt_app1] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.ExpiredSessionCookieError'>
FAILED tests/test_token_gen.py::TestVerifySessionCookie::test_certificate_request_failure[user_mgt_app1] - Failed: DID NOT RAISE <class 'firebase_admin._token_gen.CertificateF...
FAILED tests/test_token_gen.py::TestCertificateCaching::test_certificate_caching[user_mgt_app1] - assert 0 == 1

It's unfortunate our implementation doesn't handle expired emulated tokens correctly (this is because we bypass the JWT verification step entirely for emulated tokens). But this might be ok. I'm fine with skipping the above tests if we must.

@muru muru force-pushed the add-auth-emulator-support branch 3 times, most recently from b7601f6 to b779263 Compare March 12, 2021 15:23
@muru
Copy link
Contributor Author
muru commented Mar 12, 2021

@hiranya911 I removed the integration test and modified the fixtures to use the function scope, and where possible, I modified the tests to account for the current behaviour of the emulator mode instead of skipping them. If the emulator mode is improved, that might help prevent tests from being overlooked due to being skipped.

Also, I opted against using a module-level variable for _auth_utils.is_emulated() as it behaves like module fixture when a variable, causing test failures. Is that fine?

Copy link
Contributor
@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes @muru. I think this looks pretty reasonable. I've left some comments on how to further clean up and reduce some of the code duplication.

tests/test_token_gen.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
@muru muru force-pushed the add-auth-emulator-support branch 5 times, most recently from 1d817f5 to 7183f67 Compare March 16, 2021 03:07
@muru muru requested a review from hiranya911 March 16, 2021 03:08
Copy link
Contributor
@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @muru. This looks great! I only had a few minor comments, and we can merge once those are addressed.

firebase_admin/_token_gen.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
tests/test_token_gen.py Outdated Show resolved Hide resolved
tests/test_user_mgt.py Outdated Show resolved Hide resolved
To minimize modification of tests, the app fixture and instrumentation
have been modified to use a global dict of URLs, which are then
monkey-patched based on fixture parameters. Essentially, all tests using
the app fixture are run twice, once with the emulated endpoint and once
without.
@muru muru force-pushed the add-auth-emulator-support branch from 7183f67 to ba9196f Compare March 20, 2021 03:07
Where possible, tests are modified to account for the current behaviour
in emulator mode (e.g., invalid or expired tokens or cookies still
work).

Fixtures were changed to function scope to avoid problems caused by
overlap when some fixtures being in emulator mode and some in normal
mode concurrently.
@muru muru force-pushed the add-auth-emulator-support branch from ba9196f to 1e65c84 Compare March 22, 2021 02:31
Copy link
Contributor
@hiranya911 hiranya911 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @muru for patiently working through all the comments. This LGTM 👍

@hiranya911 hiranya911 assigned hiranya911 and unassigned muru Mar 23, 2021
@hiranya911 hiranya911 merged commit 04c4069 into firebase:master Mar 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

FR: Support for authentication emulator
4 participants