234 lines
6.4 KiB
Go
234 lines
6.4 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"oc-auth/conf"
|
|
"oc-auth/infrastructure"
|
|
auth_connectors "oc-auth/infrastructure/auth_connector"
|
|
"regexp"
|
|
"strings"
|
|
|
|
oclib "cloud.o-forge.io/core/oc-lib"
|
|
model "cloud.o-forge.io/core/oc-lib/models/peer"
|
|
beego "github.com/beego/beego/v2/server/web"
|
|
)
|
|
|
|
// Operations about auth
|
|
type OAuthController struct {
|
|
beego.Controller
|
|
}
|
|
|
|
// @Title Logout
|
|
// @Description unauthenticate user
|
|
// @Param Authorization header string false "auth token"
|
|
// @Param client_id query string true "the client_id you want to get"
|
|
// @Success 200 {string}
|
|
// @router /logout [delete]
|
|
func (o *OAuthController) LogOut() {
|
|
// authorize user
|
|
clientID := o.Ctx.Input.Query("client_id")
|
|
reqToken := o.Ctx.Request.Header.Get("Authorization")
|
|
splitToken := strings.Split(reqToken, "Bearer ")
|
|
if len(splitToken) < 2 {
|
|
reqToken = ""
|
|
} else {
|
|
reqToken = splitToken[1]
|
|
}
|
|
var res auth_connectors.Token
|
|
json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res)
|
|
|
|
token, err := infrastructure.GetAuthConnector().Logout(clientID, reqToken)
|
|
if err != nil || token == nil {
|
|
o.Data["json"] = err
|
|
} else {
|
|
o.Data["json"] = token
|
|
}
|
|
o.ServeJSON()
|
|
}
|
|
|
|
// @Title Login
|
|
// @Description authenticate user
|
|
// @Param body body models.workflow true "The workflow content"
|
|
// @Param client_id query string true "the client_id you want to get"
|
|
// @Success 200 {string}
|
|
// @router /login [post]
|
|
func (o *OAuthController) Login() {
|
|
// authorize user
|
|
fmt.Println("Login", o.Ctx.Input.Query("client_id"), o.Ctx.Input.Param(":client_id"))
|
|
clientID := o.Ctx.Input.Query("client_id")
|
|
var res auth_connectors.Token
|
|
json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &res)
|
|
if conf.GetConfig().SourceMode == "ldap" {
|
|
ldap := auth_connectors.New()
|
|
found, err := ldap.Authenticate(o.Ctx.Request.Context(), res.Username, res.Password)
|
|
fmt.Println("found", found, "err", err)
|
|
if err != nil || !found {
|
|
o.Data["json"] = err
|
|
o.Ctx.ResponseWriter.WriteHeader(401)
|
|
o.ServeJSON()
|
|
return
|
|
}
|
|
}
|
|
token, err := infrastructure.GetAuthConnector().Login(
|
|
clientID, res.Username,
|
|
&http.Cookie{ // open a session
|
|
Name: "csrf_token",
|
|
Value: o.XSRFToken(),
|
|
})
|
|
fmt.Println("token", token, "err", err)
|
|
if err != nil || token == nil {
|
|
o.Data["json"] = err
|
|
o.Ctx.ResponseWriter.WriteHeader(401)
|
|
} else {
|
|
o.Data["json"] = token
|
|
}
|
|
o.ServeJSON()
|
|
}
|
|
|
|
// @Title Introspection
|
|
// @Description introspect token
|
|
// @Param body body models.Token true "The token info"
|
|
// @Param client_id query string true "the client_id you want to get"
|
|
// @Success 200 {string}
|
|
// @router /refresh [post]
|
|
func (o *OAuthController) Refresh() {
|
|
clientID := o.Ctx.Input.Query("client_id")
|
|
var token auth_connectors.Token
|
|
json.Unmarshal(o.Ctx.Input.CopyBody(100000), &token)
|
|
// refresh token
|
|
newToken, err := infrastructure.GetAuthConnector().Refresh(clientID, &token)
|
|
if err != nil || newToken == nil {
|
|
o.Data["json"] = err
|
|
o.Ctx.ResponseWriter.WriteHeader(401)
|
|
} else {
|
|
o.Data["json"] = newToken
|
|
}
|
|
o.ServeJSON()
|
|
}
|
|
|
|
// @Title Introspection
|
|
// @Description introspect token
|
|
// @Param Authorization header string false "auth token"
|
|
// @Success 200 {string}
|
|
// @router /introspect [get]
|
|
func (o *OAuthController) Introspect() {
|
|
reqToken := o.Ctx.Request.Header.Get("Authorization")
|
|
splitToken := strings.Split(reqToken, "Bearer ")
|
|
if len(splitToken) < 2 {
|
|
reqToken = ""
|
|
} else {
|
|
reqToken = splitToken[1]
|
|
}
|
|
|
|
token, err := infrastructure.GetAuthConnector().Introspect(reqToken)
|
|
if err != nil || !token {
|
|
o.Data["json"] = err
|
|
o.Ctx.ResponseWriter.WriteHeader(401)
|
|
}
|
|
o.ServeJSON()
|
|
}
|
|
|
|
var whitelist = []string{
|
|
"/login",
|
|
"/refresh",
|
|
"/introspect",
|
|
}
|
|
|
|
// @Title AuthForward
|
|
// @Description auth forward
|
|
// @Param Authorization header string false "auth token"
|
|
// @Success 200 {string}
|
|
// @router /forward [get]
|
|
func (o *OAuthController) InternaisDraftlAuthForward() {
|
|
fmt.Println("InternalAuthForward")
|
|
reqToken := o.Ctx.Request.Header.Get("Authorization")
|
|
if reqToken == "" {
|
|
for _, w := range whitelist {
|
|
if strings.Contains(o.Ctx.Request.Header.Get("X-Forwarded-Uri"), w) {
|
|
o.Ctx.ResponseWriter.WriteHeader(200)
|
|
o.ServeJSON()
|
|
return
|
|
}
|
|
}
|
|
o.Ctx.ResponseWriter.WriteHeader(401)
|
|
o.ServeJSON()
|
|
return
|
|
}
|
|
splitToken := strings.Split(reqToken, "Bearer ")
|
|
if len(splitToken) < 2 {
|
|
reqToken = ""
|
|
} else {
|
|
reqToken = splitToken[1]
|
|
}
|
|
origin, publicKey, external := o.extractOrigin(o.Ctx.Request)
|
|
if !infrastructure.GetAuthConnector().CheckAuthForward( //reqToken != "" &&
|
|
reqToken, publicKey, origin,
|
|
o.Ctx.Request.Header.Get("X-Forwarded-Method"),
|
|
o.Ctx.Request.Header.Get("X-Forwarded-Uri"), external) && origin != "" && publicKey != "" {
|
|
o.Ctx.ResponseWriter.WriteHeader(401)
|
|
o.ServeJSON()
|
|
return
|
|
}
|
|
o.ServeJSON()
|
|
}
|
|
|
|
func (o *OAuthController) extractOrigin(request *http.Request) (string, string, bool) {
|
|
user, peerID, groups := oclib.ExtractTokenInfo(*request)
|
|
external := true
|
|
publicKey := ""
|
|
origin := o.Ctx.Request.Header.Get("X-Forwarded-Host")
|
|
if origin == "" {
|
|
origin = o.Ctx.Request.Header.Get("Origin")
|
|
}
|
|
searchStr := origin
|
|
r := regexp.MustCompile("(:[0-9]+)")
|
|
t := r.FindString(searchStr)
|
|
if t != "" {
|
|
searchStr = strings.Replace(searchStr, t, "", -1)
|
|
}
|
|
peer := oclib.NewRequest(oclib.LibDataEnum(oclib.PEER), user, peerID, groups, nil).Search(nil, searchStr, false)
|
|
if peer.Code != 200 || len(peer.Data) == 0 { // TODO: add state of partnership
|
|
return "", "", external
|
|
}
|
|
p := peer.Data[0].(*model.Peer)
|
|
publicKey = p.PublicKey
|
|
origin = p.Url
|
|
if origin != "" { // is external
|
|
if strings.Contains(origin, "localhost") || strings.Contains(origin, "127.0.0.1") || p.State == model.SELF {
|
|
external = false
|
|
}
|
|
} else {
|
|
external = false
|
|
}
|
|
return origin, publicKey, external
|
|
}
|
|
|
|
func ExtractClient(request http.Request) string {
|
|
reqToken := request.Header.Get("Authorization")
|
|
splitToken := strings.Split(reqToken, "Bearer ")
|
|
if len(splitToken) < 2 {
|
|
reqToken = ""
|
|
} else {
|
|
reqToken = splitToken[1]
|
|
}
|
|
if reqToken != "" {
|
|
token := strings.Split(reqToken, ".")
|
|
if len(token) > 2 {
|
|
bytes, err := base64.StdEncoding.DecodeString(token[2])
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
m := map[string]interface{}{}
|
|
err = json.Unmarshal(bytes, &m)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return m["session"].(map[string]interface{})["id_token"].(map[string]interface{})["client_id"].(string)
|
|
}
|
|
}
|
|
return ""
|
|
}
|