silo.pub supports "native" authentication now! #indieweb #micropub
So I thought, this morning, "I'll add a gem to http://manabasecrafter.com to act as an OpenID server." But all the gems are obsolete. Then I thought "Didn't I use something called MyOpenID at one point?" They've closed. Then I thought "Didn't Google offer one?" They discontinued it last month. Then I thought "I'll do it the dumb way and just use the WordPress plugin that does it on a dummy site." That plugin is no longer supported and incompatible with the current version of WordPress. Then I thought "I'll try it in raw PHP." There is apparently one working library, and all they offer is an example server "to give you an idea of how to write your own implementation."
Currently the protocol expects the use of the
client_idparameter in the authentication request. This does not seem necessary as it is never used, just a remnant of OAuth 2.0. The
redirect_uriis enough to establish the relying party's identity. So the proposal is to make
client_idsupport OPTIONAL both for relying party as well as the IndieAuth services.
client_id is actually used to display information about the application when the authorization/authentication screen is displayed.
For example, go sign in to https://quill.p3k.io/ and you will see a screen like below.
The way this works is the authorization server, in this case indieauth.com, sees the
client_id parameter and makes an HTTP request to it, looking for an
h-x-app microformats object containing application information. The h-x-app
card contains the application name and icon.
Read more about h-x-app on the IndieWebCamp wiki.
client_id is meant to be the authoritative identity of the application,
whereas an application may use more than one
redirect_uri during normal
operation. Since OAuth 2.0 requires registration of redirect URIs, the h-x-app card
would also be a good place to whitelist valid redirect URIs for the application.
Summary: The client_id parameter is required, as it is used to provide identifying information about the application.
It is advisable to implement CSRF protection. The
stateparameter can be used for that, or a new parameter, like
csrf_token, as proposed by "SaferWeb: OAuth2.a or Let's Just Fix It" MUST be implemented.
This will protect against an attacker obtaining a
codeand tricking the user's browser to go to the relying party's callback endpoint, thus gaining access to the server on the attacker's behalf and potentially leaking private data to the attacker's account.
The CSRF token (or state) needs to be saved in a browser session that is created when the user tries to login to the relying party. The CSRF token is compared to the token specified on the callback URL after the user grants permission to the relying party to obtain the user's identity.
Implementing CSRF protection is extremely important. Currently this can be done using the
state parameter, which is what the OAuth 2.0 spec recommends. It is convenient that it can also be used to store application state at the same time.
I am inclined to not introduce a new parameter, but instead require applications to use the state parameter.
Summary: Authorization servers should require applications set the state parameter.
Terminology: authentication instead of authorization
IndieAuth is actually used for authentication and not authorization as is mentioned on the "Distributed IndieAuth" page. This should be modified to talk about authentication instead. Also the name of the
authorization_endpointshould be changed to
Actually, IndieAuth can be used for both authentication and authorization. In its most basic form, it is used for authentication only. However, when used in the context of signin in to a Micropub-enabled application, it is used for authorization, to grant an application access to post to your site.
Summary: Keep using the term "authorization" and keep the name "authorization_endpoint", since IndieAuth does provide authorization.
Additional "verify" endpoint
The "auth" endpoint in IndieAuth is currently used both for initiating the authentication (GET) as well as verifying the authentication code (POST). In order to support the option to ask for user consent before the identity of the user is released, it makes sense to have a separate verification endpoint as the POST on the authentication endpoint will be used for a form submit.
This is also relevant in the case of "Distributed IndieAuth" where the user mentions the
authorization_endpoint, as a link relation on their home page. The proposal is to also allow for (optionally) defining a
verification_endpointlink relationship on the user's homepage. For example:<link rel="authentication_endpoint" href="https://indiecert.net/auth"> <link rel="verification_endpoint" href="https://indiecert.net/verify">
I don't follow this argument.
The GET method of the authorization endpoint is the first step. Users are directed to the authorization endpoint so their browser makes a GET request. What the authorization server does at that point is not defined in the IndieAuth spec. In other words, it's up to the authorization server to authenticate the user, provide an appropriate interface describing the authorization request, obtain authorization from the user, and then redirect back to the application. How that is actually done is not described in the IndieAuth spec or the OAuth 2.0 spec.
This means the authorization server does not need to use the POST method on itself for anything, since it can be implemented in any number of other ways and has no effect on anything except itself.
The POST method for the authorization endpoint is for the external applications to verify the authorization code. This is a convenient overloading of the authorization endpoint, which is otherwise unused.
Summary: No additional endpoints are needed, the authorization endpoint can be used for the user-visible authorization request as well as by apps verifying the authorization code.
Content negotiation for "verify" endpoint
Currently the IndieAuth protocol uses a
application/x-www-form-urlencodedformatted response instead of the currently more popular
application/jsonresponse format, e.g. in OAuth 2.0. It is proposed to support "Content Negotiation" by checking the HTTP
Acceptheader in the verification request and returning either
application/jsondepending on the
Acceptheader. The default can be either of those, but both MUST be supported.
The only valid argument for returning a JSON response is that OAuth 2.0 defines the token response explicitly as JSON encoded.
I've been thinking a lot about this, and it seems like this would be a reasonable change. The main reason I am willing to accept this is that there will be far fewer implementations of authorization servers than either clients or users' websites, so this is placing the burden of content negotiation on a relatively smaller number of implementations.
Summary: Update the spec to require authorization servers accept content-negotiation for clients to choose between
To prevent this kind of attack we need to: limit the number of login attempts, ban IPs that send a large number of login requests