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/reset-email-or-phone, *, *
|
||||||
p, *, *, POST, /api/upload-resource, *, *
|
p, *, *, POST, /api/upload-resource, *, *
|
||||||
p, *, *, GET, /.well-known/openid-configuration, *, *
|
p, *, *, GET, /.well-known/openid-configuration, *, *
|
||||||
|
p, *, *, GET, /.well-known/webfinger, *, *
|
||||||
p, *, *, *, /.well-known/jwks, *, *
|
p, *, *, *, /.well-known/jwks, *, *
|
||||||
p, *, *, GET, /api/get-saml-login, *, *
|
p, *, *, GET, /api/get-saml-login, *, *
|
||||||
p, *, *, POST, /api/acs, *, *
|
p, *, *, POST, /api/acs, *, *
|
||||||
|
@ -14,7 +14,11 @@
|
|||||||
|
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import "github.com/casdoor/casdoor/object"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casdoor/casdoor/object"
|
||||||
|
)
|
||||||
|
|
||||||
// GetOidcDiscovery
|
// GetOidcDiscovery
|
||||||
// @Title GetOidcDiscovery
|
// @Title GetOidcDiscovery
|
||||||
@ -42,3 +46,31 @@ func (c *RootController) GetJwks() {
|
|||||||
c.Data["json"] = jwks
|
c.Data["json"] = jwks
|
||||||
c.ServeJSON()
|
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"`
|
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 {
|
func isIpAddress(host string) bool {
|
||||||
// Attempt to split the host and port, ignoring the error
|
// Attempt to split the host and port, ignoring the error
|
||||||
hostWithoutPort, _, err := net.SplitHostPort(host)
|
hostWithoutPort, _, err := net.SplitHostPort(host)
|
||||||
@ -160,3 +172,43 @@ func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
|
|||||||
|
|
||||||
return jwks, nil
|
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/openid-configuration", &controllers.RootController{}, "GET:GetOidcDiscovery")
|
||||||
beego.Router("/.well-known/jwks", &controllers.RootController{}, "*:GetJwks")
|
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/serviceValidate", &controllers.RootController{}, "GET:CasServiceValidate")
|
||||||
beego.Router("/cas/:organization/:application/proxyValidate", &controllers.RootController{}, "GET:CasProxyValidate")
|
beego.Router("/cas/:organization/:application/proxyValidate", &controllers.RootController{}, "GET:CasProxyValidate")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user