mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
143db66445
This is a required endpoint for OIDC and is one we missed in our initial implementation. Also adds some rudamentary documentaiton about the implemented endpoints.
89 lines
2.6 KiB
Go
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/internal/middlewares"
|
|
"github.com/authelia/authelia/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)))
|
|
}
|
|
}
|