👽 Refactored metadata support due IndieAuth spec changes

This commit is contained in:
Maxim Lebedev 2022-02-17 21:13:11 +05:00
parent 0dcfdfc1ac
commit 02c459b5c2
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
3 changed files with 79 additions and 52 deletions

View File

@ -13,58 +13,51 @@ import (
type (
//nolint: tagliatelle // https://indieauth.net/source/#indieauth-server-metadata
MetadataResponse struct {
// The server's issuer identifier. The issuer identifier is a
// URL that uses the "https" scheme and has no query or fragment
// components. The identifier MUST be a prefix of the
// indieauth-metadata URL. e.g. for an indieauth-metadata
// endpoint
// https://example.com/.well-known/oauth-authorization-server,
// the issuer URL could be https://example.com/, or for a
// metadata URL of
// https://example.com/wp-json/indieauth/1.0/metadata, the
// issuer URL could be https://example.com/wp-json/indieauth/1.0
Issuer *domain.ClientID `json:"issuer"`
// The server's issuer identifier.
Issuer string `json:"issuer"`
// The Authorization Endpoint.
AuthorizationEndpoint *domain.URL `json:"authorization_endpoint"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
// The Token Endpoint.
TokenEndpoint *domain.URL `json:"token_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
// The Introspection Endpoint.
IntrospectionEndpoint string `json:"introspection_endpoint"`
// 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
// The Revocation Endpoint.
RevocationEndpoint string `json:"revocation_endpoint,omitempty"`
// JSON array containing the value "none".
RevocationEndpointAuthMethodsSupported []string `json:"revocation_endpoint_auth_methods_supported,omitempty"` //nolint: lll
// JSON array containing scope values supported by the
// IndieAuth server. Servers MAY choose not to advertise some
// supported scope values even when this parameter is used.
ScopesSupported []domain.Scope `json:"scopes_supported,omitempty"`
// IndieAuth server.
ScopesSupported []string `json:"scopes_supported,omitempty"`
// JSON array containing the response_type values supported.
// This differs from RFC8414 in that this parameter is OPTIONAL
// and that, if omitted, the default is code.
ResponseTypesSupported []domain.ResponseType `json:"response_types_supported,omitempty"`
ResponseTypesSupported []string `json:"response_types_supported,omitempty"`
// JSON array containing grant type values supported. If
// omitted, the default value differs from RFC8414 and is
// authorization_code.
GrantTypesSupported []domain.GrantType `json:"grant_types_supported,omitempty"`
// JSON array containing grant type values supported.
GrantTypesSupported []string `json:"grant_types_supported,omitempty"`
// URL of a page containing human-readable information that
// developers might need to know when using the server. This
// might be a link to the IndieAuth spec or something more
// personal to your implementation.
ServiceDocumentation *domain.URL `json:"service_documentation,omitempty"`
// developers might need to know when using the server.
ServiceDocumentation string `json:"service_documentation,omitempty"`
// JSON array containing the methods supported for PKCE. This
// parameter differs from RFC8414 in that it is not optional as
// PKCE is REQUIRED.
CodeChallengeMethodsSupported []domain.CodeChallengeMethod `json:"code_challenge_methods_supported"`
// JSON array containing the methods supported for PKCE.
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
// Boolean parameter indicating whether the authorization server
// provides the iss parameter. If omitted, the default value is
// false. As the iss parameter is REQUIRED, this is provided for
// compatibility with OAuth 2.0 servers implementing the
// parameter.
//
//nolint: lll
AuthorizationResponseIssParameterSupported bool `json:"authorization_response_iss_parameter_supported,omitempty"`
// provides the iss parameter.
AuthorizationResponseIssParameterSupported bool `json:"authorization_response_iss_parameter_supported,omitempty"` //nolint: lll
// The User Info Endpoint.
UserinfoEndpoint string `json:"userinfo_endpoint,omitempty"`
}
RequestHandler struct {
@ -89,15 +82,45 @@ func (h *RequestHandler) Register(r *router.Router) {
func (h *RequestHandler) read(ctx *http.RequestCtx) {
ctx.SetStatusCode(http.StatusOK)
ctx.SetContentType(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(ctx).Encode(&MetadataResponse{
Issuer: h.metadata.Issuer,
AuthorizationEndpoint: h.metadata.AuthorizationEndpoint,
TokenEndpoint: h.metadata.TokenEndpoint,
ScopesSupported: h.metadata.ScopesSupported,
ResponseTypesSupported: h.metadata.ResponseTypesSupported,
GrantTypesSupported: h.metadata.GrantTypesSupported,
ServiceDocumentation: h.metadata.ServiceDocumentation,
CodeChallengeMethodsSupported: h.metadata.CodeChallengeMethodsSupported,
AuthorizationEndpoint: h.metadata.AuthorizationEndpoint.String(),
IntrospectionEndpoint: h.metadata.IntrospectionEndpoint.String(),
Issuer: h.metadata.Issuer.String(),
RevocationEndpoint: h.metadata.RevocationEndpoint.String(),
ServiceDocumentation: h.metadata.ServiceDocumentation.String(),
TokenEndpoint: h.metadata.TokenEndpoint.String(),
UserinfoEndpoint: h.metadata.UserinfoEndpoint.String(),
AuthorizationResponseIssParameterSupported: h.metadata.AuthorizationResponseIssParameterSupported,
CodeChallengeMethodsSupported: codeChallengeMethods,
GrantTypesSupported: grantTypes,
IntrospectionEndpointAuthMethodsSupported: h.metadata.IntrospectionEndpointAuthMethodsSupported,
ResponseTypesSupported: responseTypes,
ScopesSupported: scopes,
// 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,
})
}

View File

@ -35,7 +35,6 @@ func TestMetadata(t *testing.T) {
result := new(delivery.MetadataResponse)
if err = json.Unmarshal(body, result); err != nil {
e := err.(*json.SyntaxError)
t.Fatalf("%s#ERROR#%s", body[:e.Offset], body[e.Offset:])
t.Fatal(err)
}
}

13
main.go
View File

@ -283,6 +283,15 @@ func (app *App) Register(r *router.Router) {
Issuer: indieAuthClient.ID,
AuthorizationEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "authorize"),
TokenEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "token"),
TicketEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "ticket"),
MicropubEndpoint: nil,
MicrosubEndpoint: nil,
IntrospectionEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "introspect"),
RevocationEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "revocation"),
UserinfoEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "userinfo"),
ServiceDocumentation: domain.MustParseURL("https://indieauth.net/source/"),
IntrospectionEndpointAuthMethodsSupported: []string{"Bearer"},
RevocationEndpointAuthMethodsSupported: []string{"none"},
ScopesSupported: domain.Scopes{
domain.ScopeBlock,
domain.ScopeChannels,
@ -305,7 +314,6 @@ func (app *App) Register(r *router.Router) {
domain.GrantTypeAuthorizationCode,
domain.GrantTypeTicket,
},
ServiceDocumentation: domain.MustParseURL("https://indieauth.net/source/"),
CodeChallengeMethodsSupported: []domain.CodeChallengeMethod{
domain.CodeChallengeMethodMD5,
domain.CodeChallengeMethodPLAIN,
@ -314,9 +322,6 @@ func (app *App) Register(r *router.Router) {
domain.CodeChallengeMethodS512,
},
AuthorizationResponseIssParameterSupported: true,
TicketEndpoint: domain.MustParseURL(indieAuthClient.ID.String() + "ticket"),
Micropub: nil,
Microsub: nil,
}).Register(r)
tokenhttpdelivery.NewRequestHandler(app.tokens, app.tickets).Register(r)
clienthttpdelivery.NewRequestHandler(clienthttpdelivery.NewRequestHandlerOptions{