Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 11x 11x 11x 2x 13x 1x 12x 12x 2x 10x 10x 1x 9x 1x 8x 8x 8x 8x 8x 8x 8x 1x 7x 7x 170x 13x 13x 13x 13x 13x 1x 5x 2x 1x 1x 13x 13x 12x 12x 3x 9x 13x | import { ref } from "vue";
import { useDBSLoginWebcomponentPlugin } from "@/components/DBSLoginWebcomponentPlugin";
import AuthorizationEventDetails from "@/types/AuthorizationEventDetails";
class JwtParseError extends Error {
constructor(message: string, options?: { cause?: unknown }) {
super(message);
this.name = "JwtParseError";
if (options?.cause !== undefined) {
this.cause = options.cause;
}
}
}
function getJwtPayloadSegment(token: string): string {
if (!token?.trim()) {
throw new JwtParseError("Invalid JWT: token must be a non-empty string");
}
const parts = token.split(".");
if (parts.length !== 3) {
throw new JwtParseError(
`Invalid JWT: expected 3 dot-separated segments, got ${parts.length}`
);
}
const [headerSegment, payloadSegment] = parts;
if (!headerSegment) {
throw new JwtParseError("Invalid JWT: header segment is missing");
}
if (!payloadSegment) {
throw new JwtParseError("Invalid JWT: payload segment is missing");
}
return payloadSegment;
}
function base64UrlToBase64(base64Url: string): string {
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
const paddingLength = (4 - (base64.length % 4)) % 4;
return base64 + "=".repeat(paddingLength);
}
function decodeJwtPayloadSegment(payloadSegment: string): string {
const base64 = base64UrlToBase64(payloadSegment);
let decoded: string;
try {
decoded = window.atob(base64);
} catch (error) {
throw new JwtParseError("Invalid JWT: failed to base64-decode payload", {
cause: error,
});
}
try {
return decodeURIComponent(
decoded
.split("")
.map((character) => {
return "%" + ("00" + character.charCodeAt(0).toString(16)).slice(-2);
})
.join("")
);
} catch (error) {
throw new JwtParseError("Invalid JWT: failed to decode payload bytes", {
cause: error,
});
}
}
function parseJwt(token: string): Record<string, unknown> {
const payloadSegment = getJwtPayloadSegment(token);
const jsonPayload = decodeJwtPayloadSegment(payloadSegment);
try {
const parsed: unknown = JSON.parse(jsonPayload);
if (
parsed === null ||
typeof parsed !== "object" ||
Array.isArray(parsed)
) {
throw new JwtParseError("Invalid JWT: payload must be a JSON object");
}
return parsed as Record<string, unknown>;
} catch (error) {
if (error instanceof JwtParseError) {
throw error;
}
throw new JwtParseError("Invalid JWT: payload is not valid JSON", {
cause: error,
});
}
}
export function getTokenData(accessToken: string): {
email?: string;
given_name?: string;
family_name?: string;
} {
const payload = parseJwt(accessToken);
const getOptionalString = (key: string): string | undefined => {
const value = payload[key];
if (value !== undefined && typeof value !== "string") {
throw new JwtParseError(`Invalid JWT: ${key} must be a string`);
}
return value as string | undefined;
};
return {
email: getOptionalString("email"),
given_name: getOptionalString("given_name"),
family_name: getOptionalString("family_name"),
};
}
export function useLogin() {
const accessToken = ref<string | null>(null);
const { loggedIn, loading } = useDBSLoginWebcomponentPlugin(
(authEventDetails: AuthorizationEventDetails) => {
accessToken.value = authEventDetails.accessToken;
},
() => {
accessToken.value = null;
}
);
return {
isLoggedIn: loggedIn,
isLoadingAuthentication: loading,
accessToken,
};
}
|