Authentication

Learn how to login, logout, and manage authenticated sessions.


Lens Authentication enables you to confirm a user's social identity and access Lens API features that require authentication.

Profile Login

In this section, we will guide you through the process of logging in using a Lens Profile.

The examples provided use @lens-protocol/react-web for creating a login webpage. This process can also be applied in React Native using the @lens-protocol/react-native package.

Start by connecting the user's wallet. Although the example uses a basic Wagmi setup, it can be adapted to suit different requirements.

LogInPage.tsx
import { useAccount, useConnect } from 'wagmi';import { InjectedConnector } from 'wagmi/connectors/injected';
import { LoginOptions } from './LoginOptions';
export function LogInPage() {  const { address, isConnecting, isDisconnected } = useAccount();
  const { connect } = useConnect({    connector: new InjectedConnector(),    onError: (error) => {      window.alert(error.message);    },  });
  const goToHome = (profile: Profile) => {    console.log('Logged in as', profile.handle?.fullHandle ?? profile.id)  };
  if (isDisconnected && !address) {    return (      <button disabled={isConnecting} onClick={connect}>        Connect Wallet      </button>    );  }
  return (    <LoginOptions wallet={address} onSuccess={goToHome} />  );}

Next, use the useProfilesManaged hook to fetch the list of Lens Profiles owned by the wallet.

LoginOptions.tsx
import { useProfilesManaged } from '@lens-protocol/react-web';
import { LoginAs } from './LoginAs';
type LoginOptionsProps = {  wallet: string;  onSuccess: (profile: Profile) => void;};
export function LoginOptions({ wallet, onSuccess }: LoginOptionsProps) {  const { data: profiles, error, loading } = useProfilesManaged({    for: wallet,    includeOwned: true  });
  if (loading) {    return <p>Loading...</p>;  }
  if (error) {    return <p>{error}</p>;  }
  if (profiles.length === 0) {    return <p>No profiles managed by this wallet.</p>;  }
  return (    <div>      {profiles.map((profile) => (        <LoginAs key={profile.id} profile={profile} onSuccess={onSuccess} />      ))}    </div>  );}

Next, use the useLogin hook to log in with a specific profile.

LoginAs.tsx
import { Profile, useLogin } from '@lens-protocol/react-web';
export type LoginAsProps = {  profile: Profile;  wallet: string;  onSuccess: (profile: Profile) => void;};
export function LoginAs({ profile, wallet, onSuccess }: LoginAsProps) {  const { execute, loading } = useLogin();
  const login = async () => {    const result = await execute({      address: wallet,      profileId: profile.id,    });
    if (result.isSuccess()) {      return onSuccess(profile);    }
    window.alert(result.error.message);  };
  return (    <button disabled={loading} onClick={login}>      {profile.handle?.fullHandle ?? profile.id}    </button>  );}

And that's it—you can now log in with any Lens Profile that the user owns.


Wallet-Only Login

If you are looking to integrate features like Open Actions or Collect Action in your decentralized application (dApp) without requiring users to have a Lens Profile, you can set up a login process that allows users to access these features without a Lens Profile. This approach broadens the accessibility of your dApp to a wider user base.

You can use the useLogin hook to log in by simply passing the wallet address.

LoginWallet.tsx
import { Profile, useLogin } from '@lens-protocol/react-web';
export type LoginWalletProps = {  wallet: string;  onSuccess: () => void;};
export function LoginWallet({ wallet, onSuccess }: LoginWalletProps) {  const { execute, loading } = useLogin();
  const login = async () => {    const result = await execute({ address: wallet });
    if (result.isSuccess()) {      return onSuccess();    }
    window.alert(result.error.message);  };
  return (    <button disabled={loading} onClick={login}>Log-in</button>  );}

The example above assumes that the user's wallet is already connected. Refer to the Profile Login section for an example of how to connect a wallet.

That's it—you can now use Open Actions and Collect Action in your dApp.


Session Management

In this section, we will show you how to manage authenticated sessions.

Current Session

A typical scenario involves retrieving the user's current session. This information is crucial for determining the user's permissions within your application.

For example, if the user is not authenticated, you could present a login page. On the other hand, if they are authenticated, you might display a dashboard.

You can use the useSession hook to fetch the user's current session, which will help you decide the appropriate UI to show.

