Add an optional authentication mode for HTTP resources#58589
Add an optional authentication mode for HTTP resources#58589mshustov merged 33 commits intoelastic:masterfrom
Conversation
src/core/server/http/http_server.ts
Outdated
| private getAuthOption( | ||
| authRequired: RouteConfigOptions<any>['authRequired'] = true | ||
| ): false | { mode: 'required' | 'optional' } { | ||
| if (this.authRegistered) { |
There was a problem hiding this comment.
It sets mode explicitly. I had to change the logic to inline it with mode: optional declaration since it cannot be used without auth strategy registration. the previous implementation relies on the internal hapi logic that true === undefined.
| expect(response.header['www-authenticate']).toBe(authResponseHeader['www-authenticate']); | ||
| }); | ||
|
|
||
| it('attach security header to not handled auth response', async () => { |
There was a problem hiding this comment.
duplicates tests in src/core/server/http/integration_tests/router.test.ts should I remove them?
There was a problem hiding this comment.
One seems enough. Not sure in which file it makes more sense to keep it though. There seems to be overlapping 'coverage' between the two test files.
| const authOptions = request.route.settings.auth; | ||
| if (typeof authOptions === 'object') { | ||
| // 'try' is used in the legacy platform | ||
| if (authOptions.mode === 'optional' || authOptions.mode === 'try') { |
There was a problem hiding this comment.
It will throw en exception in case of try after the migration is done. I decided to add an exhaustive check to catch the options introduced in the new hapi versions if any.
|
Pinging @elastic/kibana-platform (Team:Platform) |
|
@elasticmachine merge upstream |
pgayvallet
left a comment
There was a problem hiding this comment.
Implementation looks good to me.
There was a problem hiding this comment.
NIT: why remove the prefix here?
| expect(response.header['www-authenticate']).toBe(authResponseHeader['www-authenticate']); | ||
| }); | ||
|
|
||
| it('attach security header to not handled auth response', async () => { |
There was a problem hiding this comment.
One seems enough. Not sure in which file it makes more sense to keep it though. There seems to be overlapping 'coverage' between the two test files.
There was a problem hiding this comment.
Are the result && really needed? It seems result should not be false-ish with current typing?
There was a problem hiding this comment.
I guess that's because we're receiving result from auth hook handler that can return whatever it wants? Then probably result?.type would be better since isNotHandled would always return boolean and not falsy value of result.
There was a problem hiding this comment.
right. this API can be called from js code
|
ACK: will review tomorrow morning, sorry for the delay |
| type: AuthResultType.notHandled, | ||
| }; | ||
| }, | ||
| redirected(headers: { location: string } & ResponseHeaders): AuthResult { |
There was a problem hiding this comment.
Has our convention been to use lowercase header names? Really just asking for my own education.
There was a problem hiding this comment.
I don't remember we ever discussed it
| describe('Options', () => { | ||
| describe('authRequired', () => { | ||
| describe('optional', () => { | ||
| it('User has access to a route if auth mechanism not registered', async () => { |
There was a problem hiding this comment.
Should we verify the value of context.auth.isAuthenticated in these tests?
There was a problem hiding this comment.
we have separate tests for them, but it doesn't hurt since here we can verify:
- a route was hit
- auth API returns a correct result
|
ACK: reviewing... |
azasypkin
left a comment
There was a problem hiding this comment.
LGTM. Tested locally with login route - seems to work as expected, thanks!
* add authRequred: 'optional' * expose auth status via request context * update security plugin to use notHandled auth outcome * capabilities service uses optional auth * update tests * attach security headers only to unauthorised response * add isAuthenticated tests for 'optional' auth mode * security plugin relies on http.auth.isAuthenticated to calc capabilities * generate docs * reword test suit names * update tests * update test checking isAuth on optional auth path * address Oleg comments * add test for auth: try * fix * pass isAuthenticted as boolean via context * remove response header from notHandled * update docs * add redirected for auth interceptor * security plugin uses t.redirected to be compat with auth: optional * update docs * require location header in the interface * address comments #1 * declare isAuthenticated on KibanaRequest * remove auth.isAuthenticated from scope * update docs * remove unnecessary comment * do not fail on FakrRequest * small improvements
💚 Build SucceededHistory
To update your PR or re-run it, just comment with: |
* add authRequred: 'optional' * expose auth status via request context * update security plugin to use notHandled auth outcome * capabilities service uses optional auth * update tests * attach security headers only to unauthorised response * add isAuthenticated tests for 'optional' auth mode * security plugin relies on http.auth.isAuthenticated to calc capabilities * generate docs * reword test suit names * update tests * update test checking isAuth on optional auth path * address Oleg comments * add test for auth: try * fix * pass isAuthenticted as boolean via context * remove response header from notHandled * update docs * add redirected for auth interceptor * security plugin uses t.redirected to be compat with auth: optional * update docs * require location header in the interface * address comments #1 * declare isAuthenticated on KibanaRequest * remove auth.isAuthenticated from scope * update docs * remove unnecessary comment * do not fail on FakrRequest * small improvements
* master: (154 commits) Add an optional authentication mode for HTTP resources (elastic#58589) Implement embeddable drilldown menu options (elastic#59232) [Alerting] "Create alert" graph visualization design improvements (elastic#59399) Alerting update route throttle property is missing (elastic#59580) [SIEM] Adds 'Load prebuilt rules' Cypress test (elastic#59529) Show error if field is not found during filter rendering (elastic#59298) Navigate back to discover app during test, because the saved search from the preceding test has major performance problems when used with this test (elastic#59571) Check for alert dialog when doing a force logout (elastic#59329) ensure fs deletes are not cwd dependent (elastic#59570) Empty message for APM service map (elastic#59518) [Drilldowns] <ActionWizard/> Component (elastic#59032) [Reporting] Improve the page exit error messages (elastic#59351) Ensure logged out starting state for tests that need it (elastic#59322) Hide input value from kbn-config-schema error messages (elastic#58843) [ML] Transforms: Migrate client plugin to NP. (elastic#59443) [ML] Disable failing functional tests [SIEM] Update Timeline to use the latest euiFlyoutBody style (elastic#59524) Temporarily remove the project mappings for PR labels (elastic#59493) [Alerting] replace index threshold graph usage of watcher APIs with new API (elastic#59385) [ML] Show view series link in anomalies table for machine_learning_user role (elastic#59549) ...
Summary
closes #41959
The current PR adds
optionalauthentication mode for HTTP resources that acts similarly tooptionalmode in hapi https://hapi.dev/api/?v=17.9.2#-routeoptionsauthmodeFor this, I added the
notHandledoutcome for the auth interceptor. Getting it from auth hook, Kibana server behaves differently:optionalauthentication mode, allows an user to access a resourcerequiredauthentication mode (default behavior), the Kibana server responds with theunauthorizedresponse.All other cases, such as handling redirection to 3rd party IdP is up to Security plugin internal logic. Should we create followup issues in the Security team backlog?
@elastic/kibana-security let me know if the current logic makes sense for you.
Checklist
Delete any items that are not applicable to this PR.
For maintainers
Dev docs
A route config accepts
authRequired: 'optional'. A user can access a resource if has valid credentials or no credentials at all. Can be useful when we grant access to a resource but want to identify a user if possible.