mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-06-23 20:00:24 +00:00
chore: rabbit comments
This commit is contained in:
@@ -109,7 +109,10 @@ export const QuickActions = () => {
|
|||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<button className="rounded-full transition-transform duration-200 will-change-transform hover:scale-105 hover:cursor-pointer focus:ring-0 focus:outline-3 focus:outline-ring/50">
|
<button
|
||||||
|
aria-label={t("quickActionsTitle")}
|
||||||
|
className="rounded-full transition-transform duration-200 will-change-transform hover:scale-105 hover:cursor-pointer focus:ring-0 focus:outline-3 focus:outline-ring/50"
|
||||||
|
>
|
||||||
{auth.authenticated ? (
|
{auth.authenticated ? (
|
||||||
<Avatar initial={initial!} />
|
<Avatar initial={initial!} />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function useScreenParams(params: URLSearchParams): ScreenParams {
|
|||||||
export function recompileScreenParams(params: ScreenParams): string {
|
export function recompileScreenParams(params: ScreenParams): string {
|
||||||
const p = new URLSearchParams(
|
const p = new URLSearchParams(
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
Object.entries(params).filter(([, v]) => v !== null),
|
Object.entries(params).filter(([, v]) => v != null),
|
||||||
) as Record<string, string>,
|
) as Record<string, string>,
|
||||||
).toString();
|
).toString();
|
||||||
|
|
||||||
|
|||||||
@@ -98,5 +98,6 @@
|
|||||||
"quickActionsThemeLight": "Light",
|
"quickActionsThemeLight": "Light",
|
||||||
"quickActionsThemeDark": "Dark",
|
"quickActionsThemeDark": "Dark",
|
||||||
"quickActionsThemeSystem": "System",
|
"quickActionsThemeSystem": "System",
|
||||||
"quickActionsLogout": "Logout"
|
"quickActionsLogout": "Logout",
|
||||||
|
"quickActionsTitle": "Quick Actions"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,5 +98,6 @@
|
|||||||
"quickActionsThemeLight": "Light",
|
"quickActionsThemeLight": "Light",
|
||||||
"quickActionsThemeDark": "Dark",
|
"quickActionsThemeDark": "Dark",
|
||||||
"quickActionsThemeSystem": "System",
|
"quickActionsThemeSystem": "System",
|
||||||
"quickActionsLogout": "Logout"
|
"quickActionsLogout": "Logout",
|
||||||
|
"quickActionsTitle": "Quick Actions"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export const TotpPage = () => {
|
|||||||
if (auth.authenticated) {
|
if (auth.authenticated) {
|
||||||
return <Navigate to={loginForUrl} replace />;
|
return <Navigate to={loginForUrl} replace />;
|
||||||
}
|
}
|
||||||
return <Navigate to="/login" replace />;
|
return <Navigate to={`/login${compiledParams}`} replace />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -115,37 +115,16 @@ func (controller *OIDCController) authorize(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
reqQueries := c.Request.URL.Query()
|
req, err := controller.resolveAuthorizeRequest(c)
|
||||||
|
|
||||||
var req service.AuthorizeRequest
|
if err != nil {
|
||||||
|
controller.log.App.Warn().Err(err).Msg("Failed to resolve authorize request")
|
||||||
// step 1: if we have a request object, decode it and ignore other params. If not, bind the params as usual
|
controller.authorizeError(c, authorizeErrorParams{
|
||||||
if raw := reqQueries.Get("request"); raw != "" {
|
err: err,
|
||||||
requestObject, err := controller.oidc.DecodeAuthorizeJWT(raw)
|
reason: "Failed to resolve authorize request",
|
||||||
if err != nil {
|
reasonPublic: "The authorization request is invalid",
|
||||||
controller.authorizeError(c, authorizeErrorParams{
|
})
|
||||||
err: err,
|
return
|
||||||
reason: "Failed to decode request object",
|
|
||||||
reasonPublic: "The client provided an invalid request object",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req = *requestObject
|
|
||||||
} else {
|
|
||||||
// step 2: by default we assume normal GET query parameters
|
|
||||||
bind := binding.Query
|
|
||||||
// step 3: if it's a POST request, we try form parameters
|
|
||||||
if c.Request.Method == http.MethodPost {
|
|
||||||
bind = binding.Form
|
|
||||||
}
|
|
||||||
if err := c.ShouldBindWith(&req, bind); err != nil {
|
|
||||||
controller.authorizeError(c, authorizeErrorParams{
|
|
||||||
err: err,
|
|
||||||
reason: "Failed to bind request parameters",
|
|
||||||
reasonPublic: "The client provided invalid parameters",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client, ok := controller.oidc.GetClient(req.ClientID)
|
client, ok := controller.oidc.GetClient(req.ClientID)
|
||||||
@@ -159,7 +138,7 @@ func (controller *OIDCController) authorize(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := controller.oidc.ValidateAuthorizeParams(req)
|
err = controller.oidc.ValidateAuthorizeParams(*req)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
controller.log.App.Warn().Err(err).Msg("Failed to validate authorize params")
|
controller.log.App.Warn().Err(err).Msg("Failed to validate authorize params")
|
||||||
@@ -182,7 +161,7 @@ func (controller *OIDCController) authorize(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ticket := controller.oidc.CreateAuthorizeRequestTicket(req)
|
ticket := controller.oidc.CreateAuthorizeRequestTicket(*req)
|
||||||
|
|
||||||
queries, err := query.Values(AuthorizeScreenParams{
|
queries, err := query.Values(AuthorizeScreenParams{
|
||||||
LoginFor: FrontendLoginForOIDC,
|
LoginFor: FrontendLoginForOIDC,
|
||||||
@@ -284,6 +263,7 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) {
|
|||||||
callback: authorizeReq.RedirectURI,
|
callback: authorizeReq.RedirectURI,
|
||||||
callbackError: "server_error",
|
callbackError: "server_error",
|
||||||
state: authorizeReq.State,
|
state: authorizeReq.State,
|
||||||
|
json: true,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -304,6 +284,7 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) {
|
|||||||
callback: authorizeReq.RedirectURI,
|
callback: authorizeReq.RedirectURI,
|
||||||
callbackError: "server_error",
|
callbackError: "server_error",
|
||||||
state: authorizeReq.State,
|
state: authorizeReq.State,
|
||||||
|
json: true,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -650,3 +631,51 @@ func (controller *OIDCController) authorizeError(c *gin.Context, params authoriz
|
|||||||
|
|
||||||
c.Redirect(http.StatusFound, redirectUrl)
|
c.Redirect(http.StatusFound, redirectUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (controller *OIDCController) resolveAuthorizeRequest(c *gin.Context) (*service.AuthorizeRequest, error) {
|
||||||
|
// step 1: if we have a request object, decode it and ignore other params. If not, bind the params as usual
|
||||||
|
// we check both query and form parameters for the request object since this endpoint can be called with both GET and POST
|
||||||
|
requestObject, err := controller.resolveRequestObject(c)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestObject != nil {
|
||||||
|
return requestObject, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 2: by default we assume normal GET query parameters
|
||||||
|
// step 3: if it's a POST request, we try form parameters
|
||||||
|
return controller.resolveNormalParams(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (controller *OIDCController) resolveRequestObject(c *gin.Context) (*service.AuthorizeRequest, error) {
|
||||||
|
raw := c.Query("request")
|
||||||
|
|
||||||
|
if raw == "" && c.Request.Method == http.MethodPost {
|
||||||
|
raw = c.PostForm("request")
|
||||||
|
}
|
||||||
|
|
||||||
|
if raw == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return controller.oidc.DecodeAuthorizeJWT(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (controller *OIDCController) resolveNormalParams(c *gin.Context) (*service.AuthorizeRequest, error) {
|
||||||
|
var req service.AuthorizeRequest
|
||||||
|
|
||||||
|
bind := binding.Query
|
||||||
|
|
||||||
|
if c.Request.Method == http.MethodPost {
|
||||||
|
bind = binding.Form
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.ShouldBindWith(&req, bind); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &req, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ func TestOIDCController(t *testing.T) {
|
|||||||
assert.Equal(t, http.StatusFound, recorder.Code)
|
assert.Equal(t, http.StatusFound, recorder.Code)
|
||||||
location := recorder.Header().Get("Location")
|
location := recorder.Header().Get("Location")
|
||||||
assert.Contains(t, location, oidcService.GetIssuer()+"/error")
|
assert.Contains(t, location, oidcService.GetIssuer()+"/error")
|
||||||
assert.Contains(t, location, url.QueryEscape("The client provided an invalid request object"))
|
assert.Contains(t, location, url.QueryEscape("The authorization request is invalid"))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
assert.Equal(t, 307, recorder.Code)
|
assert.Equal(t, 307, recorder.Code)
|
||||||
location := recorder.Header().Get("Location")
|
location := recorder.Header().Get("Location")
|
||||||
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
||||||
assert.Contains(t, location, url.QueryEscape("app")) // login_for=app
|
assert.Contains(t, location, "login_for=app")
|
||||||
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -93,7 +93,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
assert.Equal(t, 401, recorder.Code)
|
assert.Equal(t, 401, recorder.Code)
|
||||||
location := recorder.Header().Get("x-tinyauth-location")
|
location := recorder.Header().Get("x-tinyauth-location")
|
||||||
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
||||||
assert.Contains(t, location, url.QueryEscape("app")) // login_for=app
|
assert.Contains(t, location, "login_for=app")
|
||||||
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -109,7 +109,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
assert.Equal(t, 307, recorder.Code)
|
assert.Equal(t, 307, recorder.Code)
|
||||||
location := recorder.Header().Get("Location")
|
location := recorder.Header().Get("Location")
|
||||||
assert.Contains(t, location, url.QueryEscape("https://test.example.com/hello"))
|
assert.Contains(t, location, url.QueryEscape("https://test.example.com/hello"))
|
||||||
assert.Contains(t, location, url.QueryEscape("app")) // login_for=app
|
assert.Contains(t, location, "login_for=app")
|
||||||
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -127,7 +127,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
assert.Equal(t, 307, recorder.Code)
|
assert.Equal(t, 307, recorder.Code)
|
||||||
location := recorder.Header().Get("Location")
|
location := recorder.Header().Get("Location")
|
||||||
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
||||||
assert.Contains(t, location, url.QueryEscape("app")) // login_for=app
|
assert.Contains(t, location, "login_for=app")
|
||||||
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -144,7 +144,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
assert.Equal(t, 401, recorder.Code)
|
assert.Equal(t, 401, recorder.Code)
|
||||||
location := recorder.Header().Get("x-tinyauth-location")
|
location := recorder.Header().Get("x-tinyauth-location")
|
||||||
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
||||||
assert.Contains(t, location, url.QueryEscape("app")) // login_for=app
|
assert.Contains(t, location, "login_for=app")
|
||||||
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -162,7 +162,7 @@ func TestProxyController(t *testing.T) {
|
|||||||
assert.Equal(t, 307, recorder.Code)
|
assert.Equal(t, 307, recorder.Code)
|
||||||
location := recorder.Header().Get("Location")
|
location := recorder.Header().Get("Location")
|
||||||
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
assert.Contains(t, location, url.QueryEscape("https://test.example.com/"))
|
||||||
assert.Contains(t, location, url.QueryEscape("app")) // login_for=app
|
assert.Contains(t, location, "login_for=app")
|
||||||
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
assert.Contains(t, location, "https://tinyauth.example.com/login")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user