Remove bad error message when registering U2F device.

This commit is contained in:
Clement Michaud 2019-03-31 20:09:51 +02:00 committed by Clément Michaud
parent 8a76b5118d
commit 87e06e6528
4 changed files with 52 additions and 59 deletions

View File

@ -51,7 +51,7 @@ async function triggerSecurityKeySigning(dispatch: Dispatch, redirectionUrl: str
} }
try { try {
await redirectIfPossible(dispatch, result as Response); await redirectIfPossible(result as Response);
dispatch(securityKeySignSuccess()); dispatch(securityKeySignSuccess());
await handleSuccess(dispatch, 1000); await handleSuccess(dispatch, 1000);
} catch (err) { } catch (err) {
@ -59,7 +59,7 @@ async function triggerSecurityKeySigning(dispatch: Dispatch, redirectionUrl: str
} }
} }
async function redirectIfPossible(dispatch: Dispatch, res: Response) { async function redirectIfPossible(res: Response) {
if (res.status === 204) return; if (res.status === 204) return;
const body = await res.json(); const body = await res.json();

View File

@ -2,10 +2,10 @@ import { connect } from 'react-redux';
import SecurityKeyRegistrationView from '../../../views/SecurityKeyRegistrationView/SecurityKeyRegistrationView'; import SecurityKeyRegistrationView from '../../../views/SecurityKeyRegistrationView/SecurityKeyRegistrationView';
import { RootState } from '../../../reducers'; import { RootState } from '../../../reducers';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import {to} from 'await-to-js';
import * as U2fApi from "u2f-api"; import * as U2fApi from "u2f-api";
import { Props } from '../../../views/SecurityKeyRegistrationView/SecurityKeyRegistrationView'; import { Props } from '../../../views/SecurityKeyRegistrationView/SecurityKeyRegistrationView';
import { registerSecurityKey, registerSecurityKeyFailure, registerSecurityKeySuccess } from '../../../reducers/Portal/SecurityKeyRegistration/actions'; import { registerSecurityKey, registerSecurityKeyFailure, registerSecurityKeySuccess } from '../../../reducers/Portal/SecurityKeyRegistration/actions';
import AutheliaService from '../../../services/AutheliaService';
const mapStateToProps = (state: RootState) => ({ const mapStateToProps = (state: RootState) => ({
deviceRegistered: state.securityKeyRegistration.success, deviceRegistered: state.securityKeyRegistration.success,
@ -18,32 +18,6 @@ async function checkIdentity(token: string) {
}); });
} }
async function requestRegistration() {
return fetch('/api/u2f/register_request')
.then(async (res) => {
if (res.status !== 200) {
throw new Error('Status code ' + res.status);
}
return res.json();
});
}
async function completeRegistration(response: U2fApi.RegisterResponse) {
return fetch('/api/u2f/register', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(response),
})
.then(async (res) => {
if (res.status !== 200) {
throw new Error('Status code ' + res.status);
}
});
}
function fail(dispatch: Dispatch, err: Error) { function fail(dispatch: Dispatch, err: Error) {
dispatch(registerSecurityKeyFailure(err.message)); dispatch(registerSecurityKeyFailure(err.message));
} }
@ -51,38 +25,22 @@ function fail(dispatch: Dispatch, err: Error) {
const mapDispatchToProps = (dispatch: Dispatch, ownProps: Props) => { const mapDispatchToProps = (dispatch: Dispatch, ownProps: Props) => {
return { return {
onInit: async (token: string) => { onInit: async (token: string) => {
let err, result; try {
dispatch(registerSecurityKey()); dispatch(registerSecurityKey());
[err, result] = await to(checkIdentity(token)); await checkIdentity(token);
if (err) { const requestRegister = await AutheliaService.requestSecurityKeyRegistration();
const registerResponse = await U2fApi.register(requestRegister, [], 60);
await AutheliaService.completeSecurityKeyRegistration(registerResponse);
dispatch(registerSecurityKeySuccess());
setTimeout(() => {
ownProps.history.push('/');
}, 2000);
} catch(err) {
fail(dispatch, err); fail(dispatch, err);
return;
} }
[err, result] = await to(requestRegistration());
if (err) {
fail(dispatch, err);
return;
}
[err, result] = await to(U2fApi.register(result, [], 60));
if (err) {
fail(dispatch, err);
return;
}
[err, result] = await to(completeRegistration(result as U2fApi.RegisterResponse));
if (err) {
fail(dispatch, err);
return;
}
dispatch(registerSecurityKeySuccess());
setTimeout(() => {
ownProps.history.push('/2fa');
}, 2000);
}, },
onBackClicked: () => { onBackClicked: () => {
ownProps.history.push('/2fa'); ownProps.history.push('/');
} }
} }
} }

View File

@ -2,6 +2,7 @@ import RemoteState from "../views/AuthenticationView/RemoteState";
import u2fApi, { SignRequest } from "u2f-api"; import u2fApi, { SignRequest } from "u2f-api";
import Method2FA from "../types/Method2FA"; import Method2FA from "../types/Method2FA";
import RedirectResponse from "./RedirectResponse"; import RedirectResponse from "./RedirectResponse";
import PreferedMethodResponse from "./PreferedMethodResponse";
class AutheliaService { class AutheliaService {
static async fetchSafe(url: string, options?: RequestInit): Promise<Response> { static async fetchSafe(url: string, options?: RequestInit): Promise<Response> {
@ -12,7 +13,7 @@ class AutheliaService {
return res; return res;
} }
static async fetchSafeJson(url: string, options?: RequestInit): Promise<any> { static async fetchSafeJson<T>(url: string, options?: RequestInit): Promise<T> {
const res = await fetch(url, options); const res = await fetch(url, options);
if (res.status !== 200) { if (res.status !== 200) {
throw new Error('Status code ' + res.status); throw new Error('Status code ' + res.status);
@ -167,7 +168,19 @@ class AutheliaService {
} }
static async fetchPrefered2faMethod(): Promise<Method2FA> { static async fetchPrefered2faMethod(): Promise<Method2FA> {
const doc = await this.fetchSafeJson('/api/secondfactor/preferences'); const doc = await this.fetchSafeJson<PreferedMethodResponse>('/api/secondfactor/preferences');
if (!doc) {
throw new Error("No response.");
}
if (doc.error) {
throw new Error(doc.error);
}
if (!doc.method) {
throw new Error("No method.");
}
return doc.method; return doc.method;
} }
@ -185,6 +198,21 @@ class AutheliaService {
static async getAvailable2faMethods(): Promise<Method2FA[]> { static async getAvailable2faMethods(): Promise<Method2FA[]> {
return await this.fetchSafeJson('/api/secondfactor/available'); return await this.fetchSafeJson('/api/secondfactor/available');
} }
static async completeSecurityKeyRegistration(response: u2fApi.RegisterResponse): Promise<Response> {
return await this.fetchSafe('/api/u2f/register', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(response),
});
}
static async requestSecurityKeyRegistration() {
return this.fetchSafeJson<u2fApi.RegisterRequest>('/api/u2f/register_request')
}
} }
export default AutheliaService; export default AutheliaService;

View File

@ -0,0 +1,7 @@
import Method2FA from "../types/Method2FA";
export default interface PreferedMethodResponse {
method?: Method2FA;
error?: string;
}