anastasis-core: support secret version selection

This commit is contained in:
Florian Dold 2021-11-04 17:55:05 +01:00
parent 4ebeb00243
commit 5c6f380910
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
2 changed files with 53 additions and 2 deletions

View File

@ -64,6 +64,8 @@ import {
ReducerStateRecovery, ReducerStateRecovery,
SuccessDetails, SuccessDetails,
UserAttributeSpec, UserAttributeSpec,
codecForActionArgsChangeVersion,
ActionArgsChangeVersion,
} from "./reducer-types.js"; } from "./reducer-types.js";
import fetchPonyfill from "fetch-ponyfill"; import fetchPonyfill from "fetch-ponyfill";
import { import {
@ -578,6 +580,7 @@ async function downloadPolicy(
const newProviderStatus: { [url: string]: AuthenticationProviderStatusOk } = const newProviderStatus: { [url: string]: AuthenticationProviderStatusOk } =
{}; {};
const userAttributes = state.identity_attributes!; const userAttributes = state.identity_attributes!;
const restrictProvider = state.selected_provider_url;
// FIXME: Shouldn't we also store the status of bad providers? // FIXME: Shouldn't we also store the status of bad providers?
for (const url of providerUrls) { for (const url of providerUrls) {
const pi = await getProviderInfo(url); const pi = await getProviderInfo(url);
@ -592,9 +595,17 @@ async function downloadPolicy(
if (!pi) { if (!pi) {
continue; continue;
} }
if (restrictProvider && url !== state.selected_provider_url) {
// User wants specific provider.
continue;
}
const userId = await userIdentifierDerive(userAttributes, pi.salt); const userId = await userIdentifierDerive(userAttributes, pi.salt);
const acctKeypair = accountKeypairDerive(userId); const acctKeypair = accountKeypairDerive(userId);
const resp = await fetch(new URL(`policy/${acctKeypair.pub}`, url).href); const reqUrl = new URL(`policy/${acctKeypair.pub}`, url);
if (state.selected_version) {
reqUrl.searchParams.set("version", `${state.selected_version}`);
}
const resp = await fetch(reqUrl.href);
if (resp.status !== 200) { if (resp.status !== 200) {
continue; continue;
} }
@ -842,6 +853,18 @@ async function recoveryEnterUserAttributes(
return downloadPolicy(st); return downloadPolicy(st);
} }
async function changeVersion(
state: ReducerStateRecovery,
args: ActionArgsChangeVersion,
): Promise<ReducerStateRecovery | ReducerStateError> {
const st: ReducerStateRecovery = {
...state,
selected_version: args.version,
selected_provider_url: args.provider_url,
};
return downloadPolicy(st);
}
async function selectChallenge( async function selectChallenge(
state: ReducerStateRecovery, state: ReducerStateRecovery,
ta: ActionArgsSelectChallenge, ta: ActionArgsSelectChallenge,
@ -1209,6 +1232,11 @@ const recoveryTransitions: Record<
[RecoveryStates.SecretSelecting]: { [RecoveryStates.SecretSelecting]: {
...transitionRecoveryJump("back", RecoveryStates.UserAttributesCollecting), ...transitionRecoveryJump("back", RecoveryStates.UserAttributesCollecting),
...transitionRecoveryJump("next", RecoveryStates.ChallengeSelecting), ...transitionRecoveryJump("next", RecoveryStates.ChallengeSelecting),
...transition(
"change_version",
codecForActionArgsChangeVersion(),
changeVersion,
),
}, },
[RecoveryStates.ChallengeSelecting]: { [RecoveryStates.ChallengeSelecting]: {
...transitionRecoveryJump("back", RecoveryStates.SecretSelecting), ...transitionRecoveryJump("back", RecoveryStates.SecretSelecting),

View File

@ -171,6 +171,18 @@ export interface ReducerStateRecovery {
selected_challenge_uuid?: string; selected_challenge_uuid?: string;
/**
* Explicitly selected version by the user.
* FIXME: In the C reducer this is called "version".
*/
selected_version?: number;
/**
* Explicitly selected provider URL by the user.
* FIXME: In the C reducer this is called "provider_url".
*/
selected_provider_url?: string;
challenge_feedback?: { [uuid: string]: ChallengeFeedback }; challenge_feedback?: { [uuid: string]: ChallengeFeedback };
/** /**
@ -343,7 +355,7 @@ export interface SolveChallengePinRequest {
* *
* XXX: When / why is this even used? * XXX: When / why is this even used?
*/ */
export interface SolveChallengeHashRequest { export interface SolveChallengeHashRequest {
/** /**
* Base32-crock encoded hash code. * Base32-crock encoded hash code.
*/ */
@ -363,6 +375,17 @@ export interface ActionArgsUpdateExpiration {
expiration: Timestamp; expiration: Timestamp;
} }
export interface ActionArgsChangeVersion {
provider_url: string;
version: number;
}
export const codecForActionArgsChangeVersion = () =>
buildCodecForObject<ActionArgsChangeVersion>()
.property("provider_url", codecForString())
.property("version", codecForNumber())
.build("ActionArgsChangeVersion");
export const codecForPolicyMember = () => export const codecForPolicyMember = () =>
buildCodecForObject<PolicyMember>() buildCodecForObject<PolicyMember>()
.property("authentication_method", codecForNumber()) .property("authentication_method", codecForNumber())