update
This commit is contained in:
No files matched your search
+1
-5
@@ -7,13 +7,9 @@ SSO_CONFIRM_URL =
|
|||||||
|
|
||||||
X_AP_CODE=rssa-sso
|
X_AP_CODE=rssa-sso
|
||||||
X_AP_SECRET_KEY=sapiperah
|
X_AP_SECRET_KEY=sapiperah
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID=portal-simrs-new
|
|
||||||
# Local
|
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_SECRET=
|
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL=http://127.0.0.1:8080/realms/rssa_testing
|
|
||||||
|
|
||||||
KEYCLOAK_LOGOUT_REDIRECT=http://localhost:3000/
|
KEYCLOAK_LOGOUT_REDIRECT=http://localhost:3000/
|
||||||
|
|
||||||
# test local
|
# test local
|
||||||
KEYCLOAK_REALM=rssa_testing
|
KEYCLOAK_REALM=rssa_testing
|
||||||
KEYCLOAK_URL=http://127.0.0.1:8080/
|
KEYCLOAK_URL=http://127.0.0.1:8080/
|
||||||
|
CLIENT_ID=portal-simrs-new
|
||||||
@@ -3,6 +3,8 @@ import type { z } from 'zod'
|
|||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
import { Loader2 } from 'lucide-vue-next'
|
import { Loader2 } from 'lucide-vue-next'
|
||||||
import { useForm } from 'vee-validate'
|
import { useForm } from 'vee-validate'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useKeycloak } from "~/composables/useKeycloack"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
schema: z.ZodSchema<any>
|
schema: z.ZodSchema<any>
|
||||||
@@ -14,7 +16,6 @@ const props = defineProps<Props>()
|
|||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
submit: [data: any]
|
submit: [data: any]
|
||||||
sso: []
|
sso: []
|
||||||
response: [state: string]
|
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { handleSubmit, defineField, errors, meta } = useForm({
|
const { handleSubmit, defineField, errors, meta } = useForm({
|
||||||
@@ -36,24 +37,24 @@ const onSubmit = handleSubmit(async (values) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { initKeycloak, getProfile, login } = useKeycloak()
|
||||||
|
const profile = ref<any>(null)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await initKeycloak('check-sso')
|
||||||
|
profile.value = getProfile()
|
||||||
|
console.log(profile)
|
||||||
|
})
|
||||||
|
|
||||||
const onSSO = (async () => {
|
const onSSO = (async () => {
|
||||||
console.log("Emitting SSO...")
|
|
||||||
try {
|
try {
|
||||||
await emit('sso')
|
const redirect = window.location.origin + '/auth/sso'
|
||||||
|
await login({ redirectUri: redirect })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Call SSO failed:', error)
|
console.error('Call SSO failed:', error)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const test = useRoute()
|
|
||||||
const responseSSO = test.hash
|
|
||||||
|
|
||||||
if (responseSSO != null && responseSSO != '') {
|
|
||||||
console.log("Getting Response SSO...")
|
|
||||||
await emit('response', responseSSO)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -93,11 +94,7 @@ if (responseSSO != null && responseSSO != '') {
|
|||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<a href="/auth/keycloak/login">Login with Keycloak</a>
|
|
||||||
|
|
||||||
<Button @click="onSSO" target="_blank">
|
<Button @click="onSSO" target="_blank">
|
||||||
Login SSO
|
Login SSO
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<span>success {{ responseSSO }}</span>
|
|
||||||
</template>
|
</template>
|
||||||
@@ -41,121 +41,10 @@ async function onSubmit(data: LoginFormData) {
|
|||||||
|
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = useRuntimeConfig()
|
|
||||||
// const store = useKeycloak()
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
loggedIn: false
|
|
||||||
})
|
|
||||||
|
|
||||||
async function onSSO() {
|
|
||||||
console.log("=================== on SSO! ===================")
|
|
||||||
const config = useRuntimeConfig()
|
|
||||||
|
|
||||||
const keycloak = new Keycloak({
|
|
||||||
url: config.public.KEYCLOAK_URL,
|
|
||||||
realm: config.public.KEYCLOAK_REALM,
|
|
||||||
clientId: config.public.NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const authenticatedResult = await keycloak.init({ onLoad: 'login-required' }); // Or 'login-required'
|
|
||||||
// seelah line ini aku mek paham logic e tapi faktane dunno
|
|
||||||
const nuxtApp = useNuxtApp()
|
|
||||||
nuxtApp.provide('keycloak', keycloak);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Keycloak initialization failed:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// const initOptions = {
|
|
||||||
// url: config.public.KEYCLOAK_URL,
|
|
||||||
// realm: config.public.KEYCLOAK_REALM,
|
|
||||||
// clientId: config.public.KEYCLOAK_ID,
|
|
||||||
// onLoad: 'login-required'
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const keycloak = new Keycloak(initOptions)
|
|
||||||
// console.log("=================== balik gak se! ===================")
|
|
||||||
// keycloak
|
|
||||||
// .init({ onLoad: initOptions.onLoad })
|
|
||||||
// .then((auth) => {
|
|
||||||
// console.log(auth)
|
|
||||||
// if (!auth) {
|
|
||||||
// window.location.reload()
|
|
||||||
// } else {
|
|
||||||
// // store.setup(keycloak)
|
|
||||||
// state.loggedIn = true
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
console.log("=================== onto login fes! ===================")
|
|
||||||
// if (state.loggedIn) {
|
|
||||||
// const result = await xfetch('/api/v1/authentication/login-fes', 'POST', {
|
|
||||||
// data: keycloak,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// 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'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const urlSSO =
|
|
||||||
// config.public.KEYCLOAK_ISSUER +
|
|
||||||
// '/protocol/openid-connect/auth?client_id=' +
|
|
||||||
// config.public.KEYCLOAK_ID +
|
|
||||||
// '&scope=openid%20email%20profile&response_type=code&redirect_uri=' +
|
|
||||||
// config.public.KEYCLOAK_LOGOUT_REDIRECT +
|
|
||||||
// '%2Fapi%2Fauth%2Fcallback%2Fkeycloak&state=AKf-WHWdL822V3LaNS5MSFzJ96-VHp6FUXlXxIAzXXM&code_challenge=nXOcGLLlA1NtXI4RM4hL59iP_I_yQAsUDd5sAOkKBF4&code_challenge_method=S256'
|
|
||||||
// await navigateTo(urlSSO,
|
|
||||||
// {
|
|
||||||
// open: { target: '_blank' },
|
|
||||||
// external: true
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onResponseSSO(authenticatedResult: string) {
|
|
||||||
console.log("=================== onto login fes!!! ===================")
|
|
||||||
console.log(authenticatedResult)
|
|
||||||
if (authenticatedResult) {
|
|
||||||
const result = await xfetch('/api/v1/authentication/login-fes', 'POST', {
|
|
||||||
data: authenticatedResult,
|
|
||||||
})
|
|
||||||
|
|
||||||
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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<AppAuthLogin :schema="loginSchema" :is-loading="isLoading" @submit="onSubmit" @sso="onSSO" @response="onResponseSSO" />
|
<AppAuthLogin :schema="loginSchema" :is-loading="isLoading" @submit="onSubmit" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
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 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 login = (options?: Keycloak.KeycloakLoginOptions) => {
|
||||||
|
if (!kc) throw new Error("Keycloak not initialized");
|
||||||
|
return kc.login(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
const logout = (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 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,
|
||||||
|
login,
|
||||||
|
logout,
|
||||||
|
getToken,
|
||||||
|
isAuthenticated,
|
||||||
|
getProfile,
|
||||||
|
getResponse,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
export default defineNuxtRouteMiddleware((to) => {
|
import { useKeycloak } from "~/composables/useKeycloack"
|
||||||
|
|
||||||
|
export default defineNuxtRouteMiddleware(async (to) => {
|
||||||
if (to.meta.public) return
|
if (to.meta.public) return
|
||||||
|
|
||||||
const { $pinia } = useNuxtApp()
|
const { $pinia } = useNuxtApp()
|
||||||
const oidc = useOidcAuth();
|
|
||||||
|
const { initKeycloak, isAuthenticated} = useKeycloak(); // global composable
|
||||||
|
await initKeycloak("check-sso");
|
||||||
|
|
||||||
if (import.meta.client) {
|
if (import.meta.client) {
|
||||||
const userStore = useUserStore($pinia)
|
const userStore = useUserStore($pinia)
|
||||||
if (!userStore.isAuthenticated && !oidc.loggedIn) {
|
if (!userStore.isAuthenticated && !isAuthenticated.value) {
|
||||||
|
// await login({ redirectUri: window.location.origin + to.fullPath });
|
||||||
return navigateTo('/auth/login')
|
return navigateTo('/auth/login')
|
||||||
// oidc.login('dev');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
+24
-7
@@ -1,13 +1,30 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
definePageMeta({
|
import { ref, onMounted } from 'vue'
|
||||||
layout: 'blank',
|
import { useKeycloak } from "~/composables/useKeycloack"
|
||||||
public: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const test = useRoute()
|
const error = ref<string | null>(null)
|
||||||
const temp = test.hash
|
const { initKeycloak, isAuthenticated, getResponse } = useKeycloak()
|
||||||
|
const profile = ref<any>(null)
|
||||||
|
const token = ref<string | null>(null);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
// Initialize Keycloak with login-required to ensure tokens set (Keycloak will process the code/state returned)
|
||||||
|
await initKeycloak('login-required')
|
||||||
|
// small delay to allow token propagation
|
||||||
|
if (isAuthenticated.value) {
|
||||||
|
await getResponse()
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
error.value = err?.message || String(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<span>success {{ temp }}</span>
|
<div style="max-width:720px;margin:40px auto">
|
||||||
|
<h2>Processing login...</h2>
|
||||||
|
<p v-if="error">Terjadi error: {{ error }}</p>
|
||||||
|
<p v-else>Mohon tunggu, sedang memproses otentikasi dan mengarahkan Anda ...</p>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
+2
-22
@@ -11,13 +11,11 @@ export default defineNuxtConfig({
|
|||||||
X_AP_CODE: process.env.X_AP_CODE || 'rssa-sso',
|
X_AP_CODE: process.env.X_AP_CODE || 'rssa-sso',
|
||||||
X_AP_SECRET_KEY: process.env.X_AP_SECRET_KEY || 'sapiperah',
|
X_AP_SECRET_KEY: process.env.X_AP_SECRET_KEY || 'sapiperah',
|
||||||
SSO_CONFIRM_URL: process.env.SSO_CONFIRM_URL || 'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/userinfo',
|
SSO_CONFIRM_URL: process.env.SSO_CONFIRM_URL || 'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/userinfo',
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID || 'portal-simrs-new',
|
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_SECRET: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_SECRET || 'awoiehrw3w8942341k1ln4',
|
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL || 'https://auth.dev.rssa.id/realms/sandbox',
|
|
||||||
KEYCLOAK_LOGOUT_REDIRECT: process.env.KEYCLOAK_LOGOUT_REDIRECT || 'http://localhost:3000',
|
KEYCLOAK_LOGOUT_REDIRECT: process.env.KEYCLOAK_LOGOUT_REDIRECT || 'http://localhost:3000',
|
||||||
//test
|
//test
|
||||||
KEYCLOAK_REALM: process.env.KEYCLOAK_REALM || 'sandbox',
|
KEYCLOAK_REALM: process.env.KEYCLOAK_REALM || 'sandbox',
|
||||||
KEYCLOAK_URL: process.env.KEYCLOAK_URL || 'https://auth.dev.rssa.id/',
|
KEYCLOAK_URL: process.env.KEYCLOAK_URL || 'https://auth.dev.rssa.id/',
|
||||||
|
CLIENT_ID: process.env.CLIENT_ID || 'portal-simrs-new',
|
||||||
public: {
|
public: {
|
||||||
API_ORIGIN: process.env.NUXT_API_ORIGIN || 'http://localhost:3000',
|
API_ORIGIN: process.env.NUXT_API_ORIGIN || 'http://localhost:3000',
|
||||||
VCLAIM: process.env.NUXT_API_VCLAIM || 'http://localhost:3000',
|
VCLAIM: process.env.NUXT_API_VCLAIM || 'http://localhost:3000',
|
||||||
@@ -26,13 +24,11 @@ export default defineNuxtConfig({
|
|||||||
X_AP_CODE: process.env.X_AP_CODE || 'rssa-sso',
|
X_AP_CODE: process.env.X_AP_CODE || 'rssa-sso',
|
||||||
X_AP_SECRET_KEY: process.env.X_AP_SECRET_KEY || 'sapiperah',
|
X_AP_SECRET_KEY: process.env.X_AP_SECRET_KEY || 'sapiperah',
|
||||||
SSO_CONFIRM_URL: process.env.SSO_CONFIRM_URL || 'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/userinfo',
|
SSO_CONFIRM_URL: process.env.SSO_CONFIRM_URL || 'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/userinfo',
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID || 'portal-simrs-new',
|
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_SECRET: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_SECRET || 'awoiehrw3w8942341k1ln4',
|
|
||||||
NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL || 'https://auth.dev.rssa.id/realms/sandbox',
|
|
||||||
KEYCLOAK_LOGOUT_REDIRECT: process.env.KEYCLOAK_LOGOUT_REDIRECT || 'http://localhost:3000',
|
KEYCLOAK_LOGOUT_REDIRECT: process.env.KEYCLOAK_LOGOUT_REDIRECT || 'http://localhost:3000',
|
||||||
//test
|
//test
|
||||||
KEYCLOAK_REALM: process.env.KEYCLOAK_REALM || 'sandbox',
|
KEYCLOAK_REALM: process.env.KEYCLOAK_REALM || 'sandbox',
|
||||||
KEYCLOAK_URL: process.env.KEYCLOAK_URL || 'https://auth.dev.rssa.id/',
|
KEYCLOAK_URL: process.env.KEYCLOAK_URL || 'https://auth.dev.rssa.id/',
|
||||||
|
CLIENT_ID: process.env.CLIENT_ID || 'portal-simrs-new',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ssr: false,
|
ssr: false,
|
||||||
@@ -68,24 +64,8 @@ export default defineNuxtConfig({
|
|||||||
'@nuxtjs/color-mode',
|
'@nuxtjs/color-mode',
|
||||||
'@nuxtjs/tailwindcss',
|
'@nuxtjs/tailwindcss',
|
||||||
'shadcn-nuxt',
|
'shadcn-nuxt',
|
||||||
'nuxt-oidc-auth',
|
|
||||||
],
|
],
|
||||||
|
|
||||||
oidc: {
|
|
||||||
defaultProvider: 'keycloak',
|
|
||||||
keycloak: {
|
|
||||||
audience: 'account',
|
|
||||||
baseUrl: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_BASE_URL, // change to your OP addrress
|
|
||||||
clientId: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_ID,
|
|
||||||
clientSecret: process.env.NUXT_OIDC_PROVIDERS_KEYCLOAK_CLIENT_SECRET,
|
|
||||||
redirectUri: process.env.KEYCLOAK_LOGOUT_REDIRECT, // optional
|
|
||||||
},
|
|
||||||
middleware: {
|
|
||||||
globalMiddlewareEnabled: true,
|
|
||||||
customLoginPage: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
css: ['@unocss/reset/tailwind.css', '~/assets/css/main.css'],
|
css: ['@unocss/reset/tailwind.css', '~/assets/css/main.css'],
|
||||||
|
|
||||||
features: {
|
features: {
|
||||||
|
|||||||
@@ -55,7 +55,6 @@
|
|||||||
"lucide-vue-next": "^0.482.0",
|
"lucide-vue-next": "^0.482.0",
|
||||||
"next-auth": "~4.21.1",
|
"next-auth": "~4.21.1",
|
||||||
"nuxt": "^4.0.3",
|
"nuxt": "^4.0.3",
|
||||||
"nuxt-oidc-auth": "1.0.0-beta.5",
|
|
||||||
"playwright-core": "^1.54.2",
|
"playwright-core": "^1.54.2",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"prettier-plugin-tailwindcss": "^0.5.14",
|
"prettier-plugin-tailwindcss": "^0.5.14",
|
||||||
|
|||||||
@@ -7,18 +7,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
const url = getRequestURL(event)
|
const url = getRequestURL(event)
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
|
|
||||||
console.log("body: " + JSON.stringify(body))
|
|
||||||
|
|
||||||
// const apiSSOConfirm = 'https://auth.rssa.top/realms/sandbox/protocol/openid-connect/userinfo'
|
|
||||||
const apiSSOConfirm = config.public.SSO_CONFIRM_URL
|
const apiSSOConfirm = config.public.SSO_CONFIRM_URL
|
||||||
|
const token = 'Bearer ' + body.data.token
|
||||||
const jwt = body.jwt
|
|
||||||
// const nip = body.nip
|
|
||||||
// const role = body.role
|
|
||||||
// const roleid = body.roleid
|
|
||||||
// const shift = body.shift
|
|
||||||
// const loginStatus = body.status_login
|
|
||||||
const token = 'Bearer ' + jwt
|
|
||||||
|
|
||||||
const res_sso = await fetch(apiSSOConfirm,
|
const res_sso = await fetch(apiSSOConfirm,
|
||||||
{
|
{
|
||||||
@@ -31,40 +21,17 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
console.log(res_sso)
|
console.log(res_sso)
|
||||||
if (res_sso.status === 200) {
|
if (res_sso.status === 200) {
|
||||||
const parts = jwt.split('.')
|
|
||||||
|
|
||||||
if (parts.count != 3) {
|
|
||||||
// return ['error' => 'Invalid JWT format'];
|
|
||||||
}
|
|
||||||
|
|
||||||
const header = Buffer.from(strtr(parts[0], '-_', '+/'), 'base64').toString('utf8')
|
|
||||||
const payload = Buffer.from(strtr(parts[1], '-_', '+/'), 'base64').toString('utf8')
|
|
||||||
|
|
||||||
// const textDecoder = new TextDecoder('utf-8');
|
|
||||||
// // Decode the header and payload
|
|
||||||
// const decodedBinaryHead = atob(parts[0]);
|
|
||||||
// const decodedBinaryPayload = atob(parts[0]);
|
|
||||||
// const header = textDecoder.decode(Uint8Array.from(decodedBinaryHead, char => char.charCodeAt(0)));
|
|
||||||
// const payload = textDecoder.decode(Uint8Array.from(decodedBinaryPayload, char => char.charCodeAt(0)));
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
'header': header,
|
|
||||||
'payload': payload
|
|
||||||
};
|
|
||||||
|
|
||||||
const apiOrigin = config.public.API_ORIGIN
|
const apiOrigin = config.public.API_ORIGIN
|
||||||
|
|
||||||
const cleanOrigin = apiOrigin.replace(/\/+$/, '')
|
const cleanOrigin = apiOrigin.replace(/\/+$/, '')
|
||||||
const cleanPath = url.pathname.replace(/^\/api\//, '').replace(/^\/+/, '')
|
const cleanPath = url.pathname.replace(/^\/api\//, '').replace(/^\/+/, '')
|
||||||
const externalUrl = `${cleanOrigin}/${cleanPath}${url.search}`
|
const externalUrl = `${cleanOrigin}/${cleanPath}${url.search}`
|
||||||
console.log("external url: " + externalUrl)
|
|
||||||
console.log("body: " + JSON.stringify(body))
|
|
||||||
|
|
||||||
const resp = await fetch(externalUrl,
|
const resp = await fetch(externalUrl,
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name: JSON.parse(payload).name,
|
name: body.data.user.username,
|
||||||
}),
|
}),
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -73,27 +40,6 @@ export default defineEventHandler(async (event) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(resp)
|
|
||||||
// if (resp.status === 200) {
|
|
||||||
// const data = await resp.json()
|
|
||||||
|
|
||||||
// if (data?.data?.accessToken) {
|
|
||||||
// setCookie(event, 'authentication', data.data.accessToken, {
|
|
||||||
// path: '/',
|
|
||||||
// httpOnly: true,
|
|
||||||
// sameSite: 'strict',
|
|
||||||
// maxAge: 60 * 60 * 24,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// delete data.data.accessToken
|
|
||||||
// // return data
|
|
||||||
|
|
||||||
// const { login } = useUserStore()
|
|
||||||
// await login(resp.text())
|
|
||||||
// await navigateTo('/')
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return new Response(await resp.text(), {
|
return new Response(await resp.text(), {
|
||||||
status: resp.status,
|
status: resp.status,
|
||||||
headers: {
|
headers: {
|
||||||
@@ -109,14 +55,3 @@ export default defineEventHandler(async (event) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function strtr(str: string, fromChars: string, toChars: string) {
|
|
||||||
let result = str;
|
|
||||||
for (let i = 0; i < fromChars.length; i++) {
|
|
||||||
const fromChar = fromChars[i] || '_-';
|
|
||||||
// const toChar = toChars[i];
|
|
||||||
// Use a global regex to replace all occurrences of the character
|
|
||||||
result = result.replace(new RegExp(fromChar.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), toChars);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user