~netlandish/links

LinkTaco offers an OAuth 2.0-compatible (RFC 6749) authorization process for access to the GraphQL API. This document explains the specific details of our RFC 6749 implementation and is intended to be accompanied by a reading of the RFC.

#Constraints

Our OAuth 2.0 implementation has the following caveats:

  • Only confidential clients are supported; public clients are not allowed

In the use-case of a native application, where the public client type specified in RFC 6749 is preferred, the application must either provide a web server component which completes the confidential authentication process and shares the access token with the application; or the application should ask the user to provide a personal access token, which can be generated at linktaco.com/oauth2/personal. In the latter case, the application should inform the user of the grant string which supports only the minimum access level required to use the application's features.

  • The implicit grant (section 4.2) is not supported for the same reasons
  • The resource owner password credentials grant (section 4.3) is not supported
  • The client credentials grant (section 4.4) is not used
#Access scopes

OAuth 2.0 clients using LinkTaco must specify explicitly the list of features they wish to be granted permission to use.

The format of the scope string, per section 3.3 is a space-delineated list of grants. Each grant has three components: service, scope, and access kind; and is formatted as scope:access kind.

The scope is the specific feature of that service which the grant applies to, such as "PROFILE". The list of access scopes available for each API is documented in the GraphQL schema for that API in the enum AccessScope type.

The access kind is either RO or RW; respectively referring to read-only or read/write access to that scope.

Example: PROFILE:RO LINKS:RW ANALYTICS:RO

The scopes necessary to use each GraphQL resolver are also indicated in the GraphQL schema with the @access directive.

The access scopes supported by LinkTaco, and the required scopes to utilize each resolver, are documented in the GraphQL schema.

They can also be requested programmatically by fetching the following URL:

https://api.linktaco.com/query/api-scopes.json

The following scopes are available for use:

  • PROFILE
  • LINKS
  • LISTS
  • SHORTS
  • ORGS
  • DOMAINS
  • BILLING
  • ANALYTICS
  • QRCODES
#Client registration

OAuth 2.0 clients may be registered at linktaco.com/oauth2/clients. You will be issued a client ID and secret per sections 2.2 & 2.3. The client ID is a UUID, and the secret is 64-byte random string, base64 encoded. It is not necessary to interpret them; they are passed verbatim to our OAuth 2.0 endpoints.

#Authorization endpoint

The authorization endpoint (see section 4.1.1) is https://linktaco.com/oauth2/authorize. Note that LinkTaco differs from the specification in that it REQUIRES the scope parameter to be provided; per section 3.3 LinkTaco interprets the absence of the scope parameter as an invalid scope and will cause the request to fail.

To start the exchange, direct the user to the following URL:

https://linktaco.com/oauth2/authorize

Provide the following parameters in the query string:

client_id
The client ID assigned to you in the previous step.
scope
A list of scopes you're requesting — see next section.
response_type
This **must** be set to `code`.
state
Optional: an arbitrary string — see notes.
redirect_uri
Optional: your application URI for redirect the user to — see notes.

The optional state field is returned to you after the redirect. One example use-case of this field is generating a token before directing the user to the authorization page and validating it after the redirect, to prevent users from initiating the OAuth flow without you. Most users don't need to worry about this.

The optional redirect_uri must match the redirect uri specified in the OAuth 2.0 client configuration.

The authorization code issued is a 32 character hexadecimal string, and it must be used within 5 minutes.

#Access token endpoint

The access token endpoint (see section 4.1.3) is https://linktaco.com/oauth2/access-token. The optional redirect_uri must match the redirect uri specified in the OAuth 2.0 client configuration. HTTP Basic authentication is also recommended per section 2.3.1. Our access token response will always set the token type to "bearer".

#Supported authentication profiles

There are various ways, in order of complexity and flexibility, of authenticating with the API. Your goal is to obtain an access token, which can be used to authenticate with the API.

#Personal Access Tokens

The easiest and fastest way to authenticate with LinkTaco is to create a personal access token. This token will have unrestricted access to the API and can be used like a normal access token to authenticate API requests (see Authenticating API requests).

Warning: do not give your personal access tokens to third parties. Any third party which encourages you to give them a personal access token should instead develop an OAuth 2.0 client as described in the next section.

#OAuth 2.0 Clients

