Skip to content

Scribouilli/toctoctoc2024

 
 

Repository files navigation

Toctoctoc

This project is a generic server to connect to an OAuth identity service. Currently, the implemented services are GitHub and GitLab instances.

After having logged in with the service, this server forwards everything useful (secret token, refresh token if necessary) to the client-side. From there, the client-side code communicates directly with the service without intermediaries. This is possible with the implemented services (GitHub, GitLab) because they have CORS headers open on most API endpoints.

Workflow example

Let's say you have a client application. You want your users to be able to connect with GitHub and use their GitHub identity to communicate with Github (for instance, committing stuff on one of their repository).

The typical workflow would go like this:

  • The users go on your-client-application.com.
  • They click on a "Login with GitHub" button. The link of this button would look like this: https://github.com/login/oauth/authorize?client_id=${client_id}&scope=${scope}&redirect_uri=${redirect_uri}
  • On github.com, they share rights with your toctoctoc GitHub OAuth application.
  • They are redirected to their destination (see below for more instruction), usually your-client-application.com. Through this redirection, the toctoctoc server returns a GitHub access_token to the client application.
  • From there, the client application can store the access_token (for instance, in localStorage) and makes direct calls to github.com.

You can also set it up for GitLab if you need it.

How to install toctoctoc

1 - Prerequisites

  • You need to install Node.js.
  • A URL to access your toctoctoc server. It can be http://localhost:[port] on a development environment or a domain that points to your toctoctoc server.

2 - Create an OAuth application

Create an OAuth application for the service you want to handle with the server:

  • A GitHub OAuth app: for the Authorization callback URL, use the endpoint provided by your toctoctoc server: [your-toctoctoc-server-URL]/github-callback.
  • And/or a GitLab OAuth app: for the Callback URL, use the endpoint provided by your toctoctoc server: [your-toctoctoc-server-URL]/gitlab-callback.

3 - Install the server

Clone the repository

git clone git@github.com:Scribouilli/toctoctoc.git

Install dependencies

npm install

4 - Setup the environment variables and OAuth services configuration

Environment variables

You need to fill the client id and client secret of at least one service.

  • OAUTH_SERVICES_DECRYPTION_KEY: a key to decrypt oauth-services.json.encrypted
  • PORT: The port this server will listen to. By default, it's 4000.
  • HOST: The host this server will listen to. By default, it's localhost.
  • TOCTOCTOC_ORIGIN: The web content's origin of your toctoctoc server. It is defined by the protocol, the hostname and the port of the URL you use to access your toctoctoc server. (eg. http://localhost:4000)

You can put these environment variables in an .env file.

OAuth services configuration

Oauth services are defined in the oauth-services.json file The one provided in the repo is an example file. It should not contain the real values because they should be kept secret

Instead, you should create a oauth-services.json.encrypted file. It's an encrypted oauth-services.json file. It can be done easily using the helper web app. It is available at <your toctoctoc origin>/oauth-services-config

Getting started without the encryption part

npm run env-start:no-config if you use a .env file
npm run start:no-config if you use environment variables directly

Changing the configuration

Changing the configuration requires the coordination of different changes in different places. For instance, if you want to change the redirect_uri of a gitlab config, you need to:

  • set the new redirect uri in the oauth app on the gitlab instance
  • change the encrypted configuration (in this repo of wherever your configuration is).
    • You should change the encryption key as well
  • deploy with the new encryption key and new encrypted configuration

5 - Start the server

You need to setup at least one service to use toctoctoc properly. Be sure that your OAuth application is setup correctly and your environment variables too.

Start the server. It will listen on the chosen port defined in your .env file.

npm start

How to use your toctoctoc server

On your client application, you have to authenticate your users through one of the services (GitHub or GitLab) and configure this authentication to use it with your toctoctoc server.

With GitHub

You request a user's GitHub identity through this endpoint:

https://github.com/login/oauth/authorize

To use it with toctoctoc, the mandatory parameters are:

  • client_id: it's the client_id provided by your GitHub OAuth application for toctoctoc.
  • scope: the scope you want to ask for the needed rights, for example public_repo,user:email.
  • redirect_uri: it's the endpoint provided by your toctoctoc server for GitHub that ends like /github-callback. This redirect_uri must have a destination parameter filled with ah URL: it enables toctoctoc to know where to redirect the user after fetching the access_token.

