Commit 61198274 authored by David Burke's avatar David Burke

two factor now actually activates mfa

parent 630fc6b5
Pipeline #63149213 passed with stage
in 9 minutes and 6 seconds
......@@ -325,3 +325,7 @@ export const getMfaProvisioningURI = createSelector(
selectManageMfaState,
fromManageMfa.getProvisioningURI
);
export const getMfaId = createSelector(
selectManageMfaState,
fromManageMfa.getMFAId
);
import { Action } from "@ngrx/store";
import { IGeneratedMFA } from "./manage-mfa.interfaces";
export enum ManageMfaActionTypes {
FORWARD_STEP = "[ENABLE MFA] Forward Step",
......@@ -22,7 +23,7 @@ export class EnableMfa implements Action {
export class EnableMfaSuccess implements Action {
readonly type = ManageMfaActionTypes.ENABLE_MFA_SUCCESS;
constructor(public payload: string) {}
constructor(public payload: IGeneratedMFA) {}
}
export class EnableMfaFailure implements Action {
......
......@@ -47,7 +47,7 @@
</div>
</form>
<form *ngIf="!mfaEnabled" [ngrxFormState]="form" (submit)="onSubmit()">
<form *ngIf="!mfaEnabled" [ngrxFormState]="form" (submit)="verifyMfa.emit()">
<div *ngIf="step === 0" class="manage-backup-code__actions">
<button class="button button--primary" (click)="forwardStep.emit()">
Get Started
......
......@@ -35,6 +35,7 @@ export class ManageMfaComponent {
mfaEnabled = false; // TODO remove this
@Output() generateMfa = new EventEmitter();
@Output() verifyMfa = new EventEmitter();
@Output() forwardStep = new EventEmitter();
constructor(private _sanitizer: DomSanitizer) {}
......
import { Component } from "@angular/core";
import { Store, select } from "@ngrx/store";
import { IState } from "../../app.reducers";
import { EnableMfa, ForwardStep } from "./manage-mfa.actions";
import { EnableMfa, ForwardStep, ActivateMfa } from "./manage-mfa.actions";
import {
getMfaProvisioningURI,
getMfaStep,
getEnableMfaForm
} from "../account.reducer";
import { VerifyMfa } from "../../login/verify-mfa/verify-mfa.actions";
@Component({
template: `
......@@ -17,6 +16,7 @@ import { VerifyMfa } from "../../login/verify-mfa/verify-mfa.actions";
[form]="form$ | async"
(forwardStep)="forwardStep()"
(generateMfa)="generateMfa()"
(verifyMfa)="activateMfa()"
></app-manage-mfa>
`
})
......@@ -34,7 +34,7 @@ export class ManageMfaContainer {
this.store.dispatch(new EnableMfa());
}
verifyMfa() {
this.store.dispatch(new VerifyMfa());
activateMfa() {
this.store.dispatch(new ActivateMfa());
}
}
......@@ -8,8 +8,11 @@ import {
ActivateMfaFailure,
ActivateMfaSuccess
} from "./manage-mfa.actions";
import { exhaustMap, map, catchError } from "rxjs/operators";
import { exhaustMap, map, catchError, withLatestFrom } from "rxjs/operators";
import { of } from "rxjs";
import { Store, select } from "@ngrx/store";
import { IState } from "../../app.reducers";
import { getEnableMfaForm, getMfaId } from "../account.reducer";
@Injectable()
export class ManageMFAEffects {
......@@ -18,7 +21,7 @@ export class ManageMFAEffects {
ofType(ManageMfaActionTypes.ENABLE_MFA),
exhaustMap(action =>
this.service.generateMfa().pipe(
map(resp => new EnableMfaSuccess(resp.provisioning_uri)),
map(resp => new EnableMfaSuccess(resp)),
catchError(resp => of(new EnableMfaFailure(resp)))
)
)
......@@ -27,13 +30,24 @@ export class ManageMFAEffects {
@Effect()
activateMfa$ = this.actions$.pipe(
ofType(ManageMfaActionTypes.ACTIVATE_MFA),
exhaustMap(action =>
this.service.activateMfa(1, 2).pipe(
map(resp => new ActivateMfaSuccess()),
catchError(resp => of(new ActivateMfaFailure()))
)
)
withLatestFrom(
this.store.pipe(select(getEnableMfaForm)),
this.store.pipe(select(getMfaId))
),
exhaustMap(([action, form, id]) => {
if (form.value.verificationCode && id) {
return this.service.activateMfa(form.value.verificationCode, id).pipe(
map(resp => new ActivateMfaSuccess()),
catchError(resp => of(new ActivateMfaFailure()))
);
}
return of(new ActivateMfaFailure());
})
);
constructor(private actions$: Actions, private service: UserService) {}
constructor(
private actions$: Actions,
private store: Store<IState>,
private service: UserService
) {}
}
......@@ -4,3 +4,8 @@ export enum ActivateMFAStep {
ScanQR = 2,
EnterCode = 3
}
export interface IGeneratedMFA {
provisioning_uri: string;
id: number;
}
......@@ -7,7 +7,7 @@ import {
} from "ngrx-forms";
import { required } from "ngrx-forms/validation";
import { ManageMfaActions, ManageMfaActionTypes } from "./manage-mfa.actions";
import { ActivateMFAStep } from "./manage-mfa.interfaces";
import { ActivateMFAStep, IGeneratedMFA } from "./manage-mfa.interfaces";
export const FORM_ID = "Enable MFA Form";
......@@ -16,7 +16,7 @@ export interface IEnableMfaForm {
}
export interface IEnbleMfaState {
form: FormGroupState<IEnableMfaForm>;
provisioningURI: string | null;
generatedMFA: IGeneratedMFA | null;
mfaEnabled: boolean;
step: ActivateMFAStep;
errorMessage: string[] | null;
......@@ -34,7 +34,7 @@ export const initialFormState = validateAndUpdateFormState(
export const initialState: IEnbleMfaState = {
form: initialFormState,
provisioningURI: null,
generatedMFA: null,
step: ActivateMFAStep.Start,
errorMessage: null,
mfaEnabled: false
......@@ -62,7 +62,7 @@ export function reducer(
case ManageMfaActionTypes.ENABLE_MFA_SUCCESS:
return {
...state,
provisioningURI: action.payload,
generatedMFA: action.payload,
mfaEnabled: true
};
......@@ -83,4 +83,6 @@ export const getMfaEnabled = (state: IEnbleMfaState) => state.mfaEnabled;
export const getStep = (state: IEnbleMfaState) => state.step;
export const getErrorMessage = (state: IEnbleMfaState) => state.errorMessage;
export const getProvisioningURI = (state: IEnbleMfaState) =>
state.provisioningURI;
state.generatedMFA ? state.generatedMFA.provisioning_uri : null;
export const getMFAId = (state: IEnbleMfaState) =>
state.generatedMFA ? state.generatedMFA.id : null;
......@@ -20,6 +20,7 @@ import { SetUrlAction } from "../account.actions";
import { IAuthStore, IResetPasswordVerifyResponse } from "./user.interfaces";
import { checkRespForErrors } from "~/app/shared/utils";
import { IState, selectAuthState } from "../../app.reducers";
import { IGeneratedMFA } from "../manage-mfa/manage-mfa.interfaces";
@Injectable()
export class UserService {
......@@ -425,11 +426,11 @@ export class UserService {
/** Generate new MFA code, returns the uri that can be imported into MFA apps like Google Authenticator */
generateMfa() {
const url = this.sdk.formUrl("generate-mfa/");
return this.http.post<{ provisioning_uri: string }>(url, "");
return this.http.post<IGeneratedMFA>(url, "");
}
/** Activate a generated MFA code */
activateMfa(otp: number, id: number) {
activateMfa(otp: string, id: number) {
const url = this.sdk.formUrl("activate-mfa/");
const data = { otp, id };
return this.http.post(url, data);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment