PrivateAuth is an extension to the IndieAuth protocol. It's intended to allow authentication to small applications with a limited audience; for example, a private media server, a home automation system, or a personal blog.
It tries to be as compatible as possible with IndieAuth from an endpoint perspective. A PrivateAuth endpoint should be able to handle logins for both PrivateAuth and IndieAuth clients. That way, a user may reuse an existing IndieAuth endpoint with a PrivateAuth client, or vice-versa.
To a certain degree, this compatibility extends to clients; however, clients that support both IndieAuth and PrivateAuth logins MUST verify the domain of PrivateAuth logins. In other words, they MAY NOT skip the domain check as part of the Authentication code verification section below.
A restricted client is one that wishes to limit the users that can sign into it. A full client is one that allows any user to sign in.
A user's profile data is comprised of the additional fields (name
, shortName
, and username
) specified in the Authentication code verification section below.
The authentication flow is very similar to IndieAuth. You might want to compare with section 5 of the IndieAuth spec.
A restricted client MAY skip the authorization endpoint discovery step. In this case, the restricted client SHOULD provide a configuration mechanism to allow an administrator to set a trusted authorization endpoint.
Clients MAY also provide a configuration mechanism to determine if they should behave in either a restricted or full manner.
When building the authentication request, a restricted client MAY omit the me
parameter, and rely on the authorization endpoint to determine the user's profile URL. This breaks compatibility with IndieAuth endpoints, and so should be only done if a developer is certain that their restricted client will only be used with PrivateAuth endpoints.
If an authorization endpoint receives a request without the me
parameter, it MUST somehow resolve the user's profile URL. How exactly this happens is dependent on the specific implementation—for example, a user could be prompted to enter their profile URL, or the endpoint could automatically calculate a profile URL based on a username entered by the user.
There are no changes to this section from the IndieAuth specification.
If a restricted client chose to omit the me
parameter in the initial request, then it is not possible to verify that the returned profile URL's domain is correct. Therefore, this domain check MAY be skipped by restricted clients.
Important: this domain check MAY NOT be skipped in a client that supports both IndieAuth and PrivateAuth logins, as this would be a security flaw. Both IndieAuth clients and PrivateAuth full clients must be able to reject logins from a malicious endpoint—that is, an endpoint that claims to authenticate users for a domain that it does not control.
When making the verification request, the client MUST add the X-PrivateAuth-Version header, with a value of 1. Endpoints that receive valid requests with this header MUST have a JSON response containing fields according to the following table:
Field | Status | Description | Example |
---|---|---|---|
me |
required | This has the same meaning as it does in the IndieAuth specification. | "https://alex.studer.dev" |
name |
optional | The user's full name. | "Alex Studer" |
shortName |
optional | A short version of the user's full name. | "Alex" |
username |
required | A unique identifier of the user's account at the endpoint. | "alex" |
permissions |
required | An array of a user's permissions. See the Permissions section below. | ["sampleapp:read", "differentapp:documents.read"] |
The username
MUST be unique between different users on the same endpoint, but MAY be the same between different users on different endpoints. The name
and shortName
fields do not have any uniqueness requirements.
For compatibility reasons, clients MUST be able to ignore additional fields beyond what is specified here. That is, if a future revision of the specification adds additional fields, existing clients MUST ignore the additions.
PrivateAuth adds the concept of permissions: arbitrary strings associated with a user that can be interpreted by clients. Permissions SHOULD always be in lowercase, and MUST be verified by clients in a case-insensitive manner.
This section is non-normative.
While the specification does not impose requirements on what permission strings look like, the convention is to use the client's name, a colon (:
), and a descriptive string of the permission. If some hierarchy is needed in the descriptive string, a period (.
) may be used.
For example, a client named "SampleApp" might look for the permissions sampleapp:read
, sampleapp:write
, and sampleapp:admin
. A cloud storage client named "DifferentApp" might have permissions differentapp:documents.read
, differentapp:documents.write
, differentapp:photos.read
, and differentapp:photos.write
.
A client SHOULD report an error if it finds a permission with its application name that it does not recognize, to protect against configuration errors. Clients SHOULD NOT depend on permissions that belong to other clients.
This section is non-normative.
The PrivateAuth specification does not include the concept of roles for a user. However, endpoints MAY implement this concept by allowing an administrator to define roles as lists of permissions, and then allow assigning users to those roles.
For example, an administrator could configure their endpoint to have an "Editor" role with permissions of ["sampleapp:read", "sampleapp:write", "differentapp:documents.read", "differentapp:documents.write"]
. Then, any users with the "Editor" role assigned would automatically have those permissions added to their overall permissions
array.