Available in @lens-protocol/react-web and @lens-protocol/react-native

import { SessionType, useSession } from '@lens-protocol/react-web';
function Root() {  const { data, error, loading } = useSession();
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Something went wrong.</p>;
  switch (data.type) {    case SessionType.Anonymous:      // data is a AnonymousSession      return <LoginPage />;
    case SessionType.JustWallet:      // data is a WalletOnlySession      return <Onboarding address={data.address} />;
    case SessionType.WithProfile:      // data is a ProfileSession      return <Dashboard profile={data.profile} />;
    default:      return <p>Something went wrong.</p>;  }}

If you are curious about what happens when a user's session expires, the React SDK handles the refreshing of the underlying credentials at two strategic points in time:

  • When the app thread resumes (for example, after a page refresh)

  • When a request fails due to expired credentials

The SDK performs these refreshes automatically as long as the credentials are renewable. If the credentials are not renewable, it logs the user out and updates the UI state accordingly.

For instance, referring to the example above, the <LoginPage> would be displayed if the user's session has expired.

Logout

Allow users to log out of your application.

You can use the useLogout hook to log out the user.

LogoutButton.tsx
import { useLogout } from '@lens-protocol/react-web';
export function LogoutButton() {  const { execute, loading } = useLogout();
  return (    <button disabled={loading} onClick={execute}>      Log out    </button>  );}

The useLogout hook automatically removes the user's session from both the client storage and the Lens API.

That's it—the user is now logged out.


Additional Features

Get Auth Tokens

There may be instances where you need to retrieve the accessToken, refreshToken, or identityToken for the current session from the SDK. We believe that in most cases, the identity token should suffice.

All hooks available in @lens-protocol/react-web and @lens-protocol/react-native

import { useIdentityToken } from "@lens-protocol/react-web";
function Example() {  const identityToken = useIdentityToken();
  // ...}

Verify Identity

Sometimes, you may need to verify a user's identity token to grant them access to certain resources.

The first step in this process is to retrieve the identityToken from the client side as shown in the previous section.

Next, transmit the identityToken to your backend. This allows you to verify it and subsequently grant the user access.

Finaly, you use the client.authentication.verify method to verify the identityToken.

Verify Auth Token
const isVerified = await client.authentication.verify({ identityToken });
console.log(`Token is ${isVerified ? "valid" : "invalid"}`);

Error Handling

The useLogin hook returns a Result object that can be used to handle common failure scenarios.

Login.tsx
const { execute, loading, data } = useLogin();
const login = (profileId: ProfileId) => {  const result = await execute({    address: address,    profileId: profileId,  });
  if (result.isFailure()) {    switch (result.error.name) {      case 'PendingSigningRequestError':        console.log(          'There is a pending signing request in your wallet. ' +            'Approve it or discard it and try again.'        );        break;
      case 'WalletConnectionError':        console.log('There was an error connecting to your wallet', result.error.message);        break;
      case 'UserRejectedError':        // the user decided to not sign, usually this is silently ignored by UIs        break;    }    return;  }
  // result.isSuccess() === true};

A login attempt can fail for reasons identified by the following errors:

  • PendingSigningRequestError: This error occurs when there is already a pending signing request from the Lens SDK. You can use this to inform the user that they need to approve or discard the pending request before trying again. If all these requests are Lens Log-in signing requests, it's likely due to not disabling the login button when loading is true or not debouncing the login function as needed.

  • WalletConnectionError: This error occurs when the user's wallet is no longer connected. This can happen if the user disconnects their wallet while the login is in progress.

  • UserRejectedError: This error occurs when the user rejects the signing request. UIs typically ignore this error silently.

Last Logged-In Profile

You can retrieve the last logged-in profile used by a wallet. This feature is useful when you want to automatically log in the user with the last profile they used.

The useLastLoggedInProfile hook allows you to get the last logged-in profile for a wallet address.

Available in @lens-protocol/react-web and @lens-protocol/react-native

import { useLastLoggedInProfile } from '@lens-protocol/react-web';
export function LastLoggedInProfile({ wallet }: { wallet: string }) {  const { data: profile, error, loading } = useLastLoggedInProfile({    for: wallet,  });
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  // authenticate with the profile}