Chopin
DevelopmentAuthentication

Authentication

Chopin Framework uses blockchain addresses as user identities and authenticates users via digital signatures. This is all managed by Chopin Framework itself—so the developer does not need to think about it.

How it works

HTTP requests emitted from the browser are intercepted by middleware that adds an HTTP header to the request containing the signature of the authenticating user before being sequenced onchain. This signature is then verified by the middleware prior to being forwarded to the destination server. By the time the request hits your backend, the user's address will have been verified and securely added to the x-address header in the authenticated request.

Authenticating Users

In Next.js apps

Simply install the @chopinframework/next package and use the getAddress function to retrieve the user's address on the server side.

import { getAddress } from "@chopinframework/next";
 
const address = await getAddress();

In other frameworks

When you are handling the request, extract the value of the x-address header and use it as the user's address.

Logging in users

Chopin Framework provides an embedded wallet and account system that enables users to login with their email. In the development environment, going to the login page just returns JSON, however, in production there will be a login UI.

With React

To get the address of the logged in user on the client side, you can use the @chopinframework/react package.

npm install @chopinframework/react

This package provides the useAddress hook, which returns the address of the logged in user as well as a few other functions.

import { useAddress } from "@chopinframework/react";
 
function MyComponent() {
const { address, isLoading, isLoginError, login, logout, revalidate } = useAddress();
 
    if (isLoading) {
        return <div>Loading...</div>;
    }
 
    if (isLoginError) {
        return <div>Error logging in</div>;
    }
 
    if (address) {
        return (
            <div>
                <p>Logged in as {address}</p>
                <button onClick={logout}>Logout</button>
                <button onClick={revalidate}>Refresh</button>
            </div>
        );
    }
 
    return <button onClick={login}>Login</button>;
}

Without React

Users can be logged in and out by navigating to the /_chopin/login and /_chopin/logout pages of your app respectively.

Think of this as a way to generate an address for the user. Before calling this endpoint, the users is unauthenticated. When this endpoint is called, Chopin Framework's embedded wallet system creates an address for the user and stores it in their browser. Third-part wallets like Metamask will be available soon, but currently are not supported.

This works locally and in production. While developing, you can also include ?as=<address> to login as a specific address. For example, http://localhost:4000/_chopin/login?as=0x123 in conjunction with using chopd will login as address 0x123 when running locally.

This will store a cookie in the users browser in order to help manage the session.

Making API Calls

By default, Chopin Framework uses cookies to manage the session in the browser. However, if you are not using the browser, you can use a JWT instead.

After logging in by fetching /_chopin/login, the response will adhere to the following schema:

interface LoginResponse {
    success: boolean;
    address: string;
    jwt: string;
}

Take the jwt and add it to the Authorization header of all subsequent requests outside of the browser using the Bearer scheme.

const response = await fetch(url, {
    headers: { Authorization: `Bearer ${jwt}` },
});

To be clear, you do not need to do this when you are building a web app. But it can be useful if you are not able to make use of cookies, such as in the case of mobile apps.

User identity

When adding a user to your database, you can use the address as the primary key since it's guaranteed to be unique. For example, if you are using Postgres, you can create tables like this:

CREATE TABLE users (
    address VARCHAR(42) PRIMARY KEY
);

Then if you are storing a list of users, you can use the address to identify the user.

const user = await db.query("SELECT * FROM users WHERE address = $1", [address]);

And if you have a list of a user's posts, you can use the address to identify the user.

CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    address VARCHAR(42) NOT NULL,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL
);

and

const posts = await db.query("SELECT * FROM posts WHERE address = $1", [address]);

However, it is also acceptable to use a different unique identifier for the user. For example, you could use an autoincremented id or username. You can use email, but since this data is being added to a public blockchain, PII is usually not recommended.

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE, -- Be careful because this data goes onchain
    username VARCHAR(255) NOT NULL UNIQUE,
    address VARCHAR(42) NOT NULL UNIQUE
);

As long as the address is connected to the user, you will be able to utilize the address to identify the user.

Avoiding Passwords

Do not use passwords for authentication, since they are not cryptographically secure. In the future, Chopin apps will have a way to use social login and traditional passwords, but that is not supported at this time.