mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
feat: added casdoor sso support (#204)
This commit is contained in:
parent
34289150fa
commit
7fe3517afe
9 changed files with 180 additions and 26 deletions
|
@ -8,6 +8,13 @@ StartCmd = login
|
|||
Database = database
|
||||
CADir =
|
||||
Demo =
|
||||
CasdoorEndpoint =
|
||||
CasdoorClientId =
|
||||
CasdoorClientSecret =
|
||||
CasdoorCertificate =
|
||||
CasdoorOrganization =
|
||||
CasdoorApplication =
|
||||
CasdoorRedirectUri =
|
||||
|
||||
[nginx]
|
||||
AccessLogPath = /var/log/nginx/access.log
|
||||
|
|
|
@ -13,6 +13,15 @@ const auth = {
|
|||
login(r.token)
|
||||
})
|
||||
},
|
||||
async casdoorLogin(code: string, state: string) {
|
||||
await http.post("/casdoor_callback", {
|
||||
code: code,
|
||||
state: state,
|
||||
})
|
||||
.then((r) => {
|
||||
login(r.token)
|
||||
})
|
||||
},
|
||||
logout() {
|
||||
return http.delete('/logout').then(async () => {
|
||||
logout()
|
||||
|
|
|
@ -8,6 +8,8 @@ import {Form, message} from 'ant-design-vue'
|
|||
import auth from '@/api/auth'
|
||||
import install from '@/api/install'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
import http from '@/lib/http'
|
||||
import {onMounted} from 'vue'
|
||||
|
||||
const thisYear = new Date().getFullYear()
|
||||
|
||||
|
@ -70,6 +72,37 @@ watch(() => gettext.current, () => {
|
|||
clearValidate()
|
||||
})
|
||||
|
||||
const has_casdoor = ref(false)
|
||||
const casdoor_uri = ref('')
|
||||
|
||||
http.get("/casdoor_uri")
|
||||
.then((response) => {
|
||||
if (response?.uri) {
|
||||
has_casdoor.value = true
|
||||
casdoor_uri.value = response.uri
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error($gettext(e.message ?? 'Server error'))
|
||||
});
|
||||
|
||||
const loginWithCasdoor = () => {
|
||||
window.location.href = casdoor_uri.value
|
||||
}
|
||||
|
||||
if (route.query?.code != undefined && route.query?.state != undefined) {
|
||||
loading.value = true
|
||||
auth.casdoorLogin(route.query.code.toString(), route.query.state.toString()).then(async () => {
|
||||
message.success($gettext('Login successful'), 1)
|
||||
const next = (route.query?.next || '').toString() || '/'
|
||||
await router.push(next)
|
||||
}).catch(e => {
|
||||
message.error($gettext(e.message ?? 'Server error'))
|
||||
})
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -105,6 +138,9 @@ watch(() => gettext.current, () => {
|
|||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-button @click="loginWithCasdoor" :block="true" html-type="submit" :loading="loading" v-if="has_casdoor">
|
||||
{{ $gettext('SSO Login') }}
|
||||
</a-button>
|
||||
<div class="footer">
|
||||
<p>Copyright © 2020 - {{ thisYear }} Nginx UI</p>
|
||||
Language
|
||||
|
|
3
go.mod
3
go.mod
|
@ -7,6 +7,7 @@ toolchain go1.21.0
|
|||
require (
|
||||
github.com/0xJacky/pofile v0.2.1
|
||||
github.com/BurntSushi/toml v1.3.2
|
||||
github.com/casdoor/casdoor-go-sdk v0.32.1
|
||||
github.com/creack/pty v1.1.20
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/fatih/color v1.15.0
|
||||
|
@ -236,7 +237,7 @@ require (
|
|||
golang.org/x/arch v0.5.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.12.0 // indirect
|
||||
golang.org/x/oauth2 v0.13.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
|
|
6
go.sum
6
go.sum
|
@ -149,6 +149,8 @@ github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKE
|
|||
github.com/bytedance/sonic v1.10.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
||||
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
|
||||
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||
github.com/casdoor/casdoor-go-sdk v0.32.1 h1:SMMbicerANhceSiYdzFN2woZyf63aPemvZVT7fsJu+A=
|
||||
github.com/casdoor/casdoor-go-sdk v0.32.1/go.mod h1:hVSgmSdwTCsBEJNt9r2K5aLVsoeMc37/N4Zzescy5SA=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
|
@ -1013,8 +1015,8 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
|
|||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
|
||||
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
|
||||
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY=
|
||||
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"net/http"
|
||||
|
@ -55,3 +58,62 @@ func Logout(c *gin.Context) {
|
|||
}
|
||||
c.JSON(http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
type CasdoorLoginUser struct {
|
||||
Code string `json:"code" binding:"required,max=255"`
|
||||
State string `json:"state" binding:"required,max=255"`
|
||||
}
|
||||
|
||||
func CasdoorCallback(c *gin.Context) {
|
||||
var loginUser CasdoorLoginUser
|
||||
fmt.Println("CasdoorCallback called")
|
||||
ok := BindAndValid(c, &loginUser)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
endpoint := settings.ServerSettings.CasdoorEndpoint
|
||||
clientId := settings.ServerSettings.CasdoorClientId
|
||||
clientSecret := settings.ServerSettings.CasdoorClientSecret
|
||||
certificate := settings.ServerSettings.CasdoorCertificate
|
||||
organization := settings.ServerSettings.CasdoorOrganization
|
||||
application := settings.ServerSettings.CasdoorApplication
|
||||
if endpoint == "" || clientId == "" || clientSecret == "" || certificate == "" || organization == "" || application == "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": "Casdoor is not configured",
|
||||
})
|
||||
}
|
||||
casdoorsdk.InitConfig(endpoint, clientId, clientSecret, certificate, organization, application)
|
||||
token, err := casdoorsdk.GetOAuthToken(loginUser.Code, loginUser.State)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
claims, err := casdoorsdk.ParseJwtToken(token.AccessToken)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
u, err := model.GetUser(claims.Name)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
userToken, err := model.GenerateJWT(u.Name)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
"token": userToken,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func GetSettings(c *gin.Context) {
|
||||
|
@ -39,3 +41,21 @@ func SaveSettings(c *gin.Context) {
|
|||
|
||||
GetSettings(c)
|
||||
}
|
||||
|
||||
func GetCasdoorUri(c *gin.Context) {
|
||||
endpoint := settings.ServerSettings.CasdoorEndpoint
|
||||
clientId := settings.ServerSettings.CasdoorClientId
|
||||
redirectUri := settings.ServerSettings.CasdoorRedirectUri
|
||||
state := settings.ServerSettings.CasdoorApplication
|
||||
fmt.Println(redirectUri)
|
||||
if endpoint == "" || clientId == "" || redirectUri == "" || state == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"uri": "",
|
||||
})
|
||||
return
|
||||
}
|
||||
encodedRedirectUri := url.QueryEscape(redirectUri)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"uri": fmt.Sprintf("%s/login/oauth/authorize?client_id=%s&response_type=code&redirect_uri=%s&state=%s&scope=read", endpoint, clientId, encodedRedirectUri, state),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ func InitRouter() *gin.Engine {
|
|||
root.POST("/login", api.Login)
|
||||
root.DELETE("/logout", api.Logout)
|
||||
|
||||
root.GET("/casdoor_uri", api.GetCasdoorUri)
|
||||
root.POST("/casdoor_callback", api.CasdoorCallback)
|
||||
|
||||
// translation
|
||||
root.GET("translation/:code", api.GetTranslation)
|
||||
|
||||
|
|
|
@ -29,6 +29,13 @@ type Server struct {
|
|||
Demo bool `json:"demo"`
|
||||
PageSize int `json:"page_size"`
|
||||
GithubProxy string `json:"github_proxy"`
|
||||
CasdoorEndpoint string `json:"casdoor_endpoint"`
|
||||
CasdoorClientId string `json:"casdoor_client_id"`
|
||||
CasdoorClientSecret string `json:"casdoor_client_secret"`
|
||||
CasdoorCertificate string `json:"casdoor_certificate"`
|
||||
CasdoorOrganization string `json:"casdoor_organization"`
|
||||
CasdoorApplication string `json:"casdoor_application"`
|
||||
CasdoorRedirectUri string `json:"casdoor_redirect_uri"`
|
||||
}
|
||||
|
||||
type Nginx struct {
|
||||
|
@ -59,6 +66,13 @@ var ServerSettings = Server{
|
|||
PageSize: 10,
|
||||
CADir: "",
|
||||
GithubProxy: "",
|
||||
CasdoorEndpoint: "",
|
||||
CasdoorClientId: "",
|
||||
CasdoorClientSecret: "",
|
||||
CasdoorCertificate: "",
|
||||
CasdoorOrganization: "",
|
||||
CasdoorApplication: "",
|
||||
CasdoorRedirectUri: "",
|
||||
}
|
||||
|
||||
var NginxSettings = Nginx{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue