fix: generate valid urls when app url contains a trailing slash (#257)

This commit is contained in:
2025-02-22 14:00:25 +00:00
parent 7446f853fc
commit e40ed50bed
6 changed files with 26 additions and 13 deletions

View File

@@ -1,13 +1,14 @@
package controller
import (
"github.com/pocket-id/pocket-id/backend/internal/common"
"github.com/pocket-id/pocket-id/backend/internal/utils/cookie"
"log"
"net/http"
"net/url"
"strings"
"github.com/pocket-id/pocket-id/backend/internal/common"
"github.com/pocket-id/pocket-id/backend/internal/utils/cookie"
"github.com/gin-gonic/gin"
"github.com/pocket-id/pocket-id/backend/internal/dto"
"github.com/pocket-id/pocket-id/backend/internal/middleware"
@@ -149,7 +150,7 @@ func (oc *OidcController) EndSessionHandler(c *gin.Context) {
if err != nil {
// If the validation fails, the user has to confirm the logout manually and doesn't get redirected
log.Printf("Error getting logout callback URL, the user has to confirm the logout manually: %v", err)
c.Redirect(http.StatusFound, common.EnvConfig.AppURL+"/logout")
c.Redirect(http.StatusFound, utils.GetAbsoluteURL(common.EnvConfig.AppURL, "/logout"))
return
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/pocket-id/pocket-id/backend/internal/common"
"github.com/pocket-id/pocket-id/backend/internal/service"
"github.com/pocket-id/pocket-id/backend/internal/utils"
)
func NewWellKnownController(group *gin.RouterGroup, jwtService *service.JwtService) {
@@ -32,11 +33,11 @@ func (wkc *WellKnownController) openIDConfigurationHandler(c *gin.Context) {
appUrl := common.EnvConfig.AppURL
config := map[string]interface{}{
"issuer": appUrl,
"authorization_endpoint": appUrl + "/authorize",
"token_endpoint": appUrl + "/api/oidc/token",
"userinfo_endpoint": appUrl + "/api/oidc/userinfo",
"end_session_endpoint": appUrl + "/api/oidc/end-session",
"jwks_uri": appUrl + "/.well-known/jwks.json",
"authorization_endpoint": utils.GetAbsoluteURL(appUrl, "/authorize"),
"token_endpoint": utils.GetAbsoluteURL(appUrl, "/api/oidc/token"),
"userinfo_endpoint": utils.GetAbsoluteURL(appUrl, "/api/oidc/userinfo"),
"end_session_endpoint": utils.GetAbsoluteURL(appUrl, "/api/oidc/end-session"),
"jwks_uri": utils.GetAbsoluteURL(appUrl, "/.well-known/jwks.json"),
"scopes_supported": []string{"openid", "profile", "email"},
"claims_supported": []string{"sub", "given_name", "family_name", "name", "email", "email_verified", "preferred_username", "picture"},
"response_types_supported": []string{"code", "id_token"},

View File

@@ -16,6 +16,7 @@ import (
"github.com/pocket-id/pocket-id/backend/internal/common"
"github.com/pocket-id/pocket-id/backend/internal/model"
"github.com/pocket-id/pocket-id/backend/internal/utils"
"github.com/pocket-id/pocket-id/backend/internal/utils/email"
"gorm.io/gorm"
)
@@ -66,7 +67,7 @@ func (srv *EmailService) SendTestEmail(recipientUserId string) error {
func SendEmail[V any](srv *EmailService, toEmail email.Address, template email.Template[V], tData *V) error {
data := &email.TemplateData[V]{
AppName: srv.appConfigService.DbConfig.AppName.Value,
LogoURL: common.EnvConfig.AppURL + "/api/application-configuration/logo",
LogoURL: utils.GetAbsoluteURL(common.EnvConfig.AppURL, "/api/application-configuration/logo"),
Data: tData,
}

View File

@@ -401,7 +401,7 @@ func (s *OidcService) GetUserClaimsForClient(userID string, clientID string) (ma
"family_name": user.LastName,
"name": user.FullName(),
"preferred_username": user.Username,
"picture": fmt.Sprintf("%s/api/users/%s/profile-picture.png", common.EnvConfig.AppURL, user.ID),
"picture": utils.GetAbsoluteURL(common.EnvConfig.AppURL, fmt.Sprintf("/api/users/%s/profile-picture.png", user.ID)),
}
if strings.Contains(scope, "profile") {

View File

@@ -3,8 +3,6 @@ package service
import (
"errors"
"fmt"
"github.com/google/uuid"
"github.com/pocket-id/pocket-id/backend/internal/utils/image"
"io"
"log"
"net/url"
@@ -12,6 +10,9 @@ import (
"strings"
"time"
"github.com/google/uuid"
profilepicture "github.com/pocket-id/pocket-id/backend/internal/utils/image"
"github.com/pocket-id/pocket-id/backend/internal/common"
"github.com/pocket-id/pocket-id/backend/internal/dto"
"github.com/pocket-id/pocket-id/backend/internal/model"
@@ -197,7 +198,7 @@ func (s *UserService) RequestOneTimeAccessEmail(emailAddress, redirectPath strin
return err
}
link := fmt.Sprintf("%s/login/%s", common.EnvConfig.AppURL, oneTimeAccessToken)
link := utils.GetAbsoluteURL(common.EnvConfig.AppURL, fmt.Sprintf("/login/%s", oneTimeAccessToken))
// Add redirect path to the link
if strings.HasPrefix(redirectPath, "/") {

View File

@@ -40,6 +40,15 @@ func GetHostnameFromURL(rawURL string) string {
return parsedURL.Hostname()
}
// Returns an absolute path when provided with a URL (https://test.com) and a path "/.well-known/openid-configuration"
func GetAbsoluteURL(baseURL string, path string) string {
url, err := url.JoinPath(baseURL, path)
if err != nil {
return ""
}
return url
}
// StringPointer creates a string pointer from a string value
func StringPointer(s string) *string {
return &s