---
title: Open redirect in auth callback
description: Detects redirect targets taken from request parameters without validation.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/open-redirect
  md: >-
    https://shopify.dev/docs/apps/build/security/app-security-checks/open-redirect.md
---

# Open redirect in auth callback

Detects redirect targets taken from request parameters without validation.

| Detail | Value |
| - | - |
| Check ID | `OPEN_REDIRECT` |
| Severity | Medium |
| How it runs | Agent review |

***

## Vulnerable example

## app/routes/auth.callback.tsx

```tsx
import { redirect } from "react-router";
import type { LoaderFunctionArgs } from "react-router";


import { authenticate } from "../shopify.server";


export const loader = async ({ request }: LoaderFunctionArgs) => {
  await authenticate.admin(request);


  const returnTo = new URL(request.url).searchParams.get("return_to");


  // The destination is whatever the caller put in the URL, so the
  // app will bounce a freshly authenticated merchant to an
  // attacker's page.
  return redirect(returnTo ?? "/app");
};
```

***

## How to fix

Validate the redirect URL against an allowlist of permitted domains.

For more detail, see [Authentication and authorization](https://shopify.dev/docs/apps/build/authentication-authorization).

## app/routes/auth.callback.tsx

```tsx
import { redirect } from "react-router";
import type { LoaderFunctionArgs } from "react-router";


import { authenticate } from "../shopify.server";


const ALLOWED_PATHS = ["/app", "/app/settings", "/app/orders"];


export const loader = async ({ request }: LoaderFunctionArgs) => {
  await authenticate.admin(request);


  const returnTo = new URL(request.url).searchParams.get("return_to");


  // Allowlist the destination. Accepting only known in-app paths
  // also rules out protocol-relative targets such as
  // //evil.example.
  const destination = ALLOWED_PATHS.includes(returnTo ?? "")
    ? returnTo!
    : "/app";


  return redirect(destination);
};
```

***

## Related

* [`shopify app security check`](https://shopify.dev/docs/api/shopify-cli/app/app-security-check), the command that runs this check
* [All app security checks](https://shopify.dev/docs/apps/build/security/app-security-checks)

***
