mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-29 02:21:08 +02:00
* UI: Move `wrapped_token` login functionality to route (#30465) * move token unwrap functionality to page component * update mfa test * remove wrapped_token logic from page component * more cleanup to relocate unwrap logic * move wrapped_token to route * move unwrap tests to acceptance * move mfa form back * add some padding * update mfa-form tests * get param from params * wait for auth form on back * run rests * UI: Add MFA support for SSO methods (#30489) * initial implementation of mfa validation for sso methods * update typescript interfaces * add stopgap changes to auth service * switch order backend is defined * update login form for tests even though it will be deleted * attempt to stabilize wrapped_query test * =update login form test why not * Update ui/app/components/auth/form/saml.ts Co-authored-by: lane-wetmore <lane.wetmore@hashicorp.com> --------- Co-authored-by: lane-wetmore <lane.wetmore@hashicorp.com> * Move CSP error to page component (#30492) * initial implementation of mfa validation for sso methods * update typescript interfaces * add stopgap changes to auth service * switch order backend is defined * update login form for tests even though it will be deleted * attempt to stabilize wrapped_query test * =update login form test why not * move csp error to page component * move csp error to page component * Move fetching unauthenticated mounts to the route (#30509) * rename namespace arg to namespaceQueryParam * move fetch mounts to route * add margin to sign in button spacing * update selectors for oidc provider test * add todo delete comments * fix arg typo in test * change method name * fix args handling tab click * remove tests that no longer relate to components functionality * add tests for preselectedAuthType functionality * move typescript interfaces, fix selector * add await * oops * move format method down, make private * move tab formatting to the route * move to page object * fix token unwrap aborting transition * not sure what that is doing there.. * add comments * rename to presetAuthType * use did-insert instead * UI: Implement `Auth::FormTemplate` (#30521) * replace Auth::LoginForm with Auth::FormTemplate * first round of test updates * return null if mounts object is empty * add comment and test for empty sys/internal/mounts data * more test updates * delete listing_visibility test, delete login-form component test * update divs to Hds::Card::Container * add overflow class * remove unused getters * move requesting stored auth type to page component * fix typo * Update ui/app/components/auth/form/oidc-jwt.ts make comment make more sense * small cleanup items, update imports * Delete old auth components (#30527) * delete old components * update codeowners * Update `with` query param functionality (#30537) * update path input to type=hidden * add test coverage * update page test * update auth route * delete login form * update ent test * consolidate logic in getter * add more comments * more comments.. * rename selector * refresh model as well * redirect for invalid query params * move unwrap to redirect * only redirect on invalid query params * add tests for query param * test selector updates * remove todos, update relevant ones with initials * add changelog --------- Co-authored-by: lane-wetmore <lane.wetmore@hashicorp.com>
104 lines
3.1 KiB
TypeScript
104 lines
3.1 KiB
TypeScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
import AuthBase from './base';
|
|
import { action } from '@ember/object';
|
|
import { service } from '@ember/service';
|
|
import { task, timeout } from 'ember-concurrency';
|
|
import { tracked } from '@glimmer/tracking';
|
|
import { waitFor } from '@ember/test-waiters';
|
|
import errorMessage from 'vault/utils/error-message';
|
|
import uuid from 'core/utils/uuid';
|
|
|
|
import type AuthService from 'vault/vault/services/auth';
|
|
|
|
/**
|
|
* @module Auth::Form::Okta
|
|
* see Auth::Base
|
|
* */
|
|
|
|
export default class AuthFormOkta extends AuthBase {
|
|
@service declare readonly auth: AuthService;
|
|
|
|
@tracked challengeAnswer = '';
|
|
@tracked oktaVerifyError = '';
|
|
@tracked showNumberChallenge = false;
|
|
|
|
loginFields = [{ name: 'username' }, { name: 'password' }];
|
|
|
|
login = task(
|
|
waitFor(async (data) => {
|
|
// wait for 1s to wait to see if there is a login error before polling
|
|
await timeout(1000);
|
|
|
|
data.nonce = uuid();
|
|
this.pollForOktaNumberChallenge.perform(data.nonce, data.path);
|
|
|
|
try {
|
|
// selecting the correct okta verify answer on the personal device resolves this request
|
|
const authResponse = await this.auth.authenticate({
|
|
clusterId: this.args.cluster.id,
|
|
backend: this.args.authType,
|
|
data,
|
|
selectedAuth: this.args.authType,
|
|
});
|
|
|
|
this.handleAuthResponse(authResponse);
|
|
} catch (error) {
|
|
// if a user fails the okta verify challenge, the POST login request fails (made by this.auth.authenticate above)
|
|
// bubble those up for consistency instead of managing error state in this component
|
|
this.onError(error as Error);
|
|
// cancel polling tasks and reset state
|
|
this.reset();
|
|
}
|
|
})
|
|
);
|
|
|
|
pollForOktaNumberChallenge = task(
|
|
waitFor(async (nonce, mountPath) => {
|
|
this.showNumberChallenge = true;
|
|
|
|
// keep polling /auth/okta/verify/:nonce API every 1s until response returns with correct_number
|
|
let verifyNumber = null;
|
|
while (verifyNumber === null) {
|
|
await timeout(1000);
|
|
verifyNumber = await this.requestOktaVerify(nonce, mountPath);
|
|
}
|
|
|
|
// display correct number so user can select on personal MFA device
|
|
this.challengeAnswer = verifyNumber ?? '';
|
|
})
|
|
);
|
|
|
|
@action
|
|
async requestOktaVerify(nonce: string, mountPath: string) {
|
|
const url = `/v1/auth/${mountPath}/verify/${nonce}`;
|
|
try {
|
|
const response = await this.auth.ajax(url, 'GET', {});
|
|
return response.data.correct_answer;
|
|
} catch (e) {
|
|
const error = e as Response;
|
|
if (error?.status === 404) {
|
|
// if error status is 404 return null to keep polling for a response
|
|
return null;
|
|
} else {
|
|
// this would be unusual, but handling just in case
|
|
this.oktaVerifyError = errorMessage(e);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
@action
|
|
reset() {
|
|
// reset tracked variables and stop polling tasks
|
|
this.challengeAnswer = '';
|
|
this.oktaVerifyError = '';
|
|
this.showNumberChallenge = false;
|
|
this.login.cancelAll();
|
|
this.pollForOktaNumberChallenge.cancelAll();
|
|
}
|
|
}
|