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