sync authserver sso integrations
This commit is contained in:
@@ -53,6 +53,31 @@ server {
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
location /auth/.well-known/ {
|
||||
proxy_pass http://authserver-backend:8083;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
location /internal/clouddm/ {
|
||||
proxy_pass http://open-cdm.db.svc.cluster.local:8222/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host 218.11.5.223:30009;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-Host 218.11.5.223:30009;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto http;
|
||||
proxy_connect_timeout 5s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
location /auth/ {
|
||||
try_files $uri $uri/ /auth/index.html;
|
||||
}
|
||||
|
||||
+60
-17
@@ -4,6 +4,7 @@ import { computed, onMounted, ref } from 'vue'
|
||||
const TOKEN_KEY = 'authserver_token'
|
||||
const SSO_LOGIN_PATH = '/auth/api/v1/login/internal-sso'
|
||||
const WAYEN_LOGIN_PATH = '/auth/api/v1/wayen/login'
|
||||
const CLOUDDM_LOGIN_PATH = '/auth/api/v1/clouddm/login'
|
||||
|
||||
const token = ref(localStorage.getItem(TOKEN_KEY) || '')
|
||||
const currentUser = ref(null)
|
||||
@@ -11,6 +12,7 @@ const message = ref('')
|
||||
const loading = ref(false)
|
||||
const redirectingToSSO = ref(false)
|
||||
const wayenLoading = ref(false)
|
||||
const clouddmLoading = ref(false)
|
||||
|
||||
const isAuthed = computed(() => Boolean(token.value))
|
||||
const currentUserLabel = computed(() => {
|
||||
@@ -26,20 +28,24 @@ function clearAuth() {
|
||||
localStorage.removeItem(TOKEN_KEY)
|
||||
}
|
||||
|
||||
function relayState(openWayen = false) {
|
||||
function relayState(openApp = '') {
|
||||
const url = new URL(window.location.href)
|
||||
if (openWayen) {
|
||||
url.searchParams.delete('open_wayen')
|
||||
url.searchParams.delete('open_app')
|
||||
if (openApp === 'wayen') {
|
||||
url.searchParams.set('open_wayen', '1')
|
||||
} else if (openApp) {
|
||||
url.searchParams.set('open_app', openApp)
|
||||
}
|
||||
return `${url.pathname}${url.search}${url.hash}` || '/'
|
||||
}
|
||||
|
||||
function ssoLogin({ openWayen = false } = {}) {
|
||||
function ssoLogin({ openApp = '' } = {}) {
|
||||
if (redirectingToSSO.value) {
|
||||
return
|
||||
}
|
||||
redirectingToSSO.value = true
|
||||
window.location.assign(`${SSO_LOGIN_PATH}?relay_state=${encodeURIComponent(relayState(openWayen))}`)
|
||||
window.location.assign(`${SSO_LOGIN_PATH}?relay_state=${encodeURIComponent(relayState(openApp))}`)
|
||||
}
|
||||
|
||||
async function api(path, options = {}) {
|
||||
@@ -55,7 +61,7 @@ async function api(path, options = {}) {
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
clearAuth()
|
||||
ssoLogin({ openWayen: true })
|
||||
ssoLogin()
|
||||
}
|
||||
const error = new Error(data.error || `HTTP ${response.status}`)
|
||||
error.status = response.status
|
||||
@@ -103,7 +109,7 @@ async function openWayen() {
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
clearAuth()
|
||||
ssoLogin({ openWayen: true })
|
||||
ssoLogin({ openApp: 'wayen' })
|
||||
}
|
||||
throw new Error(data.error || `HTTP ${response.status}`)
|
||||
}
|
||||
@@ -118,26 +124,59 @@ async function openWayen() {
|
||||
}
|
||||
}
|
||||
|
||||
async function openCloudDM() {
|
||||
clouddmLoading.value = true
|
||||
message.value = ''
|
||||
try {
|
||||
const response = await fetch(CLOUDDM_LOGIN_PATH, {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${token.value}`,
|
||||
},
|
||||
credentials: 'include',
|
||||
})
|
||||
const data = await response.json().catch(() => ({}))
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
clearAuth()
|
||||
ssoLogin({ openApp: 'clouddm' })
|
||||
}
|
||||
throw new Error(data.error || `HTTP ${response.status}`)
|
||||
}
|
||||
if (!data.target_url) {
|
||||
throw new Error('CloudDM 跳转地址为空')
|
||||
}
|
||||
window.location.assign(data.target_url)
|
||||
} catch (error) {
|
||||
message.value = error.message
|
||||
} finally {
|
||||
clouddmLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const url = new URL(window.location.href)
|
||||
const ssoToken = url.searchParams.get('sso_token')
|
||||
const shouldOpenWayen = url.searchParams.get('open_wayen') === '1'
|
||||
const openApp = url.searchParams.get('open_wayen') === '1' ? 'wayen' : url.searchParams.get('open_app')
|
||||
if (ssoToken) {
|
||||
token.value = ssoToken
|
||||
localStorage.setItem(TOKEN_KEY, ssoToken)
|
||||
url.searchParams.delete('sso_token')
|
||||
url.searchParams.delete('open_wayen')
|
||||
url.searchParams.delete('open_app')
|
||||
window.history.replaceState({}, '', `${url.pathname}${url.search}${url.hash}`)
|
||||
}
|
||||
if (!token.value) {
|
||||
ssoLogin({ openWayen: true })
|
||||
ssoLogin()
|
||||
return
|
||||
}
|
||||
await run(async () => {
|
||||
await loadMe()
|
||||
}, '已就绪')
|
||||
if (shouldOpenWayen) {
|
||||
if (openApp === 'wayen') {
|
||||
await openWayen()
|
||||
} else if (openApp === 'clouddm') {
|
||||
await openCloudDM()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -147,17 +186,17 @@ onMounted(async () => {
|
||||
<section class="login-panel">
|
||||
<div>
|
||||
<p class="eyebrow">AuthServer</p>
|
||||
<h1>Wayen 登录入口</h1>
|
||||
<h1>应用入口</h1>
|
||||
</div>
|
||||
<p class="message">正在跳转到 SSO 登录...</p>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<main v-else class="wayen-page">
|
||||
<header class="wayen-header">
|
||||
<main v-else class="app-page">
|
||||
<header class="app-header">
|
||||
<div>
|
||||
<p class="eyebrow">AuthServer</p>
|
||||
<h1>Wayen</h1>
|
||||
<h1>应用入口</h1>
|
||||
</div>
|
||||
<div class="user-block">
|
||||
<span>{{ currentUserLabel }}</span>
|
||||
@@ -165,10 +204,14 @@ onMounted(async () => {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="wayen-main">
|
||||
<button class="wayen-button" type="button" :disabled="wayenLoading" @click="openWayen">
|
||||
<span class="wayen-icon" aria-hidden="true">W</span>
|
||||
<span class="wayen-title">Wayen</span>
|
||||
<section class="app-main">
|
||||
<button class="app-button wayen-button" type="button" :disabled="wayenLoading" @click="openWayen">
|
||||
<span class="app-icon wayen-icon" aria-hidden="true">W</span>
|
||||
<span class="app-title">Wayen</span>
|
||||
</button>
|
||||
<button class="app-button clouddm-button" type="button" :disabled="clouddmLoading" @click="openCloudDM">
|
||||
<span class="app-icon clouddm-icon" aria-hidden="true">C</span>
|
||||
<span class="app-title">CloudDM</span>
|
||||
</button>
|
||||
<p v-if="message" class="message">{{ message }}</p>
|
||||
</section>
|
||||
|
||||
@@ -98,7 +98,7 @@ h1 {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.wayen-page {
|
||||
.app-page {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
@@ -107,7 +107,7 @@ h1 {
|
||||
#f5f7fb;
|
||||
}
|
||||
|
||||
.wayen-header {
|
||||
.app-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -118,7 +118,7 @@ h1 {
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.wayen-main {
|
||||
.app-main {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 360px));
|
||||
justify-content: center;
|
||||
@@ -127,7 +127,7 @@ h1 {
|
||||
padding: 32px 20px;
|
||||
}
|
||||
|
||||
.wayen-button {
|
||||
.app-button {
|
||||
width: min(280px, 78vw);
|
||||
aspect-ratio: 1;
|
||||
display: grid;
|
||||
@@ -140,27 +140,34 @@ h1 {
|
||||
box-shadow: 0 18px 50px rgb(43 57 84 / 12%);
|
||||
}
|
||||
|
||||
.wayen-button:hover:not(:disabled),
|
||||
.wayen-button:focus-visible {
|
||||
.app-button:hover:not(:disabled),
|
||||
.app-button:focus-visible {
|
||||
border-color: #1b64d8;
|
||||
box-shadow: 0 22px 60px rgb(27 100 216 / 18%);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.wayen-icon {
|
||||
.app-icon {
|
||||
width: 112px;
|
||||
height: 112px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 28px;
|
||||
background: #1b64d8;
|
||||
color: #ffffff;
|
||||
font-size: 64px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.wayen-title {
|
||||
.wayen-icon {
|
||||
background: #1b64d8;
|
||||
}
|
||||
|
||||
.clouddm-icon {
|
||||
background: #0f7b6c;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
color: #172033;
|
||||
font-size: 22px;
|
||||
font-weight: 750;
|
||||
@@ -175,7 +182,7 @@ h1 {
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.wayen-header {
|
||||
.app-header {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
padding: 18px 20px;
|
||||
@@ -186,14 +193,14 @@ h1 {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.wayen-icon {
|
||||
.app-icon {
|
||||
width: 92px;
|
||||
height: 92px;
|
||||
border-radius: 22px;
|
||||
font-size: 52px;
|
||||
}
|
||||
|
||||
.wayen-main {
|
||||
.app-main {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user