summaryrefslogtreecommitdiff
path: root/internal/handlers/response.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/handlers/response.go')
-rw-r--r--internal/handlers/response.go105
1 files changed, 46 insertions, 59 deletions
diff --git a/internal/handlers/response.go b/internal/handlers/response.go
index f4112fc6f..107aaf5b3 100644
--- a/internal/handlers/response.go
+++ b/internal/handlers/response.go
@@ -3,7 +3,6 @@ package handlers
import (
"fmt"
"net/url"
- "path"
"time"
"github.com/google/uuid"
@@ -129,51 +128,7 @@ func Handle2FAResponse(ctx *middlewares.AutheliaCtx, targetURI string) {
ctx.ReplyOK()
}
-// handleOIDCWorkflowResponse handle the redirection upon authentication in the OIDC workflow.
-func handleOIDCWorkflowResponse(ctx *middlewares.AutheliaCtx, userSession *session.UserSession, targetURI, workflowID string) {
- switch {
- case len(workflowID) != 0:
- handleOIDCWorkflowResponseWithID(ctx, userSession, workflowID)
- case len(targetURI) != 0:
- handleOIDCWorkflowResponseWithTargetURL(ctx, userSession, targetURI)
- default:
- ctx.Error(fmt.Errorf("invalid post data: must contain either a target url or a workflow id"), messageAuthenticationFailed)
- }
-}
-
-func handleOIDCWorkflowResponseWithTargetURL(ctx *middlewares.AutheliaCtx, userSession *session.UserSession, targetURI string) {
- var (
- issuerURL *url.URL
- targetURL *url.URL
- err error
- )
-
- if targetURL, err = url.ParseRequestURI(targetURI); err != nil {
- ctx.Error(fmt.Errorf("unable to parse target URL '%s': %w", targetURI, err), messageAuthenticationFailed)
-
- return
- }
-
- issuerURL = ctx.RootURL()
-
- if targetURL.Host != issuerURL.Host {
- ctx.Error(fmt.Errorf("unable to redirect to '%s': target host '%s' does not match expected issuer host '%s'", targetURL, targetURL.Host, issuerURL.Host), messageAuthenticationFailed)
-
- return
- }
-
- if userSession.IsAnonymous() {
- ctx.Error(fmt.Errorf("unable to redirect to '%s': user is anonymous", targetURL), messageAuthenticationFailed)
-
- return
- }
-
- if err = ctx.SetJSONBody(redirectResponse{Redirect: targetURL.String()}); err != nil {
- ctx.Logger.Errorf("Unable to set default redirection URL in body: %s", err)
- }
-}
-
-func handleOIDCWorkflowResponseWithID(ctx *middlewares.AutheliaCtx, userSession *session.UserSession, id string) {
+func handleOIDCWorkflowResponse(ctx *middlewares.AutheliaCtx, userSession *session.UserSession, id string) {
var (
workflowID uuid.UUID
client oidc.Client
@@ -194,7 +149,7 @@ func handleOIDCWorkflowResponseWithID(ctx *middlewares.AutheliaCtx, userSession
}
if consent.Responded() {
- ctx.Error(fmt.Errorf("consent has already been responded to '%s': %w", id, err), messageAuthenticationFailed)
+ ctx.Error(fmt.Errorf("consent has already been responded to '%s'", id), messageAuthenticationFailed)
return
}
@@ -211,26 +166,58 @@ func handleOIDCWorkflowResponseWithID(ctx *middlewares.AutheliaCtx, userSession
return
}
- level := client.GetAuthorizationPolicyRequiredLevel(authorization.Subject{Username: userSession.Username, Groups: userSession.Groups, IP: ctx.RemoteIP()})
+ if !consent.Subject.Valid {
+ if consent.Subject.UUID, err = ctx.Providers.OpenIDConnect.GetSubject(ctx, client.GetSectorIdentifierURI(), userSession.Username); err != nil {
+ ctx.Error(fmt.Errorf("unable to determine consent subject for client with id '%s' with consent challenge id '%s': %w", client.GetID(), consent.ChallengeID, err), messageAuthenticationFailed)
- switch {
- case authorization.IsAuthLevelSufficient(userSession.AuthenticationLevel, level), level == authorization.Denied:
- var (
- targetURL *url.URL
- form url.Values
- )
+ return
+ }
- targetURL = ctx.RootURL()
+ consent.Subject.Valid = true
- if form, err = consent.GetForm(); err != nil {
- ctx.Error(fmt.Errorf("unable to get authorization form values from consent session with challenge id '%s': %w", consent.ChallengeID, err), messageAuthenticationFailed)
+ if err = ctx.Providers.StorageProvider.SaveOAuth2ConsentSessionSubject(ctx, consent); err != nil {
+ ctx.Error(fmt.Errorf("unable to update consent subject for client with id '%s' with consent challenge id '%s': %w", client.GetID(), consent.ChallengeID, err), messageAuthenticationFailed)
return
}
+ }
- form.Set(queryArgConsentID, workflowID.String())
+ var (
+ issuer *url.URL
+ form url.Values
+ )
+
+ issuer = ctx.RootURL()
+
+ if form, err = consent.GetForm(); err != nil {
+ ctx.Error(fmt.Errorf("unable to get authorization form values from consent session with challenge id '%s': %w", consent.ChallengeID, err), messageAuthenticationFailed)
+
+ return
+ }
+
+ if oidc.RequestFormRequiresLogin(form, consent.RequestedAt, userSession.LastAuthenticatedTime()) {
+ targetURL := issuer.JoinPath(oidc.EndpointPathConsentLogin)
+
+ query := targetURL.Query()
+ query.Set(queryArgWorkflow, workflowOpenIDConnect)
+ query.Set(queryArgWorkflowID, workflowID.String())
- targetURL.Path = path.Join(targetURL.Path, oidc.EndpointPathAuthorization)
+ targetURL.RawQuery = query.Encode()
+
+ if err = ctx.SetJSONBody(redirectResponse{Redirect: targetURL.String()}); err != nil {
+ ctx.Logger.Errorf("Unable to set default redirection URL in body: %s", err)
+ }
+
+ return
+ }
+
+ level := client.GetAuthorizationPolicyRequiredLevel(authorization.Subject{Username: userSession.Username, Groups: userSession.Groups, IP: ctx.RemoteIP()})
+
+ switch {
+ case authorization.IsAuthLevelSufficient(userSession.AuthenticationLevel, level), level == authorization.Denied:
+ targetURL := issuer.JoinPath(oidc.EndpointPathAuthorization)
+
+ form.Set(queryArgConsentID, workflowID.String())
targetURL.RawQuery = form.Encode()
if err = ctx.SetJSONBody(redirectResponse{Redirect: targetURL.String()}); err != nil {