Here is an example of link to let your users to authenticate through GitHub and retrieve an access_token with your toctoctoc server:

<a
 href="https://github.com/login/oauth/authorize?client_id=XXXXXX&scope=public_repo,user:email&redirect_uri=http://my-toctoctoc-server-host.com/github-callback?destination=http://my-client-application.com"
>
  Login with GitHub 🍂
</a>

You can check GitHub's available scopes to only ask for the rights you need.

With GitLab

You request a GitLab authorization code through this endpoint:

https://gitlab.com/oauth/authorize

To use it with toctoctoc, the mandatory parameters are:

  • client_id: it's the client_id provided by your GitHub OAuth application for toctoctoc.
  • response_type: code.
  • state : a value that can’t be predicted, used by you to maintain state between the request to GitLab and the callback on your client application.
  • scope: the scope you want to ask for the needed rights, for example read_repository+write_repository+email.
  • redirect_uri: it's the endpoint provided by your toctoctoc server for GitHub that ends like /gitlab-callback. This redirect_uri must have a destination parameter filled with ah URL: it enables toctoctoc to know where to redirect the user after fetching the access_token and the refresh_token.

Here is an example of a link to let your users authenticate through GitLab and retrieve an access_token with your toctoctoc server:

<a
  href="https://gitlab.com/oauth/authorize?client_id=XXXXXX&redirect_uri=http://my-toctoctoc-server-host.com/gitlab-callback?destination=http://my-client-application.com&response_type=code&state=XXXXXX&scope=read_repository+write_repository+email"
>
  Login with GitLab 🍃
</a>

Along with the access_token, some other parameters are returned with the destination URL after the GitLab authentication:

  • refresh_token: a token used to ask for a new GitLab OAuth token (check the section below for more information).
  • expires_in: the validity of the access_token in milliseconds.
  • state : the value you provided to maintain state between the request to GitLab and the callback on your client application.

You can check GitLab's available scopes to only ask for the rights you need.

Token expiration

GitLab access tokens expire after two hours. On your client application, after maximum two hours, you have to generate a new access_token using the refresh_token attribute following the third step of this documentation.

Endpoints

This server provides the following endpoints for you to use with your service OAuth application:

  • /github-callback: route for GitHub to redirect to as redirect URL.
  • /gitlab-callback: route for GitLab to redirect to as a redirect URL.

Benefits of this approach

  1. This approach enables a client-side-only application to have an identity and private/personal storage associated to it without having to implement any of it. This reduces the cost and hassle of writing an application with private data

GitHub was a first choice to make it easy to prove the viability of the approach, but of course, it's a limited choice.
We plan on implementing the same for gitlab (both gitlab.com and self-hosted gitlab instances). And maybe one day ActivityPub-compatible identities...

  1. A single server for different applications

  2. no server-side code

Security

The only thing this server has to protect are the credentials received from the services (for example GitHub's secret token).

Aside from adhering to POLA practices, this server has very little to do, so little to protect and it's good this way.
It does not keep trace of the token after having sent it to their destination. One risk is a man-in-the-middle attack, but well-configured HTTPS takes care of this easily.

The only remaining risk probably comes from a complete take-over of the server via a remote-code execution (RCE) or complete system take-over. This could happen in the following ways:

  • hardware-access attack (backdoor or direct malicious access to hardware)
  • (I haven't studied it, but probably DNS-based attacks)
  • exploitation of a known RCE vulnerability in the operating system (and probably network stack specifically)
  • exploitation of a known RCE vulnerability in a dependency
    • node.js itself
    • in a dependency itself
    • or via a supply-chain attack

Another important piece of the security puzzle are the various your-client-application.com services themselves who need HTTPS and to make sure what's stored in the local storage is secure (so only highly-trusted third-party scripts, CSP, etc.)

An important note is that the different your-client-application.com services are isolated from one another.

For the most part, the boring aspect of the project (accounting data from very small companies), HTTPS and up-to-date dependencies (OS, node.js and package.json dependencies) should probably keep things safe fairly easily.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 63.4%
  • HTML 36.4%
  • Shell 0.2%