-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Add an optional authentication mode for HTTP resources #58589
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
.
@@ -684,6 +701,27 @@ describe('Auth', () => { | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duplicates tests in src/core/server/http/integration_tests/router.test.ts should I remove them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation looks good to me.
const route = http.anonymousPaths.isAnonymous(window.location.pathname) ? '/defaults' : ''; | ||
const capabilities = await http.post<Capabilities>(`/api/core/capabilities${route}`, { | ||
const capabilities = await http.post<Capabilities>('/api/core/capabilities', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
const router = http.createRouter('/api/core/capabilities'); | ||
const router = http.createRouter(''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: why remove the prefix here?
@@ -684,6 +701,27 @@ describe('Auth', () => { | |||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
isAuthenticated(result: AuthResult): result is Authenticated { | ||
return result && result.type === AuthResultType.authenticated; | ||
}, | ||
isNotHandled(result: AuthResult): result is AuthNotHandled { | ||
return result && result.type === AuthResultType.notHandled; | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the result &&
really needed? It seems result
should not be false-ish with current typing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has our convention been to use lowercase header names? Really just asking for my own education.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we verify the value of context.auth.isAuthenticated
in these tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
optional
authentication mode for HTTP resources that acts similarly tooptional
mode in hapi https://hapi.dev/api/?v=17.9.2#-routeoptionsauthmodeFor this, I added the
notHandled
outcome for the auth interceptor. Getting it from auth hook, Kibana server behaves differently:optional
authentication mode, allows an user to access a resourcerequired
authentication mode (default behavior), the Kibana server responds with theunauthorized
response.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.