Personal access tokens are suitable for authenticating yourself, but if you intend to provide software that other LinkTaco users can log into, you should create an OAuth client instead. The OAuth 2.0 flow allows end-users to grant your client only the privileges it requires to execute its duties and to revoke this access at any time. This is accomplished through an OAuth 2.0 exchange:

  1. Direct the user (in a web browser) to a special page on LinkTaco where we present them with the permissions you're asking for and they provide consent.
  2. The user is redirected back to your application's configured redirect URI. We will add an exchange token to the query string via the code parameter.
  3. Your application sends an HTTP request directly to LinkTaco using this exchange token and your client credentials to obtain an access token.

To this end, you need to have an HTTP server running somewhere (localhost is suitable for testing) that the user can be redirected to upon consenting to the permissions you requested. Decide on a URL we can redirect the user to in your application, and fill out the base redirect URI accordingly.

Upon submitting the form, your client ID and client secret will be shown to you. Record your client secret now. It will not be shown to you again.

#OAuth 2.0 scopes

API endpoints on LinkTaco generally require an access token valid for a specific scope to be used. This allows you to only request access to the subset of the API that you require. Scopes are written with the following notation(s):

name
name:access

name is the name of the OAuth 2.0 scope, which is documented alongside the API resolvers which require it (e.g. getFeed requires the PROFILE scope). access is either RO or RW, and may be omitted (default: RO).

Scopes sent to the authorize endpoint should be space separated. For instance:

PROFILE:RO LINKS:RW ANALYTICS

#The application redirect

Once the user consents, they will be redirected to your configured application redirect_uri. We will update your redirect URI with some additional query string parameters you can use for the next steps:

code
An exchange token you can use to obtain an access token in the next step.
iss
The base URI for the api server. See [RFC 2907][].
state
If present, it will be the "state" value given by your application.
error
If present, indicates that an error occurred in the process — see notes.
error_description
If present, a human friendly error string, if that human is an engineer.
error_uri
If present, a URL to a webpage with more details for the given error.

Possible values for error:

  • access_declined
  • invalid_request
  • invalid_scope
  • server_error

Important: the user is able to edit the scopes you've requested before consenting. You must handle the case where the scopes returned when obtaining an access token do not match the scopes requested.

#Obtaining an access token

Once your application retrieves the exchange token from the redirect, you can submit an HTTP POST request to https://linktaco.com/oauth2/access-token. The request Content-Type should be application/x-www-form-urlencoded and include the following parameters:

client_id
The client ID assigned to you when you registered the application.
client_secret
The client secret assigned to you when you registered the application.
grant_type
The request type being requested. Must be `authorization_code` or `refresh_token`.
code
The exchange token issued in the previous step.
refresh_token
Only required if the `grant_type` is set to `refresh_token`.

You will receive a response like this:

{
    "access_token": "your access token",
    "token_type": "bearer",
    "expires": 1736201028,
    "scope": "PROFILE:RO ANALYTICS:RW",
    "refresh_token": "refresh token"
}

The expires date is in Unix epoch format.

You can now use this token for Authenticating API requests.

#Refreshing access tokens

You can refresh an access token programmatically to avoid service disruptions. To refresh a token simply follow the same steps in "Obtaining an access token" above. You must:

  • Specify refresh_token in the grant_type parameter.
  • Give the access token's refresh token via the refresh_token parameter.

Upon a successful refresh you will receive the same response json as when obtaining a new token. You should then update your own database with the new access token, refresh token, and expiration date.

#Rotating your client secret

On the security tab of your OAuth 2.0 client's dashboard (which can be accessed from the OAuth clients page), you can rotate your client secret, in the event that it is compromised.

#Revoking access tokens

On the security tab of your OAuth 2.0 client's dashboard (which can be accessed from the OAuth clients page), you can revoke all issued access tokens at once, in the event some or all of them are compromised. Users will have to repeat the authorization flow.

#Authenticating API requests

Authenticating your API request is simple once you have an access token. You just need to set the Authorization header to Bearer your-access-token. For example:

oauth_token=your oauth token
curl \
  --oauth2-bearer "$oauth_token" \
  -H 'Content-Type: application/json' \
  -d '{"query": "{ version { major, minor, patch } }"}' \
  https://api.linktaco.com/query

#Documentation Attribution

Our GraphQL setup is heavily based on the SourceHut GraphQL services. As such this document is a modified version of the original SourceHut document.

About this wiki

commit 2aac1348afc29af64b6d24324bd435bffb2881d1
Author: Peter Sanchez <peter@netlandish.com>
Date:   2025-02-24T14:03:34-06:00

Fixing anchor name in support doc
Clone this wiki
https://git.code.netlandish.com/~netlandish/links-wiki (read-only)
git@git.code.netlandish.com:~netlandish/links-wiki (read/write)