2024-01-30 07:57:49 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
"time"
|
2024-03-20 12:56:43 +00:00
|
|
|
|
|
|
|
"git.solsynth.dev/hydrogen/identity/pkg/database"
|
|
|
|
"git.solsynth.dev/hydrogen/identity/pkg/models"
|
|
|
|
"git.solsynth.dev/hydrogen/identity/pkg/security"
|
|
|
|
"git.solsynth.dev/hydrogen/identity/pkg/services"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"github.com/samber/lo"
|
2024-01-30 07:57:49 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func preConnect(c *fiber.Ctx) error {
|
|
|
|
id := c.Query("client_id")
|
|
|
|
redirect := c.Query("redirect_uri")
|
|
|
|
|
2024-02-05 14:47:07 +00:00
|
|
|
if len(id) <= 0 || len(redirect) <= 0 {
|
|
|
|
return fiber.NewError(fiber.StatusBadRequest, "invalid request, missing query parameters")
|
|
|
|
}
|
|
|
|
|
2024-01-30 07:57:49 +00:00
|
|
|
var client models.ThirdClient
|
|
|
|
if err := database.C.Where(&models.ThirdClient{Alias: id}).First(&client).Error; err != nil {
|
|
|
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
|
|
|
} else if !client.IsDraft && !lo.Contains(client.Callbacks, strings.Split(redirect, "?")[0]) {
|
2024-01-30 13:15:15 +00:00
|
|
|
return fiber.NewError(fiber.StatusBadRequest, "invalid callback url")
|
2024-01-30 07:57:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
user := c.Locals("principal").(models.Account)
|
|
|
|
|
|
|
|
var session models.AuthSession
|
|
|
|
if err := database.C.Where(&models.AuthSession{
|
2024-01-30 15:32:21 +00:00
|
|
|
AccountID: user.ID,
|
|
|
|
ClientID: &client.ID,
|
|
|
|
}).Where("last_grant_at IS NULL").First(&session).Error; err == nil {
|
2024-01-30 07:57:49 +00:00
|
|
|
if session.ExpiredAt != nil && session.ExpiredAt.Unix() < time.Now().Unix() {
|
|
|
|
return c.JSON(fiber.Map{
|
|
|
|
"client": client,
|
|
|
|
"session": nil,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
session, err = security.RegenSession(session)
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.JSON(fiber.Map{
|
|
|
|
"client": client,
|
|
|
|
"session": session,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return c.JSON(fiber.Map{
|
|
|
|
"client": client,
|
|
|
|
"session": nil,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func doConnect(c *fiber.Ctx) error {
|
|
|
|
user := c.Locals("principal").(models.Account)
|
|
|
|
id := c.Query("client_id")
|
|
|
|
response := c.Query("response_type")
|
|
|
|
redirect := c.Query("redirect_uri")
|
|
|
|
scope := c.Query("scope")
|
|
|
|
if len(scope) <= 0 {
|
|
|
|
return fiber.NewError(fiber.StatusBadRequest, "invalid request params")
|
|
|
|
}
|
|
|
|
|
|
|
|
var client models.ThirdClient
|
|
|
|
if err := database.C.Where(&models.ThirdClient{Alias: id}).First(&client).Error; err != nil {
|
|
|
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
switch response {
|
|
|
|
case "code":
|
|
|
|
// OAuth Authorization Mode
|
|
|
|
session, err := security.GrantOauthSession(
|
|
|
|
user,
|
|
|
|
client,
|
|
|
|
strings.Split(scope, " "),
|
2024-02-18 03:20:22 +00:00
|
|
|
[]string{"identity", client.Alias},
|
2024-01-30 09:57:23 +00:00
|
|
|
nil,
|
2024-01-30 07:57:49 +00:00
|
|
|
lo.ToPtr(time.Now()),
|
|
|
|
c.IP(),
|
|
|
|
c.Get(fiber.HeaderUserAgent),
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
|
|
} else {
|
2024-01-30 09:57:23 +00:00
|
|
|
services.AddEvent(user, "oauth.connect", client.Alias, c.IP(), c.Get(fiber.HeaderUserAgent))
|
2024-01-30 07:57:49 +00:00
|
|
|
return c.JSON(fiber.Map{
|
|
|
|
"session": session,
|
|
|
|
"redirect_uri": redirect,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
case "token":
|
|
|
|
// OAuth Implicit Mode
|
|
|
|
session, err := security.GrantOauthSession(
|
|
|
|
user,
|
|
|
|
client,
|
|
|
|
strings.Split(scope, " "),
|
2024-02-18 03:20:22 +00:00
|
|
|
[]string{"identity", client.Alias},
|
2024-01-30 09:57:23 +00:00
|
|
|
nil,
|
2024-01-30 07:57:49 +00:00
|
|
|
lo.ToPtr(time.Now()),
|
|
|
|
c.IP(),
|
|
|
|
c.Get(fiber.HeaderUserAgent),
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
|
|
} else if access, refresh, err := security.GetToken(session); err != nil {
|
|
|
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
|
|
|
} else {
|
2024-01-30 09:57:23 +00:00
|
|
|
services.AddEvent(user, "oauth.connect", client.Alias, c.IP(), c.Get(fiber.HeaderUserAgent))
|
2024-01-30 07:57:49 +00:00
|
|
|
return c.JSON(fiber.Map{
|
|
|
|
"access_token": access,
|
|
|
|
"refresh_token": refresh,
|
|
|
|
"redirect_uri": redirect,
|
|
|
|
"session": session,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return fiber.NewError(fiber.StatusBadRequest, "unsupported response type")
|
|
|
|
}
|
|
|
|
}
|