120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
import Keycloak from "keycloak-js";
|
|
import { ref, computed, onBeforeMount } from "vue";
|
|
|
|
let kc: any | null = null;
|
|
|
|
const initialized = ref(false);
|
|
const authenticated = ref(false);
|
|
const token = ref<string | null>(null);
|
|
const profile = ref<any>(null);
|
|
|
|
export function useKeycloak() {
|
|
const config = useRuntimeConfig()
|
|
const initKeycloak = async (onLoad: "login-required" | "check-sso" = "check-sso") => {
|
|
if (kc) return kc;
|
|
kc = new Keycloak({
|
|
url: config.public.KEYCLOAK_URL,
|
|
realm: config.public.KEYCLOAK_REALM,
|
|
clientId: config.public.CLIENT_ID,
|
|
});
|
|
|
|
try {
|
|
const initOptions = {
|
|
onLoad,
|
|
promiseType: "native" as const,
|
|
pkceMethod: "S256" as const,
|
|
};
|
|
console.log(kc.url)
|
|
authenticated.value = await kc.init(initOptions);
|
|
initialized.value = true;
|
|
token.value = kc.token ?? null;
|
|
if (authenticated.value) {
|
|
try {
|
|
profile.value = await kc.loadUserProfile();
|
|
} catch (e) {
|
|
profile.value = null;
|
|
}
|
|
}
|
|
// automatically update token in background
|
|
kc.onTokenExpired = async () => {
|
|
try {
|
|
const refreshed = await kc.updateToken(30);
|
|
token.value = kc?.token ?? null;
|
|
if (!refreshed) {
|
|
// token not refreshed but still valid
|
|
}
|
|
} catch (err) {
|
|
console.warn("Failed to refresh token", err);
|
|
}
|
|
};
|
|
return kc;
|
|
} catch (err) {
|
|
console.log(authenticated)
|
|
console.error("Keycloak init xyz failed", err);
|
|
initialized.value = true;
|
|
authenticated.value = false;
|
|
return kc;
|
|
}
|
|
};
|
|
|
|
const loginSSO = (options?: Keycloak.KeycloakLoginOptions) => {
|
|
if (!kc) throw new Error("Keycloak not initialized");
|
|
return kc.login(options);
|
|
};
|
|
|
|
const logoutSSO = (redirectUri?: string) => {
|
|
if (!kc) throw new Error("Keycloak not initialized");
|
|
return kc.logout({ redirectUri });
|
|
};
|
|
|
|
const getToken = () => token.value;
|
|
const isAuthenticated = computed(() => authenticated.value);
|
|
const getProfile = () => profile.value;
|
|
|
|
// init on client automatically
|
|
onBeforeMount(() => {
|
|
// try check-sso silently
|
|
if (!initialized.value) initKeycloak("check-sso");
|
|
});
|
|
|
|
const apiErrors = ref<Record<string, string>>({})
|
|
const { login } = useUserStore()
|
|
|
|
const getResponse = async () => {
|
|
console.log("=================== onto login fes!!! ===================")
|
|
const params = {
|
|
token: token.value,
|
|
user: profile.value
|
|
}
|
|
const result = await xfetch('/api/v1/authentication/login-fes', 'POST', {
|
|
data: params,
|
|
})
|
|
|
|
if (result.success) {
|
|
const { data: rawdata, meta } = result.body
|
|
if (meta.status === 'verified') {
|
|
login(rawdata)
|
|
navigateTo('/')
|
|
}
|
|
} else {
|
|
if (result.errors) {
|
|
Object.entries(result.errors).forEach(
|
|
([field, errorInfo]: [string, any]) => (apiErrors.value[field] = errorInfo.message),
|
|
)
|
|
} else {
|
|
apiErrors.value.general = result.error?.message || result.message || 'Login failed'
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
initKeycloak,
|
|
loginSSO,
|
|
logoutSSO,
|
|
getToken,
|
|
isAuthenticated,
|
|
getProfile,
|
|
getResponse,
|
|
};
|
|
}
|