Permalink
Fetching contributors…
Cannot retrieve contributors at this time
153 lines (107 sloc) 8.33 KB
layout title id permalink
documentation
Horizon authentication
auth
/docs/auth/

Horizon uses JSON Web Tokens for user authentication, an open industry standard. Depending on your application, you can choose one of three types of authentication handling by passing the authType option to the Horizon object constructor.

  • unauthenticated: do not generate a web token, and do not create entries in the Horizon user table. This essentially bypasses Horizon's authentication system, and is best for applications that don't need to store any user data.
  • anonymous: generate a unique token for each new user, and create an entry in the users table for the generated token. This allows authentication through the generated token, which is stored client-side in localStorage.
  • token: verify a user's identify via a third-party OAuth service provider. As with anonymous, the returned JWT will be stored client-side.

You may also pass an already-created JWT to authType; this is useful for bootstrapping the admin user, or for integrating with non-browser-based authentication methods. Read "Making an admin auth token" in Permissions and schema enforcement for more details.

Using local authentication

Note that Horizon does _not_ have any "baked-in" local user/password authentication. The only fully-supported authentication method for individual user accounts is OAuth through a third-party provider.

Unauthenticated

The first auth type is unauthenticated. This creates no web token, and Horizon does no user management whatsoever. To create a connection using the 'unauthenticated' method do:

const horizon = Horizon({ authType: 'unauthenticated' });

This is the default authentication method and provides no means to separate user permissions or data in the Horizon application.

Anonymous

The second auth type is anonymous. If anonymous authentication is enabled in the config, any user requesting anonymous authentication will be given a new JWT, with no other confirmation necessary. The server will create a user entry in the users table for this token, with no other way to authenticate as this user than by passing the token back. (This is done "under the hood," with the JWT stored in localStorage and passed back automatically on subsequent requests.)

const horizon = Horizon({ authType: 'anonymous' });

In effect, this authentication type creates a "temporary user" for use with the current session. This allows user information to be saved while that session is active, but the user has no way of reauthenticating with the same account if the token is lost. (Note that the temporary user ID is stored in the Horizon database, and must be cleaned up manually.)

Using OAuth {#oauth}

Your application will need a client ID and "secret" for each OAuth provider you want to connect with. The providers Horizon currently supports are:

Each provider will let you register your application, and will give you the client data you need to give Horizon.

Configuring the server

In order to use OAuth with Horizon, you'll need to configure a TLS certificate so you can serve assets with HTTPS, and either specify the --key-file and --cert-file options to hz serve or add them to the server's .hz/config.toml file. (See The config.toml file for more details.) You can create a self-signed certificate with hz create-cert.

You'll need to enter id and secret values in the .hz/secrets.toml file for your server (along with host and redirect_url values for Auth0). Toward the bottom of the automatically generated file, you'll see commented-out sample settings. Uncomment the appropriate lines and replace the dummy values with the ones you've received from the application provider. Adding Github OAuth configuration data would look like this:

# [auth.facebook]
# id = "000000000000000"
# secret = "00000000000000000000000000000000"
#
# [auth.google]
# id = "00000000000-00000000000000000000000000000000.apps.googleusercontent.com"
# secret = "000000000000000000000000"
#
# [auth.twitter]
# id = "0000000000000000000000000"
# secret = "00000000000000000000000000000000000000000000000000"

[auth.github]
id = "your_client_id"
secret = "your_client_secret"

Verify the configuration by running hz serve and browsing to https://localhost:8181/horizon/auth_methods. (If you're not running on your local machine, change the server name and port as appropriate.) You'll see a list of currently active authentication options. For our example, you should see github included in the available auth methods object:

{
  github: "/horizon/github"
}

If instead you only see empty brackets (e.g., { }), ensure you've restarted the Horizon server, and that it's using the .hz/config.toml file you've edited.

Note: If your application embeds Horizon rather than using hz serve, you'll need to pass the OAuth endpoint to that object. Read "Configuring OAuth providers" in Embedding Horizon for details.

Configuring the client application

Use authType: 'token' when initializing Horizon in your client, and then use the authEndpoint() command to retrieve the endpoint for your OAuth identity provider and redirect the user to that URL.

const horizon = Horizon({ authType: 'token' });
if (!horizon.hasAuthToken()) {
  horizon.authEndpoint('github').subscribe((endpoint) => {
    window.location.replace(endpoint);
  });
} else {
  // We have a token already, do authenticated Horizon stuff here
}

After logging in with Github, the user will be redirected back to the root page of your application, with the JSON Web Token in the horizon_token query parameter. The Horizon client will automatically save the JWT from the redirected URL, storing it client-side in localStorage (just as with anonymous tokens). If the token is lost, the user can simply re-authenticate with the provider. User information will be stored in the Users table.

If an error occurs somewhere during the authentication process, the browser will be redirected back to the root of page with an error message in the query parameters.

Clearing tokens

To delete all authentication tokens from localStorage, use clearAuthTokens().

// Note the 'H'
Horizon.clearAuthTokens();

Accessing session data

You can check whether a user is currently authenticated using the Horizon.hasAuthToken method, and access their information with Horizon.currentUser. For more information, read about Users and groups and Permissions and schema enforcement.

Notes about Horizon's OAuth support

  • The authorization callback URL defaults to https://<hostname>/horizon/<servicename>. For Github, for instance, your callback would be https://yourapp.com/horizon/github. This can be changed with the path option to the add_auth_provider method. (See Embedding Horizon for details on this option.)
  • Currently, no metadata from OAuth providers—for example, friend/following lists— can be requested. In the near future, Horizon will support authentication scopes for selected providers to request access to these details, and returned metadata will be stored in the Users table.
  • The redirection URL will be configurable in a future release.
  • Passport integration is not currently on Horizon's roadmap; this decision was made to avoid tightly coupling Horizon with Express. (A Github issue may be opened to discuss this in the future.)