Unclass
This commit is contained in:
parent
206be5c16f
commit
5e2261f793
3 changed files with 46 additions and 53 deletions
|
@ -175,7 +175,7 @@ const CodeDisplay: React.FC<CodeDisplay> = ({ codeInfo }) => {
|
|||
const generateCodes = () => {
|
||||
try {
|
||||
const currentTime = new Date().getTime();
|
||||
if (codeInfo.type.toLowerCase() === "totp") {
|
||||
if (codeInfo.type === "totp") {
|
||||
const totp = new TOTP({
|
||||
secret: codeInfo.secret,
|
||||
algorithm: codeInfo.algorithm,
|
||||
|
@ -188,7 +188,7 @@ const CodeDisplay: React.FC<CodeDisplay> = ({ codeInfo }) => {
|
|||
timestamp: currentTime + codeInfo.period * 1000,
|
||||
}),
|
||||
);
|
||||
} else if (codeInfo.type.toLowerCase() === "hotp") {
|
||||
} else if (codeInfo.type === "hotp") {
|
||||
const hotp = new HOTP({
|
||||
secret: codeInfo.secret,
|
||||
counter: 0,
|
||||
|
@ -417,7 +417,7 @@ function BadCodeInfo({ codeInfo, codeErr }) {
|
|||
<div>
|
||||
{showRawData ? (
|
||||
<div onClick={() => setShowRawData(false)}>
|
||||
{codeInfo.rawData ?? "no raw data"}
|
||||
{codeInfo.uriString ?? "(no raw data)"}
|
||||
</div>
|
||||
) : (
|
||||
<div onClick={() => setShowRawData(true)}>Show rawData</div>
|
||||
|
|
|
@ -1,54 +1,47 @@
|
|||
import { URI } from "vscode-uri";
|
||||
|
||||
type Type = "totp" | "TOTP" | "hotp" | "HOTP";
|
||||
|
||||
type Algorithm = "sha1" | "sha256" | "sha512";
|
||||
|
||||
export class Code {
|
||||
// id for the corresponding auth entity
|
||||
/**
|
||||
* A parsed representation of an xOTP code URI.
|
||||
*
|
||||
* This is all the data we need to drive a OTP generator.
|
||||
*/
|
||||
export interface Code {
|
||||
/** The uniquue id for the corresponding auth entity. */
|
||||
id?: String;
|
||||
/** The type of the code. */
|
||||
type: "totp" | "hotp";
|
||||
/** The user's account or email for which this code is used. */
|
||||
account: string;
|
||||
/** The name of the entity that issued this code. */
|
||||
issuer: string;
|
||||
/** Number of digits in the code. */
|
||||
digits: number;
|
||||
/**
|
||||
* The time period (in seconds) for which a single OTP generated from this
|
||||
* code remains valid.
|
||||
*/
|
||||
period: number;
|
||||
/** The secret that is used to drive the OTP generator. */
|
||||
secret: string;
|
||||
algorithm: Algorithm;
|
||||
type: Type;
|
||||
rawData?: string;
|
||||
|
||||
constructor(
|
||||
account: string,
|
||||
issuer: string,
|
||||
digits: number,
|
||||
period: number,
|
||||
secret: string,
|
||||
algorithm: Algorithm,
|
||||
type: Type,
|
||||
rawData?: string,
|
||||
id?: string,
|
||||
) {
|
||||
this.account = account;
|
||||
this.issuer = issuer;
|
||||
this.digits = digits;
|
||||
this.period = period;
|
||||
this.secret = secret;
|
||||
this.algorithm = algorithm;
|
||||
this.type = type;
|
||||
this.rawData = rawData;
|
||||
this.id = id;
|
||||
}
|
||||
/** The (hashing) algorithim used by the OTP generator. */
|
||||
algorithm: "sha1" | "sha256" | "sha512";
|
||||
/** The original string from which this code was generated. */
|
||||
uriString?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a "raw" OTP secret URL into its parse representation, a {@link Code}.
|
||||
* Convert a OTP code URI into its parse representation, a {@link Code}.
|
||||
*
|
||||
* An example {@link rawData}:
|
||||
* @param id A unique ID of this code within the auth app.
|
||||
*
|
||||
* otpauth://totp/account:user@example.org?algorithm=SHA1&digits=6&issuer=issuer&period=30&secret=ALPHANUM
|
||||
* @param uriString A string specifying how to generate a TOTP/HOTP/Steam OTP
|
||||
* code. These strings are of the form:
|
||||
*
|
||||
* - (TOTP)
|
||||
* otpauth://totp/account:user@example.org?algorithm=SHA1&digits=6&issuer=issuer&period=30&secret=ALPHANUM
|
||||
*/
|
||||
export const codeFromRawData = (id: string, rawData: string): Code => {
|
||||
let santizedRawData = rawData
|
||||
export const codeFromURIString = (id: string, uriString: string): Code => {
|
||||
let santizedRawData = uriString
|
||||
.replace(/\+/g, "%2B")
|
||||
.replace(/:/g, "%3A")
|
||||
.replaceAll("\r", "");
|
||||
|
@ -78,17 +71,17 @@ export const codeFromRawData = (id: string, rawData: string): Code => {
|
|||
uriPath = uriPath.split("otpauth%3A//")[1];
|
||||
}
|
||||
|
||||
return new Code(
|
||||
_getAccount(uriPath),
|
||||
_getIssuer(uriPath, uriParams),
|
||||
parseDigits(uriParams),
|
||||
parsePeriod(uriParams),
|
||||
getSanitizedSecret(uriParams),
|
||||
parseAlgorithm(uriParams),
|
||||
_getType(uriPath),
|
||||
rawData,
|
||||
return {
|
||||
id,
|
||||
);
|
||||
type: _getType(uriPath),
|
||||
account: _getAccount(uriPath),
|
||||
issuer: _getIssuer(uriPath, uriParams),
|
||||
digits: parseDigits(uriParams),
|
||||
period: parsePeriod(uriParams),
|
||||
secret: getSanitizedSecret(uriParams),
|
||||
algorithm: parseAlgorithm(uriParams),
|
||||
uriString,
|
||||
};
|
||||
};
|
||||
|
||||
const _getAccount = (uriPath: string): string => {
|
||||
|
@ -135,7 +128,7 @@ const parseDigits = (uriParams): number =>
|
|||
const parsePeriod = (uriParams): number =>
|
||||
parseInt(uriParams["period"] ?? "", 10) || 30;
|
||||
|
||||
const parseAlgorithm = (uriParams): Algorithm => {
|
||||
const parseAlgorithm = (uriParams): Code["algorithm"] => {
|
||||
switch (uriParams["algorithm"]?.toLowerCase()) {
|
||||
case "sha256":
|
||||
return "sha256";
|
||||
|
@ -146,7 +139,7 @@ const parseAlgorithm = (uriParams): Algorithm => {
|
|||
}
|
||||
};
|
||||
|
||||
const _getType = (uriPath: string): Type => {
|
||||
const _getType = (uriPath: string): Code["type"] => {
|
||||
const oauthType = uriPath.split("/")[0].substring(0);
|
||||
if (oauthType.toLowerCase() === "totp") {
|
||||
return "totp";
|
||||
|
|
|
@ -6,7 +6,7 @@ import { getEndpoint } from "@ente/shared/network/api";
|
|||
import { getToken } from "@ente/shared/storage/localStorage/helpers";
|
||||
import { getActualKey } from "@ente/shared/user";
|
||||
import { HttpStatusCode } from "axios";
|
||||
import { Code, codeFromRawData } from "services/code";
|
||||
import { codeFromURIString, type Code } from "services/code";
|
||||
|
||||
const ENDPOINT = getEndpoint();
|
||||
|
||||
|
@ -33,7 +33,7 @@ export const getAuthCodes = async (): Promise<Code[]> => {
|
|||
entity.header,
|
||||
authenticatorKey,
|
||||
);
|
||||
return codeFromRawData(entity.id, decryptedCode);
|
||||
return codeFromURIString(entity.id, decryptedCode);
|
||||
} catch (e) {
|
||||
log.error(`failed to parse codeId = ${entity.id}`);
|
||||
return null;
|
||||
|
|
Loading…
Reference in a new issue