♻️ Refactored metadata HTTP schema usage

This commit is contained in:
Maxim Lebedev 2024-05-08 16:52:03 +05:00
parent 48c5423ae1
commit f381c107b8
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
2 changed files with 74 additions and 45 deletions

View File

@ -13,9 +13,7 @@ type Handler struct {
}
func NewHandler(metadata *domain.Metadata) *Handler {
return &Handler{
metadata: metadata,
}
return &Handler{metadata: metadata}
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -26,47 +24,6 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
w.Header().Set(common.HeaderContentType, common.MIMEApplicationJSONCharsetUTF8)
scopes, responseTypes, grantTypes, codeChallengeMethods := make([]string, 0), make([]string, 0),
make([]string, 0), make([]string, 0)
for i := range h.metadata.ScopesSupported {
scopes = append(scopes, h.metadata.ScopesSupported[i].String())
}
for i := range h.metadata.ResponseTypesSupported {
responseTypes = append(responseTypes, h.metadata.ResponseTypesSupported[i].String())
}
for i := range h.metadata.GrantTypesSupported {
grantTypes = append(grantTypes, h.metadata.GrantTypesSupported[i].String())
}
for i := range h.metadata.CodeChallengeMethodsSupported {
codeChallengeMethods = append(codeChallengeMethods,
h.metadata.CodeChallengeMethodsSupported[i].String())
}
_ = json.NewEncoder(w).Encode(&MetadataResponse{
Issuer: h.metadata.Issuer.String(),
AuthorizationEndpoint: h.metadata.AuthorizationEndpoint.String(),
TokenEndpoint: h.metadata.TokenEndpoint.String(),
IntrospectionEndpoint: h.metadata.IntrospectionEndpoint.String(),
IntrospectionEndpointAuthMethodsSupported: h.metadata.IntrospectionEndpointAuthMethodsSupported,
RevocationEndpoint: h.metadata.RevocationEndpoint.String(),
// NOTE(toby3d): If a revocation endpoint is provided, this
// property should also be provided with the value ["none"],
// since the omission of this value defaults to
// client_secret_basic according to RFC8414.
RevocationEndpointAuthMethodsSupported: h.metadata.RevocationEndpointAuthMethodsSupported,
ScopesSupported: scopes,
ResponseTypesSupported: responseTypes,
GrantTypesSupported: grantTypes,
ServiceDocumentation: h.metadata.ServiceDocumentation.String(),
CodeChallengeMethodsSupported: codeChallengeMethods,
AuthorizationResponseIssParameterSupported: h.metadata.AuthorizationResponseIssParameterSupported,
UserinfoEndpoint: h.metadata.UserinfoEndpoint.String(),
})
_ = json.NewEncoder(w).Encode(NewMetadataResponse(*h.metadata))
w.WriteHeader(http.StatusOK)
}

View File

@ -1,5 +1,11 @@
package http
import (
"fmt"
"source.toby3d.me/toby3d/auth/internal/domain"
)
//nolint:tagliatelle // https://indieauth.net/source/#indieauth-server-metadata
type MetadataResponse struct {
// URL of a page containing human-readable information that
@ -48,3 +54,69 @@ type MetadataResponse struct {
// provides the iss parameter.
AuthorizationResponseIssParameterSupported bool `json:"authorization_response_iss_parameter_supported,omitempty"` //nolint:lll
}
//nolint:funlen // false-positive due 3-line documentation comment
func NewMetadataResponse(m domain.Metadata) *MetadataResponse {
out := &MetadataResponse{
AuthorizationEndpoint: "",
AuthorizationResponseIssParameterSupported: false,
CodeChallengeMethodsSupported: make([]string, 0),
GrantTypesSupported: make([]string, 0),
IntrospectionEndpoint: "",
IntrospectionEndpointAuthMethodsSupported: make([]string, 0),
Issuer: "",
ResponseTypesSupported: make([]string, 0),
RevocationEndpoint: "",
RevocationEndpointAuthMethodsSupported: make([]string, 0),
ScopesSupported: make([]string, 0),
ServiceDocumentation: "",
TokenEndpoint: "",
UserinfoEndpoint: "",
}
out.AuthorizationResponseIssParameterSupported = m.AuthorizationResponseIssParameterSupported
for i := range m.ScopesSupported {
out.ScopesSupported = append(out.ScopesSupported, m.ScopesSupported[i].String())
}
for i := range m.ResponseTypesSupported {
out.ResponseTypesSupported = append(out.ResponseTypesSupported, m.ResponseTypesSupported[i].String())
}
for i := range m.GrantTypesSupported {
out.GrantTypesSupported = append(out.GrantTypesSupported, m.GrantTypesSupported[i].String())
}
for i := range m.CodeChallengeMethodsSupported {
out.CodeChallengeMethodsSupported = append(out.CodeChallengeMethodsSupported,
m.CodeChallengeMethodsSupported[i].String())
}
out.IntrospectionEndpointAuthMethodsSupported = append(out.IntrospectionEndpointAuthMethodsSupported,
m.IntrospectionEndpointAuthMethodsSupported...)
// NOTE(toby3d) = If a revocation endpoint is provided, this property
// should also be provided with the value ["none"], since the omission
// of this value defaults to client_secret_basic according to RFC8414.
out.RevocationEndpointAuthMethodsSupported = append(out.RevocationEndpointAuthMethodsSupported,
m.RevocationEndpointAuthMethodsSupported...)
for dst, src := range map[*string]fmt.Stringer{
&out.AuthorizationEndpoint: m.AuthorizationEndpoint,
&out.IntrospectionEndpoint: m.IntrospectionEndpoint,
&out.Issuer: m.Issuer,
&out.RevocationEndpoint: m.RevocationEndpoint,
&out.ServiceDocumentation: m.ServiceDocumentation,
&out.TokenEndpoint: m.TokenEndpoint,
&out.UserinfoEndpoint: m.UserinfoEndpoint,
} {
if src == nil {
continue
}
*dst = src.String()
}
return out
}