mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 02:35:49 +08:00
feat: add OIDC WebFinger support (#3245)
* feat: add WebFinger support * lint: used gofumpt * oidc: ensure webfinger rel is checked
This commit is contained in:
parent
717c53f6e5
commit
d647eed22a
@ -77,6 +77,7 @@ p, *, *, POST, /api/verify-code, *, *
|
||||
p, *, *, POST, /api/reset-email-or-phone, *, *
|
||||
p, *, *, POST, /api/upload-resource, *, *
|
||||
p, *, *, GET, /.well-known/openid-configuration, *, *
|
||||
p, *, *, GET, /.well-known/webfinger, *, *
|
||||
p, *, *, *, /.well-known/jwks, *, *
|
||||
p, *, *, GET, /api/get-saml-login, *, *
|
||||
p, *, *, POST, /api/acs, *, *
|
||||
|
@ -14,7 +14,11 @@
|
||||
|
||||
package controllers
|
||||
|
||||
import "github.com/casdoor/casdoor/object"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/object"
|
||||
)
|
||||
|
||||
// GetOidcDiscovery
|
||||
// @Title GetOidcDiscovery
|
||||
@ -42,3 +46,31 @@ func (c *RootController) GetJwks() {
|
||||
c.Data["json"] = jwks
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// GetWebFinger
|
||||
// @Title GetWebFinger
|
||||
// @Tag OIDC API
|
||||
// @Param resource query string true "resource"
|
||||
// @Success 200 {object} object.WebFinger
|
||||
// @router /.well-known/webfinger [get]
|
||||
func (c *RootController) GetWebFinger() {
|
||||
resource := c.Input().Get("resource")
|
||||
rels := []string{}
|
||||
host := c.Ctx.Request.Host
|
||||
|
||||
for key, value := range c.Input() {
|
||||
if strings.HasPrefix(key, "rel") {
|
||||
rels = append(rels, value...)
|
||||
}
|
||||
}
|
||||
|
||||
webfinger, err := object.GetWebFinger(resource, rels, host)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = webfinger
|
||||
c.Ctx.Output.ContentType("application/jrd+json")
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
@ -44,6 +44,18 @@ type OidcDiscovery struct {
|
||||
EndSessionEndpoint string `json:"end_session_endpoint"`
|
||||
}
|
||||
|
||||
type WebFinger struct {
|
||||
Subject string `json:"subject"`
|
||||
Links []WebFingerLink `json:"links"`
|
||||
Aliases *[]string `json:"aliases,omitempty"`
|
||||
Properties *map[string]string `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
type WebFingerLink struct {
|
||||
Rel string `json:"rel"`
|
||||
Href string `json:"href"`
|
||||
}
|
||||
|
||||
func isIpAddress(host string) bool {
|
||||
// Attempt to split the host and port, ignoring the error
|
||||
hostWithoutPort, _, err := net.SplitHostPort(host)
|
||||
@ -160,3 +172,43 @@ func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
|
||||
|
||||
return jwks, nil
|
||||
}
|
||||
|
||||
func GetWebFinger(resource string, rels []string, host string) (WebFinger, error) {
|
||||
wf := WebFinger{}
|
||||
|
||||
resourceSplit := strings.Split(resource, ":")
|
||||
|
||||
if len(resourceSplit) != 2 {
|
||||
return wf, fmt.Errorf("invalid resource")
|
||||
}
|
||||
|
||||
resourceType := resourceSplit[0]
|
||||
resourceValue := resourceSplit[1]
|
||||
|
||||
oidcDiscovery := GetOidcDiscovery(host)
|
||||
|
||||
switch resourceType {
|
||||
case "acct":
|
||||
user, err := GetUserByEmailOnly(resourceValue)
|
||||
if err != nil {
|
||||
return wf, err
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
return wf, fmt.Errorf("user not found")
|
||||
}
|
||||
|
||||
wf.Subject = resource
|
||||
|
||||
for _, rel := range rels {
|
||||
if rel == "http://openid.net/specs/connect/1.0/issuer" {
|
||||
wf.Links = append(wf.Links, WebFingerLink{
|
||||
Rel: "http://openid.net/specs/connect/1.0/issuer",
|
||||
Href: oidcDiscovery.Issuer,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wf, nil
|
||||
}
|
||||
|
@ -290,6 +290,7 @@ func initAPI() {
|
||||
|
||||
beego.Router("/.well-known/openid-configuration", &controllers.RootController{}, "GET:GetOidcDiscovery")
|
||||
beego.Router("/.well-known/jwks", &controllers.RootController{}, "*:GetJwks")
|
||||
beego.Router("/.well-known/webfinger", &controllers.RootController{}, "GET:GetWebFinger")
|
||||
|
||||
beego.Router("/cas/:organization/:application/serviceValidate", &controllers.RootController{}, "GET:CasServiceValidate")
|
||||
beego.Router("/cas/:organization/:application/proxyValidate", &controllers.RootController{}, "GET:CasProxyValidate")
|
||||
|
Loading…
x
Reference in New Issue
Block a user