diff --git a/internal/app/api/core/assets/doc/v0_swagger.json b/internal/app/api/core/assets/doc/v0_swagger.json index 0658046..e7bd238 100644 --- a/internal/app/api/core/assets/doc/v0_swagger.json +++ b/internal/app/api/core/assets/doc/v0_swagger.json @@ -57,6 +57,52 @@ } } }, + "/auth/login/{provider}/callback": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Authentication" + ], + "summary": "Handle the OAuth callback.", + "operationId": "auth_handleOauthCallbackGet", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.LoginProviderInfo" + } + } + } + } + } + }, + "/auth/login/{provider}/init": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Authentication" + ], + "summary": "Initiate the OAuth login flow.", + "operationId": "auth_handleOauthInitiateGet", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/model.LoginProviderInfo" + } + } + } + } + } + }, "/auth/logout": { "post": { "produces": [ @@ -275,52 +321,6 @@ } } }, - "/auth/{provider}/callback": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Authentication" - ], - "summary": "Handle the OAuth callback.", - "operationId": "auth_handleOauthCallbackGet", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.LoginProviderInfo" - } - } - } - } - } - }, - "/auth/{provider}/init": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Authentication" - ], - "summary": "Initiate the OAuth login flow.", - "operationId": "auth_handleOauthInitiateGet", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.LoginProviderInfo" - } - } - } - } - } - }, "/config/frontend.js": { "get": { "produces": [ @@ -2234,6 +2234,9 @@ "MailLinkOnly": { "type": "boolean" }, + "MinPasswordLength": { + "type": "integer" + }, "PersistentConfigSupported": { "type": "boolean" }, diff --git a/internal/app/api/core/assets/doc/v0_swagger.yaml b/internal/app/api/core/assets/doc/v0_swagger.yaml index e8778b2..a76b5ca 100644 --- a/internal/app/api/core/assets/doc/v0_swagger.yaml +++ b/internal/app/api/core/assets/doc/v0_swagger.yaml @@ -383,6 +383,8 @@ definitions: type: boolean MailLinkOnly: type: boolean + MinPasswordLength: + type: integer PersistentConfigSupported: type: boolean SelfProvisioning: @@ -472,7 +474,22 @@ paths: summary: Get all available audit entries. Ordered by timestamp. tags: - Audit - /auth/{provider}/callback: + /auth/login: + post: + operationId: auth_handleLoginPost + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/model.LoginProviderInfo' + type: array + summary: Get all available external login providers. + tags: + - Authentication + /auth/login/{provider}/callback: get: operationId: auth_handleOauthCallbackGet produces: @@ -487,7 +504,7 @@ paths: summary: Handle the OAuth callback. tags: - Authentication - /auth/{provider}/init: + /auth/login/{provider}/init: get: operationId: auth_handleOauthInitiateGet produces: @@ -502,21 +519,6 @@ paths: summary: Initiate the OAuth login flow. tags: - Authentication - /auth/login: - post: - operationId: auth_handleLoginPost - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/model.LoginProviderInfo' - type: array - summary: Get all available external login providers. - tags: - - Authentication /auth/logout: post: operationId: auth_handleLogoutPost diff --git a/internal/app/api/v0/handlers/endpoint_authentication.go b/internal/app/api/v0/handlers/endpoint_authentication.go index de412e3..26532b0 100644 --- a/internal/app/api/v0/handlers/endpoint_authentication.go +++ b/internal/app/api/v0/handlers/endpoint_authentication.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "log/slog" "net/http" "net/url" "strconv" @@ -189,7 +190,7 @@ func (e AuthEndpoint) handleSessionInfoGet() http.HandlerFunc { // @Summary Initiate the OAuth login flow. // @Produce json // @Success 200 {object} []model.LoginProviderInfo -// @Router /auth/{provider}/init [get] +// @Router /auth/login/{provider}/init [get] func (e AuthEndpoint) handleOauthInitiateGet() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { currentSession := e.session.GetData(r.Context()) @@ -234,6 +235,8 @@ func (e AuthEndpoint) handleOauthInitiateGet() http.HandlerFunc { authCodeUrl, state, nonce, err := e.authService.OauthLoginStep1(context.Background(), provider) if err != nil { + slog.Debug("failed to create oauth auth code URL", + "provider", provider, "error", err) if autoRedirect && e.isValidReturnUrl(returnTo) { redirectToReturn() } else { @@ -268,7 +271,7 @@ func (e AuthEndpoint) handleOauthInitiateGet() http.HandlerFunc { // @Summary Handle the OAuth callback. // @Produce json // @Success 200 {object} []model.LoginProviderInfo -// @Router /auth/{provider}/callback [get] +// @Router /auth/login/{provider}/callback [get] func (e AuthEndpoint) handleOauthCallbackGet() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { currentSession := e.session.GetData(r.Context()) @@ -306,6 +309,8 @@ func (e AuthEndpoint) handleOauthCallbackGet() http.HandlerFunc { oauthState := request.Query(r, "state") if provider != currentSession.OauthProvider { + slog.Debug("invalid oauth provider in callback", + "expected", currentSession.OauthProvider, "got", provider, "state", oauthState) if returnUrl != nil && e.isValidReturnUrl(returnUrl.String()) { redirectToReturn() } else { @@ -315,6 +320,8 @@ func (e AuthEndpoint) handleOauthCallbackGet() http.HandlerFunc { return } if oauthState != currentSession.OauthState { + slog.Debug("invalid oauth state in callback", + "expected", currentSession.OauthState, "got", oauthState, "provider", provider) if returnUrl != nil && e.isValidReturnUrl(returnUrl.String()) { redirectToReturn() } else { @@ -324,11 +331,13 @@ func (e AuthEndpoint) handleOauthCallbackGet() http.HandlerFunc { return } - loginCtx, cancel := context.WithTimeout(context.Background(), 1000*time.Second) + loginCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // avoid long waits user, err := e.authService.OauthLoginStep2(loginCtx, provider, currentSession.OauthNonce, oauthCode) cancel() if err != nil { + slog.Debug("failed to process oauth code", + "provider", provider, "state", oauthState, "error", err) if returnUrl != nil && e.isValidReturnUrl(returnUrl.String()) { redirectToReturn() } else {