feat(openvpn): add OIDC browser authentication and setup guide

This commit is contained in:
opsx committed 2026-10-20 23:31:46 +08:00
1 parent 5107f134dd
commit d6a9a92ad0
13 files changed
+817 -14

No files matched your search

@@ -0,0 +1,66 @@
<template>
<section class="oidc-guide">
<div class="guide-title"><b>{{ $t('oidcGuide.title') }}</b><el-tag type="warning" effect="plain">{{ $t('oidcGuide.externalService') }}</el-tag></div>
<el-steps :active="guideStep" finish-status="success" align-center class="guide-steps">
<el-step :title="$t('oidcGuide.app')" :description="$t('oidcGuide.appShort')" />
<el-step :title="$t('oidcGuide.identity')" :description="$t('oidcGuide.identityShort')" />
<el-step :title="$t('oidcGuide.callback')" :description="$t('oidcGuide.callbackShort')" />
<el-step :title="$t('oidcGuide.test')" :description="$t('oidcGuide.testShort')" />
</el-steps>
<el-alert type="info" :closable="false" :title="$t('oidcGuide.appTip')" class="guide-alert">
<template #default>
<a href="https://open.feishu.cn/app" target="_blank" rel="noopener noreferrer">{{ $t('oidcGuide.openConsole') }} ↗</a>
<ol><li>{{ $t('oidcGuide.appInstruction1') }}</li><li>{{ $t('oidcGuide.appInstruction2') }}</li><li>{{ $t('oidcGuide.appInstruction3') }}</li></ol>
<p>{{ $t('oidcGuide.scopeTip') }}</p>
</template>
</el-alert>
<el-form-item :label="$t('oidcGuide.issuer')" required>
<el-input v-model.trim="config.oidc_issuer" placeholder="https://idp.example.com" />
<div class="field-tip">{{ $t('oidcGuide.issuerTip') }}</div>
</el-form-item>
<el-form-item :label="$t('oidcGuide.clientId')" required>
<el-input v-model.trim="config.oidc_client_id" />
</el-form-item>
<el-form-item :label="$t('oidcGuide.clientSecret')" :required="!editing">
<el-input v-model="config.oidc_client_secret" type="password" show-password autocomplete="new-password" :placeholder="editing ? $t('oidcGuide.keepSecret') : $t('oidcGuide.copySecret')" />
<div class="field-tip">{{ $t('oidcGuide.secretTip') }}</div>
</el-form-item>
<el-form-item :label="$t('oidcGuide.baseUrl')" required>
<el-input v-model.trim="config.oidc_base_url" placeholder="https://vpn-login.example.com" />
<div class="field-tip">{{ $t('oidcGuide.baseTip') }}</div>
</el-form-item>
<el-form-item :label="$t('oidcGuide.listenPort')">
<el-input-number v-model="config.oidc_http_port" :min="1024" :max="65535" />
<div class="field-tip">{{ $t('oidcGuide.portTip') }}</div>
</el-form-item>
<el-alert type="warning" :closable="false" class="guide-alert" :title="$t('oidcGuide.callbackTitle')">
<template #default>
<code>{{ callbackUrl }}</code>
<p>{{ $t('oidcGuide.callbackTip', { port: config.oidc_http_port || 19090 }) }}</p>
</template>
</el-alert>
<el-alert type="info" :closable="false" :title="$t('oidcGuide.testTip')" />
</section>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({ config: { type: Object, required: true }, editing: { type: Boolean, default: false } })
const callbackUrl = computed(() => `${(props.config.oidc_base_url || 'https://vpn-login.example.com').replace(/\/+$/, '')}/oauth2/callback`)
const guideStep = computed(() => !props.config.oidc_client_id ? 0
: !props.config.oidc_issuer || (!props.config.oidc_client_secret && !props.editing) ? 1
: !props.config.oidc_base_url ? 2 : 3)
</script>
<style scoped>
.oidc-guide { margin: 10px 0 24px; padding: 18px; border: 1px solid var(--border-base); border-radius: var(--radius-sm); background: var(--bg-inset); }
.guide-title { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.guide-steps { margin: 24px 0; }
.guide-alert { margin: 16px 0; }
.guide-alert p { margin: 8px 0 0; line-height: 1.5; }
.guide-alert ol { padding-left: 20px; line-height: 1.7; }
.field-tip { margin-top: 4px; color: var(--text-secondary); font-size: 12px; line-height: 1.5; }
code { overflow-wrap: anywhere; }
@media (max-width: 720px) { .guide-steps { overflow-x: auto; justify-content: flex-start; } .guide-steps :deep(.el-step) { min-width: 120px; } }
</style>