summaryrefslogtreecommitdiff
path: root/internal/handlers/handler_oauth_introspection.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/handlers/handler_oauth_introspection.go')
-rw-r--r--internal/handlers/handler_oauth_introspection.go97
1 files changed, 94 insertions, 3 deletions
diff --git a/internal/handlers/handler_oauth_introspection.go b/internal/handlers/handler_oauth_introspection.go
index 6ef375986..cbb2a4cc3 100644
--- a/internal/handlers/handler_oauth_introspection.go
+++ b/internal/handlers/handler_oauth_introspection.go
@@ -1,10 +1,16 @@
package handlers
import (
+ "encoding/json"
"net/http"
+ "net/url"
+ "time"
"github.com/google/uuid"
"github.com/ory/fosite"
+ "github.com/ory/fosite/token/jwt"
+ "github.com/pkg/errors"
+ "github.com/valyala/fasthttp"
"github.com/authelia/authelia/v4/internal/middlewares"
"github.com/authelia/authelia/v4/internal/oidc"
@@ -38,11 +44,96 @@ func OAuthIntrospectionPOST(ctx *middlewares.AutheliaCtx, rw http.ResponseWriter
return
}
- requester := responder.GetAccessRequester()
+ ctx.Logger.Tracef("Introspection Request with id '%s' yeilded a %s (active: %t) requested at %s created with request id '%s' on client with id '%s'", requestID, responder.GetTokenUse(), responder.IsActive(), responder.GetAccessRequester().GetRequestedAt().String(), responder.GetAccessRequester().GetID(), responder.GetAccessRequester().GetClient().GetID())
- ctx.Logger.Tracef("Introspection Request with id '%s' yeilded a %s (active: %t) requested at %s created with request id '%s' on client with id '%s'", requestID, responder.GetTokenUse(), responder.IsActive(), requester.GetRequestedAt().String(), requester.GetID(), requester.GetClient().GetID())
+ aud, introspection := oidc.IntrospectionResponseToMap(responder)
- ctx.Providers.OpenIDConnect.WriteIntrospectionResponse(ctx, rw, responder)
+ var (
+ client oidc.Client
+ ok bool
+ )
+
+ if client, ok = responder.GetAccessRequester().GetClient().(oidc.Client); !ok {
+ ctx.Logger.Errorf("Introspection Request with id '%s' failed with error: %s", requestID, oidc.ErrorToDebugRFC6749Error(fosite.ErrInvalidClient.WithDebugf("The client does not implement the correct type as it's a '%T'", responder.GetAccessRequester().GetClient())))
+
+ ctx.Providers.OpenIDConnect.WriteIntrospectionError(ctx, rw, fosite.ErrInvalidClient)
+
+ return
+ }
+
+ switch alg := client.GetIntrospectionSignedResponseAlg(); alg {
+ case oidc.SigningAlgNone:
+ rw.Header().Set(fasthttp.HeaderContentType, "application/json; charset=utf-8")
+ rw.Header().Set(fasthttp.HeaderCacheControl, "no-store")
+ rw.Header().Set(fasthttp.HeaderPragma, "no-cache")
+ rw.WriteHeader(http.StatusOK)
+
+ _ = json.NewEncoder(rw).Encode(introspection)
+ default:
+ var (
+ issuer *url.URL
+ token string
+ jwk *oidc.JWK
+ jti uuid.UUID
+ )
+
+ if issuer, err = ctx.IssuerURL(); err != nil {
+ ctx.Logger.WithError(err).Errorf("Error occurred determining issuer")
+
+ ctx.Providers.OpenIDConnect.WriteIntrospectionError(ctx, rw, errors.WithStack(fosite.ErrServerError.WithHint("Failed to lookup required information to perform this request.").WithDebugf("The issuer could not be determined with error %+v.", err)))
+
+ return
+ }
+
+ if jwk = ctx.Providers.OpenIDConnect.KeyManager.Get(ctx, client.GetIntrospectionSignedResponseKeyID(), alg); jwk == nil {
+ ctx.Logger.WithError(err).Errorf("Introspection Request with id '%s' failed to lookup key for key manager due to likely no support for the key algorithm", requestID)
+
+ ctx.Providers.OpenIDConnect.WriteIntrospectionError(ctx, rw, errors.WithStack(fosite.ErrServerError.WithHint("Failed to lookup required information to perform this request.").WithDebugf("The JWK matching algorithm '%s' and key id '%s' could not be found.", alg, client.GetIntrospectionSignedResponseKeyID())))
+
+ return
+ }
+
+ if jti, err = uuid.NewRandom(); err != nil {
+ ctx.Logger.WithError(err).Errorf("Introspection Request with id '%s' failed to generate a JTI", requestID)
+
+ ctx.Providers.OpenIDConnect.WriteIntrospectionError(ctx, rw, errors.WithStack(fosite.ErrServerError.WithHint("Failed to lookup required information to perform this request.").WithDebugf("The JTI could not be generated for the Introspection JWT response type with error %+v.", err)))
+
+ return
+ }
+
+ headers := &jwt.Headers{
+ Extra: map[string]any{
+ oidc.JWTHeaderKeyIdentifier: jwk.KeyID(),
+ oidc.JWTHeaderKeyType: oidc.JWTHeaderTypeValueTokenIntrospectionJWT,
+ },
+ }
+
+ claims := map[string]any{
+ oidc.ClaimJWTID: jti.String(),
+ oidc.ClaimIssuer: issuer,
+ oidc.ClaimIssuedAt: time.Now().UTC().Unix(),
+ oidc.ClaimTokenIntrospection: introspection,
+ }
+
+ if aud != nil {
+ claims[oidc.ClaimAudience] = aud
+ }
+
+ if token, _, err = jwk.Strategy().Generate(ctx, claims, headers); err != nil {
+ ctx.Logger.WithError(err).Errorf("Introspection Request with id '%s' failed to generate the Introspection JWT response", requestID)
+
+ ctx.Providers.OpenIDConnect.WriteIntrospectionError(ctx, rw, errors.WithStack(fosite.ErrServerError.WithHint("Failed to generate the response.").WithDebugf("The Introspection JWT itself could not be generated with error %+v.", err)))
+
+ return
+ }
+
+ rw.Header().Set(fasthttp.HeaderContentType, "application/token-introspection+jwt; charset=utf-8")
+ rw.Header().Set(fasthttp.HeaderCacheControl, "no-store")
+ rw.Header().Set(fasthttp.HeaderPragma, "no-cache")
+ rw.WriteHeader(http.StatusOK)
+
+ _, _ = rw.Write([]byte(token))
+ }
ctx.Logger.Debugf("Introspection Request with id '%s' was processed successfully", requestID)
}