Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/saleor/auth-sdk


https://github.com/saleor/auth-sdk

apollo graphql hacktoberfest nextjs saleor typescript urql

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

        





# Saleor Auth SDK

Saleor Auth SDK integrates secure and customizable authentication and authorization into storefronts using Saleor.

**Below 3kB bundle size (gzipped).**


npm

Docs

Twitter

Discord


[![Discord Badge](https://dcbadge.vercel.app/api/server/H52JTZAtSH)](https://discord.gg/H52JTZAtSH)

## Usage

### Next.js App Router

Next.js 13+ App Router is the recommended way to use the Saleor Auth SDK. It is the easiest to set up and provides the best user experience.

In order to use Saleor Auth SDK in React Server Components, the client needs to be created in the following way:

```ts
import { createSaleorAuthClient } from "@saleor/auth-sdk";
import { getNextServerCookiesStorage } from "@saleor/auth-sdk/next/server";

const getServerAuthClient = () => {
const nextServerCookiesStorage = getNextServerCookiesStorage();
returncreateSaleorAuthClient({
saleorApiUrl: "…",
refreshTokenStorage: nextServerCookiesStorage,
accessTokenStorage: nextServerCookiesStorage,
});
};
```

Logging in can be implemented via Server Actions:

```tsx
{
"use server";

await getServerAuthClient().signIn(
{
email: formData.get("email").toString(),
password: formData.get("password").toString(),
},
{ cache: "no-store" },
);
}}
>
{/* … rest of the form … */}

```

Then, you can use `saleorAuthClient.fetchWithAuth` directly for any queries and mutations.

For a full working example, see the [Saleor Auth SDK example](https://github.com/saleor/example-auth-sdk/tree/app/ssr/page.tsx).

### Next.js Pages Router with [Apollo Client](https://www.apollographql.com/docs/react/)

Step-by-step video tutorial

Check the following [step-by-step video](https://www.youtube.com/watch?v=XY1t8JiPwk0) guide on how to set this up.
[![Saleor Auth with Next.js](https://img.youtube.com/vi/t6nxBk7JHCw/0.jpg)](https://www.youtube.com/watch?v=XY1t8JiPwk0)

When using Next.js (Pages Router) along with [Apollo Client](https://www.apollographql.com/docs/react/), there are two essential steps to setting up your application. First, you have to surround your application's root with two providers: `` and ``.

`` comes from our React.js-auth package, located at `@saleor/auth-sdk/react`, and it needs to be set up with the Saleor auth client instance.

The `` comes from `@apollo/client` and it needs the live GraphQL client instance, which is enhanced with the authenticated `fetch` that comes from the Saleor auth client.

Lastly, you must run the `useAuthChange` hook. This links the `onSignedOut` and `onSignedIn` events.

Let's look at an example:

```tsx
import { AppProps } from "next/app";
import { ApolloProvider, ApolloClient, InMemoryCache, createHttpLink } from "@apollo/client";
import { createSaleorAuthClient } from "@saleor/auth-sdk";
import { SaleorAuthProvider, useAuthChange } from "@saleor/auth-sdk/react";

const saleorApiUrl = "";

// Saleor Client
const saleorAuthClient = createSaleorAuthClient({ saleorApiUrl });

// Apollo Client
const httpLink = createHttpLink({
uri: saleorApiUrl,
fetch: saleorAuthClient.fetchWithAuth,
});

export const apolloClient = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
});

export default function App({ Component, pageProps }: AppProps) {
useAuthChange({
saleorApiUrl,
onSignedOut: () => apolloClient.resetStore(),
onSignedIn: () => {
apolloClient.refetchQueries({ include: "all" });
},
});

return (





);
}
```

Then, in your register, login and logout forms you can use the auth methods (`signIn`, `signOut`, `isAuthenticating`) provided by the `useSaleorAuthContext()`. For example, `signIn` is usually triggered when submitting the login form credentials.

```tsx
import React, { FormEvent } from "react";
import { useSaleorAuthContext } from "@saleor/auth-sdk/react";
import { gql, useQuery } from "@apollo/client";

const CurrentUserDocument = gql`
query CurrentUser {
me {
id
email
firstName
lastName
avatar {
url
alt
}
}
}
`;

export default function LoginPage() {
const { signIn, signOut } = useSaleorAuthContext();

const { data: currentUser, loading } = useQuery(CurrentUserDocument);

const submitHandler = async (event: FormEvent) => {
event.preventDefault();

const result = await signIn({
email: "[email protected]",
password: "admin",
});

if (result.data.tokenCreate.errors) {
// handle errors
}
};

if (loading) {
return

Loading...
;
}

return (

{currentUser?.me ? (
<>

Display user {JSON.stringify(currentUser)}

signOut()}>
Log Out

>
) : (


{/* You must connect your inputs to state or use a form library such as react-hook-form */}



Log In



)}

);
}
```

### Next.js (Pages Router) with [urql](https://formidable.com/open-source/urql/)

When using Next.js (Pages Router) along with [urql](https://formidable.com/open-source/urql/) client, there are two essential steps to setting up your application. First, you have to surround your application's root with two providers: `` and ``.

`` comes from our React.js-auth package, located at `@saleor/auth-sdk/react`, and it needs to be set up with the Saleor auth client.

The `` comes from `urql` and it needs the GraphQL client instance, which is enhanced with the authenticated `fetch` that comes from the Saleor auth client.

Lastly, you must run the `useAuthChange` hook. This links the `onSignedOut` and `onSignedIn` events and is meant to refresh the GraphQL store and in-flight active GraphQL queries.

Let's look at an example:

```tsx
import { AppProps } from "next/app";
import { Provider, cacheExchange, fetchExchange, ssrExchange } from "urql";
import { SaleorAuthProvider, useAuthChange } from "@saleor/auth-sdk/react";

const saleorApiUrl = "";

const saleorAuthClient = createSaleorAuthClient({ saleorApiUrl });

const makeUrqlClient = () =>
createClient({
url: saleorApiUrl,
fetch: saleorAuthClient.fetchWithAuth,
exchanges: [cacheExchange, fetchExchange],
});

export default function App({ Component, pageProps }: AppProps) {
// https://github.com/urql-graphql/urql/issues/297#issuecomment-504782794
const [urqlClient, setUrqlClient] = useState(makeUrqlClient());

useAuthChange({
saleorApiUrl,
onSignedOut: () => setUrqlClient(makeUrqlClient()),
onSignedIn: () => setUrqlClient(makeUrqlClient()),
});

return (





);
}
```

Then, in your register, login and logout forms you can use the auth methods (`signIn`, `signOut`) provided by the `useSaleorAuthContext()`. For example, `signIn` is usually triggered when submitting the login form credentials.

```tsx
import React, { FormEvent } from "react";
import { useSaleorAuthContext } from "@saleor/auth-sdk/react";
import { gql, useQuery } from "urql";

const CurrentUserDocument = gql`
query CurrentUser {
me {
id
email
firstName
lastName
avatar {
url
alt
}
}
}
`;

export default function LoginPage() {
const { signIn, signOut } = useSaleorAuthContext();

const [{ data: currentUser, fetching: loading }] = useQuery({
query: CurrentUserDocument,
pause: isAuthenticating,
});

const submitHandler = async (event: FormEvent) => {
event.preventDefault();

const result = await signIn({
email: "[email protected]",
password: "admin",
});

if (result.data.tokenCreate.errors) {
// handle errors
}
};

if (loading) {
return

Loading...
;
}

return (

{currentUser?.me ? (
<>

Display user {JSON.stringify(currentUser)}

signOut()}>
Log Out

>
) : (


{/* You must connect your inputs to state or use a form library such as react-hook-form */}



Log In



)}

);
}
```

### Next.js (Pages Router) with OpenID Connect

Setup `_app.tsx` as described above. In your login component trigger the external auth flow using the following code:

```tsx
import { useSaleorAuthContext, useSaleorExternalAuth } from "@saleor/auth-sdk/react";
import { ExternalProvider } from "@saleor/auth-sdk";
import Link from "next/link";
import { gql, useQuery } from "@apollo/client";

export default function Home() {
const {
loading: isLoadingCurrentUser,
error,
data,
} = useQuery(gql`
query CurrentUser {
me {
id
email
firstName
lastName
}
}
`);
const { authURL, loading: isLoadingExternalAuth } = useSaleorExternalAuth({
saleorApiUrl,
provider: ExternalProvider.OpenIDConnect,
redirectURL: "/api/auth/callback",
});

const { signOut } = useSaleorAuthContext();

if (isLoadingExternalAuth || isLoadingCurrentUser) {
return

Loading...
;
}

if (data?.me) {
return (


{JSON.stringify(data)}
signOut()}>Logout

);
}
if (authURL) {
return (

Login

);
}
return
Something went wrong
;
}
```

You also need to define the auth callback. In `pages/api/auth` create the `callback.ts` with the following content:

```ts
import { ExternalProvider, SaleorExternalAuth } from "@saleor/auth-sdk";
import { createSaleorExternalAuthHandler } from "@saleor/auth-sdk/next";

const externalAuth = new SaleorExternalAuth("", ExternalProvider.OpenIDConnect);

export default createSaleorExternalAuthHandler(externalAuth);
```

## FAQ

## How do I reset password?

The `SaleorAuthClient` class provides you with a reset password method. If the reset password mutation is successful, it will log you in automatically, just like after a regular sign-in. The [`onSignIn` method of `useAuthChange` hook](#how-do-i-tell-my-graphql-client-to-refresh-queries-on-signin--signout) will also be triggered.

```javascript
const { resetPassword } = useSaleorAuthContext();

const response = await resetPassword({
email: "[email protected]",
password: "newPassword",
token: "apiToken",
});
```