authelia/internal/handlers/handler_oidc_userinfo.go
Clément Michaud 92d328926d
refactor(handlers): lower case error messages (#2289)
* refactor(handlers): lower case error messages

also refactor verifyAuth function to detect malicious activity both with session
cookie and authorization header.

* refacto(handlers): simplify error construction

* fix(handlers): check prefix in authorization header to determine auth method

* fix(handlers): determining the method should be done with headers instead of query arg

* refacto(handlers): rollback changes of verifyAuth

* don't lowercase log messages

* Apply suggestions from code review

Make sure logger errors are not lowercased.

* fix: uppercase logger errors and remove unused param

* Do not lowercase logger errors
* Remove unused param targetURL
* Rename url variable to not conflict with imported package

Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
2021-09-17 15:53:40 +10:00

89 lines
2.6 KiB
Go

package handlers
import (
"fmt"
"net/http"
"time"
"github.com/google/uuid"
"github.com/ory/fosite"
"github.com/ory/fosite/token/jwt"
"github.com/pkg/errors"
"github.com/authelia/authelia/v4/internal/middlewares"
"github.com/authelia/authelia/v4/internal/oidc"
)
func oidcUserinfo(ctx *middlewares.AutheliaCtx, rw http.ResponseWriter, req *http.Request) {
session := newOpenIDSession("")
tokenType, ar, err := ctx.Providers.OpenIDConnect.Fosite.IntrospectToken(req.Context(), fosite.AccessTokenFromRequest(req), fosite.AccessToken, session)
if err != nil {
rfc := fosite.ErrorToRFC6749Error(err)
if rfc.StatusCode() == http.StatusUnauthorized {
rw.Header().Set("WWW-Authenticate", fmt.Sprintf("error=%s,error_description=%s", rfc.ErrorField, rfc.GetDescription()))
}
ctx.Providers.OpenIDConnect.WriteError(rw, req, err)
return
}
if tokenType != fosite.AccessToken {
errStr := "authorization header must contain an OAuth access token."
rw.Header().Set("WWW-Authenticate", fmt.Sprintf("error_description=\"%s\"", errStr))
ctx.Providers.OpenIDConnect.WriteErrorCode(rw, req, http.StatusUnauthorized, errors.New(errStr))
return
}
client, ok := ar.GetClient().(*oidc.InternalClient)
if !ok {
ctx.Providers.OpenIDConnect.WriteError(rw, req, errors.WithStack(fosite.ErrServerError.WithHint("Unable to assert type of client")))
return
}
claims := ar.GetSession().(*oidc.OpenIDSession).IDTokenClaims().ToMap()
delete(claims, "jti")
delete(claims, "sid")
delete(claims, "at_hash")
delete(claims, "c_hash")
delete(claims, "exp")
delete(claims, "nonce")
if audience, ok := claims["aud"].([]string); !ok || len(audience) == 0 {
claims["aud"] = []string{client.GetID()}
}
switch client.UserinfoSigningAlgorithm {
case "RS256":
claims["jti"] = uuid.New()
claims["iat"] = time.Now().Unix()
keyID, err := ctx.Providers.OpenIDConnect.KeyManager.Strategy().GetPublicKeyID(req.Context())
if err != nil {
ctx.Providers.OpenIDConnect.WriteError(rw, req, err)
return
}
token, _, err := ctx.Providers.OpenIDConnect.KeyManager.Strategy().Generate(req.Context(), claims,
&jwt.Headers{
Extra: map[string]interface{}{"kid": keyID},
})
if err != nil {
ctx.Providers.OpenIDConnect.WriteError(rw, req, err)
return
}
rw.Header().Set("Content-Type", "application/jwt")
_, _ = rw.Write([]byte(token))
case "none", "":
ctx.Providers.OpenIDConnect.Write(rw, req, claims)
default:
ctx.Providers.OpenIDConnect.WriteError(rw, req, errors.WithStack(fosite.ErrServerError.WithHintf("Unsupported userinfo signing algorithm '%s'.", client.UserinfoSigningAlgorithm)))
}
}