UI: Fix OIDC login in fullscreen (#19071)
This commit is contained in:
parent
e04a3d21a1
commit
1ec10bccd3
|
@ -0,0 +1,3 @@
|
|||
```release-note:bug
|
||||
ui: Fix bug where logging in via OIDC fails if browser is in fullscreen mode
|
||||
```
|
|
@ -2,7 +2,6 @@ import Ember from 'ember';
|
|||
import { inject as service } from '@ember/service';
|
||||
// ARG NOTE: Once you remove outer-html after glimmerizing you can remove the outer-html component
|
||||
import Component from './outer-html';
|
||||
import { later } from '@ember/runloop';
|
||||
import { task, timeout, waitForEvent } from 'ember-concurrency';
|
||||
import { computed } from '@ember/object';
|
||||
import { waitFor } from '@ember/test-waiters';
|
||||
|
@ -76,6 +75,17 @@ export default Component.extend({
|
|||
})
|
||||
).restartable(),
|
||||
|
||||
cancelLogin(oidcWindow, errorMessage) {
|
||||
this.closeWindow(oidcWindow);
|
||||
this.handleOIDCError(errorMessage);
|
||||
},
|
||||
|
||||
closeWindow(oidcWindow) {
|
||||
this.watchPopup.cancelAll();
|
||||
this.watchCurrent.cancelAll();
|
||||
oidcWindow.close();
|
||||
},
|
||||
|
||||
handleOIDCError(err) {
|
||||
this.onLoading(false);
|
||||
this.prepareForOIDC.cancelAll();
|
||||
|
@ -94,10 +104,7 @@ export default Component.extend({
|
|||
// ensure that postMessage event is from expected source
|
||||
while (true) {
|
||||
const event = yield waitForEvent(thisWindow, 'message');
|
||||
if (event.origin !== thisWindow.origin || !event.isTrusted) {
|
||||
return this.handleOIDCError();
|
||||
}
|
||||
if (event.data.source === 'oidc-callback') {
|
||||
if (event.data.source === 'oidc-callback' && event.isTrusted && event.origin === thisWindow.origin) {
|
||||
return this.exchangeOIDC.perform(event.data, oidcWindow);
|
||||
}
|
||||
// continue to wait for the correct message
|
||||
|
@ -119,12 +126,6 @@ export default Component.extend({
|
|||
oidcWindow.close();
|
||||
}),
|
||||
|
||||
closeWindow(oidcWindow) {
|
||||
this.watchPopup.cancelAll();
|
||||
this.watchCurrent.cancelAll();
|
||||
oidcWindow.close();
|
||||
},
|
||||
|
||||
exchangeOIDC: task(function* (oidcState, oidcWindow) {
|
||||
if (oidcState === null || oidcState === undefined) {
|
||||
return;
|
||||
|
@ -145,12 +146,8 @@ export default Component.extend({
|
|||
}
|
||||
}
|
||||
|
||||
// defer closing of the window, but continue executing the task
|
||||
later(() => {
|
||||
this.closeWindow(oidcWindow);
|
||||
}, WAIT_TIME);
|
||||
if (!path || !state || !code) {
|
||||
return this.handleOIDCError(ERROR_MISSING_PARAMS);
|
||||
return this.cancelLogin(oidcWindow, ERROR_MISSING_PARAMS);
|
||||
}
|
||||
const adapter = this.store.adapterFor('auth-method');
|
||||
this.onNamespace(namespace);
|
||||
|
@ -159,8 +156,11 @@ export default Component.extend({
|
|||
// and submit auth form
|
||||
try {
|
||||
resp = yield adapter.exchangeOIDC(path, state, code);
|
||||
this.closeWindow(oidcWindow);
|
||||
} catch (e) {
|
||||
return this.handleOIDCError(e);
|
||||
// If there was an error on Vault's end, close the popup
|
||||
// and show the error on the login screen
|
||||
return this.cancelLogin(oidcWindow, e);
|
||||
}
|
||||
yield this.onSubmit(null, null, resp.auth.client_token);
|
||||
}),
|
||||
|
|
|
@ -7,6 +7,7 @@ import { _cancelTimers as cancelTimers } from '@ember/runloop';
|
|||
|
||||
const mockWindow = EmberObject.extend(Evented, {
|
||||
origin: 'http://localhost:4200',
|
||||
close: () => {},
|
||||
});
|
||||
|
||||
module('Unit | Component | auth-jwt', function (hooks) {
|
||||
|
@ -18,21 +19,25 @@ module('Unit | Component | auth-jwt', function (hooks) {
|
|||
this.errorSpy = sinon.spy(this.component, 'handleOIDCError');
|
||||
});
|
||||
|
||||
test('it should handle error for cross origin messages while waiting for oidc callback', async function (assert) {
|
||||
assert.expect(1);
|
||||
test('it should ignore messages from cross origin windows while waiting for oidc callback', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.component.prepareForOIDC.perform(mockWindow.create());
|
||||
this.component.window.trigger('message', { origin: 'http://anotherdomain.com', isTrusted: true });
|
||||
assert.ok(this.errorSpy.calledOnce, 'Error handled from cross origin window message event');
|
||||
|
||||
assert.ok(this.errorSpy.notCalled, 'Error handler not triggered while waiting for oidc callback message');
|
||||
assert.strictEqual(this.component.exchangeOIDC.performCount, 0, 'exchangeOIDC method not fired');
|
||||
cancelTimers();
|
||||
});
|
||||
|
||||
test('it should handle error for untrusted messages while waiting for oidc callback', async function (assert) {
|
||||
assert.expect(1);
|
||||
test('it should ignore untrusted messages while waiting for oidc callback', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.component.prepareForOIDC.perform(mockWindow.create());
|
||||
this.component.window.trigger('message', { origin: 'http://localhost:4200', isTrusted: false });
|
||||
assert.ok(this.errorSpy.calledOnce, 'Error handled from untrusted window message event');
|
||||
assert.ok(this.errorSpy.notCalled, 'Error handler not triggered while waiting for oidc callback message');
|
||||
assert.strictEqual(this.component.exchangeOIDC.performCount, 0, 'exchangeOIDC method not fired');
|
||||
cancelTimers();
|
||||
});
|
||||
|
||||
// test case for https://github.com/hashicorp/vault/issues/12436
|
||||
test('it should ignore messages sent from outside the app while waiting for oidc callback', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
|
Loading…
Reference in New Issue