145 lines
5.1 KiB
Go
145 lines
5.1 KiB
Go
package http
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"source.toby3d.me/toby3d/auth/internal/common"
|
|
"source.toby3d.me/toby3d/auth/internal/domain"
|
|
)
|
|
|
|
type (
|
|
|
|
//nolint:tagliatelle // https://indieauth.net/source/#indieauth-server-metadata
|
|
Response struct {
|
|
// URL of a page containing human-readable information that
|
|
// developers might need to know when using the server.
|
|
ServiceDocumentation string `json:"service_documentation,omitempty"`
|
|
|
|
// The Authorization Endpoint.
|
|
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
|
|
|
// The Token Endpoint.
|
|
TokenEndpoint string `json:"token_endpoint"`
|
|
|
|
// The Introspection Endpoint.
|
|
IntrospectionEndpoint string `json:"introspection_endpoint"`
|
|
|
|
// The User Info Endpoint.
|
|
UserinfoEndpoint string `json:"userinfo_endpoint,omitempty"`
|
|
|
|
// The Revocation Endpoint.
|
|
RevocationEndpoint string `json:"revocation_endpoint,omitempty"`
|
|
|
|
// The server's issuer identifier.
|
|
Issuer string `json:"issuer"`
|
|
|
|
// JSON array containing the value "none".
|
|
RevocationEndpointAuthMethodsSupported []string `json:"revocation_endpoint_auth_methods_supported,omitempty"` //nolint:lll
|
|
|
|
// JSON array containing the response_type values supported.
|
|
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
|
|
|
|
// JSON array containing grant type values supported.
|
|
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
|
|
|
|
// JSON array containing scope values supported by the
|
|
// IndieAuth server.
|
|
ScopesSupported []string `json:"scopes_supported,omitempty"`
|
|
|
|
// JSON array containing the methods supported for PKCE.
|
|
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
|
|
|
|
// JSON array containing a list of client authentication methods
|
|
// supported by this introspection endpoint.
|
|
IntrospectionEndpointAuthMethodsSupported []string `json:"introspection_endpoint_auth_methods_supported,omitempty"` //nolint:lll
|
|
|
|
// Boolean parameter indicating whether the authorization server
|
|
// provides the iss parameter.
|
|
AuthorizationResponseIssParameterSupported bool `json:"authorization_response_iss_parameter_supported,omitempty"` //nolint:lll
|
|
}
|
|
|
|
Handler struct {
|
|
metadata *domain.Metadata
|
|
}
|
|
)
|
|
|
|
func NewHandler(metadata *domain.Metadata) *Handler {
|
|
return &Handler{metadata: metadata}
|
|
}
|
|
|
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "" && r.Method != http.MethodGet {
|
|
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
|
|
|
return
|
|
}
|
|
|
|
w.Header().Set(common.HeaderContentType, common.MIMEApplicationJSONCharsetUTF8)
|
|
_ = json.NewEncoder(w).Encode(NewResponse(h.metadata))
|
|
}
|
|
|
|
func NewResponse(src *domain.Metadata) *Response {
|
|
out := &Response{
|
|
AuthorizationEndpoint: "",
|
|
AuthorizationResponseIssParameterSupported: src.AuthorizationResponseIssParameterSupported,
|
|
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: "",
|
|
}
|
|
|
|
for i := range src.ScopesSupported {
|
|
out.ScopesSupported = append(out.ScopesSupported, src.ScopesSupported[i].String())
|
|
}
|
|
|
|
for i := range src.ResponseTypesSupported {
|
|
out.ResponseTypesSupported = append(out.ResponseTypesSupported, src.ResponseTypesSupported[i].String())
|
|
}
|
|
|
|
for i := range src.GrantTypesSupported {
|
|
out.GrantTypesSupported = append(out.GrantTypesSupported, src.GrantTypesSupported[i].String())
|
|
}
|
|
|
|
for i := range src.CodeChallengeMethodsSupported {
|
|
out.CodeChallengeMethodsSupported = append(out.CodeChallengeMethodsSupported,
|
|
src.CodeChallengeMethodsSupported[i].String())
|
|
}
|
|
|
|
out.IntrospectionEndpointAuthMethodsSupported = append(out.IntrospectionEndpointAuthMethodsSupported,
|
|
src.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,
|
|
src.RevocationEndpointAuthMethodsSupported...)
|
|
|
|
for dst, src := range map[*string]fmt.Stringer{
|
|
&out.AuthorizationEndpoint: src.AuthorizationEndpoint,
|
|
&out.IntrospectionEndpoint: src.IntrospectionEndpoint,
|
|
&out.Issuer: src.Issuer,
|
|
&out.RevocationEndpoint: src.RevocationEndpoint,
|
|
&out.ServiceDocumentation: src.ServiceDocumentation,
|
|
&out.TokenEndpoint: src.TokenEndpoint,
|
|
&out.UserinfoEndpoint: src.UserinfoEndpoint,
|
|
} {
|
|
if src == nil {
|
|
continue
|
|
}
|
|
|
|
*dst = src.String()
|
|
}
|
|
|
|
return out
|
|
}
|